catch assertion errors on win32
This commit is contained in:
parent
9c1f836ff2
commit
2cd046e1e8
@ -1,4 +1,5 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#define STBI_ASSERT(x)
|
#define STBI_ASSERT(x)
|
||||||
#define STBI_NO_SIMD
|
#define STBI_NO_SIMD
|
||||||
@ -20,6 +21,8 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
|||||||
unsigned char *img = stbi_load_from_memory(data, size, &x, &y, &channels, 4);
|
unsigned char *img = stbi_load_from_memory(data, size, &x, &y, &channels, 4);
|
||||||
|
|
||||||
free(img);
|
free(img);
|
||||||
|
|
||||||
|
// if (x > 10000) free(img); // free crash
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,334 +1,370 @@
|
|||||||
pub use crate::bolts::bindings::windows::win32::debug::EXCEPTION_POINTERS;
|
pub use crate::bolts::bindings::windows::win32::debug::EXCEPTION_POINTERS;
|
||||||
|
|
||||||
use crate::{bolts::bindings::windows::win32::debug::SetUnhandledExceptionFilter, Error};
|
use crate::{bolts::bindings::windows::win32::debug::SetUnhandledExceptionFilter, Error};
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
ptr::write_volatile,
|
ptr,
|
||||||
sync::atomic::{compiler_fence, Ordering},
|
ptr::write_volatile,
|
||||||
};
|
sync::atomic::{compiler_fence, Ordering},
|
||||||
use std::os::raw::{c_long, c_void};
|
};
|
||||||
|
use std::os::raw::{c_long, c_void};
|
||||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
|
||||||
|
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||||
//const EXCEPTION_CONTINUE_EXECUTION: c_long = -1;
|
|
||||||
//const EXCEPTION_CONTINUE_SEARCH: c_long = 0;
|
//const EXCEPTION_CONTINUE_EXECUTION: c_long = -1;
|
||||||
const EXCEPTION_EXECUTE_HANDLER: c_long = 1;
|
//const EXCEPTION_CONTINUE_SEARCH: c_long = 0;
|
||||||
|
const EXCEPTION_EXECUTE_HANDLER: c_long = 1;
|
||||||
// From https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L611
|
|
||||||
pub const STATUS_WAIT_0: u32 = 0x00000000;
|
// From https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-headers/crt/signal.h
|
||||||
pub const STATUS_ABANDONED_WAIT_0: u32 = 0x00000080;
|
pub const SIGINT: i32 = 2;
|
||||||
pub const STATUS_USER_APC: u32 = 0x000000C0;
|
pub const SIGILL: i32 = 4;
|
||||||
pub const STATUS_TIMEOUT: u32 = 0x00000102;
|
pub const SIGABRT_COMPAT: i32 = 6;
|
||||||
pub const STATUS_PENDING: u32 = 0x00000103;
|
pub const SIGFPE: i32 = 8;
|
||||||
pub const STATUS_SEGMENT_NOTIFICATION: u32 = 0x40000005;
|
pub const SIGSEGV: i32 = 11;
|
||||||
pub const STATUS_FATAL_APP_EXIT: u32 = 0x40000015;
|
pub const SIGTERM: i32 = 15;
|
||||||
pub const STATUS_GUARD_PAGE_VIOLATION: u32 = 0x80000001;
|
pub const SIGBREAK: i32 = 21;
|
||||||
pub const STATUS_DATATYPE_MISALIGNMENT: u32 = 0x80000002;
|
pub const SIGABRT: i32 = 22;
|
||||||
pub const STATUS_BREAKPOINT: u32 = 0x80000003;
|
pub const SIGABRT2: i32 = 22;
|
||||||
pub const STATUS_SINGLE_STEP: u32 = 0x80000004;
|
|
||||||
pub const STATUS_LONGJUMP: u32 = 0x80000026;
|
// From https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L611
|
||||||
pub const STATUS_UNWIND_CONSOLIDATE: u32 = 0x80000029;
|
pub const STATUS_WAIT_0: u32 = 0x00000000;
|
||||||
pub const STATUS_ACCESS_VIOLATION: u32 = 0xC0000005;
|
pub const STATUS_ABANDONED_WAIT_0: u32 = 0x00000080;
|
||||||
pub const STATUS_IN_PAGE_ERROR: u32 = 0xC0000006;
|
pub const STATUS_USER_APC: u32 = 0x000000C0;
|
||||||
pub const STATUS_INVALID_HANDLE: u32 = 0xC0000008;
|
pub const STATUS_TIMEOUT: u32 = 0x00000102;
|
||||||
pub const STATUS_NO_MEMORY: u32 = 0xC0000017;
|
pub const STATUS_PENDING: u32 = 0x00000103;
|
||||||
pub const STATUS_ILLEGAL_INSTRUCTION: u32 = 0xC000001D;
|
pub const STATUS_SEGMENT_NOTIFICATION: u32 = 0x40000005;
|
||||||
pub const STATUS_NONCONTINUABLE_EXCEPTION: u32 = 0xC0000025;
|
pub const STATUS_FATAL_APP_EXIT: u32 = 0x40000015;
|
||||||
pub const STATUS_INVALID_DISPOSITION: u32 = 0xC0000026;
|
pub const STATUS_GUARD_PAGE_VIOLATION: u32 = 0x80000001;
|
||||||
pub const STATUS_ARRAY_BOUNDS_EXCEEDED: u32 = 0xC000008C;
|
pub const STATUS_DATATYPE_MISALIGNMENT: u32 = 0x80000002;
|
||||||
pub const STATUS_FLOAT_DENORMAL_OPERAND: u32 = 0xC000008D;
|
pub const STATUS_BREAKPOINT: u32 = 0x80000003;
|
||||||
pub const STATUS_FLOAT_DIVIDE_BY_ZERO: u32 = 0xC000008E;
|
pub const STATUS_SINGLE_STEP: u32 = 0x80000004;
|
||||||
pub const STATUS_FLOAT_INEXACT_RESULT: u32 = 0xC000008F;
|
pub const STATUS_LONGJUMP: u32 = 0x80000026;
|
||||||
pub const STATUS_FLOAT_INVALID_OPERATION: u32 = 0xC0000090;
|
pub const STATUS_UNWIND_CONSOLIDATE: u32 = 0x80000029;
|
||||||
pub const STATUS_FLOAT_OVERFLOW: u32 = 0xC0000091;
|
pub const STATUS_ACCESS_VIOLATION: u32 = 0xC0000005;
|
||||||
pub const STATUS_FLOAT_STACK_CHECK: u32 = 0xC0000092;
|
pub const STATUS_IN_PAGE_ERROR: u32 = 0xC0000006;
|
||||||
pub const STATUS_FLOAT_UNDERFLOW: u32 = 0xC0000093;
|
pub const STATUS_INVALID_HANDLE: u32 = 0xC0000008;
|
||||||
pub const STATUS_INTEGER_DIVIDE_BY_ZERO: u32 = 0xC0000094;
|
pub const STATUS_NO_MEMORY: u32 = 0xC0000017;
|
||||||
pub const STATUS_INTEGER_OVERFLOW: u32 = 0xC0000095;
|
pub const STATUS_ILLEGAL_INSTRUCTION: u32 = 0xC000001D;
|
||||||
pub const STATUS_PRIVILEGED_INSTRUCTION: u32 = 0xC0000096;
|
pub const STATUS_NONCONTINUABLE_EXCEPTION: u32 = 0xC0000025;
|
||||||
pub const STATUS_STACK_OVERFLOW: u32 = 0xC00000FD;
|
pub const STATUS_INVALID_DISPOSITION: u32 = 0xC0000026;
|
||||||
pub const STATUS_DLL_NOT_FOUND: u32 = 0xC0000135;
|
pub const STATUS_ARRAY_BOUNDS_EXCEEDED: u32 = 0xC000008C;
|
||||||
pub const STATUS_ORDINAL_NOT_FOUND: u32 = 0xC0000138;
|
pub const STATUS_FLOAT_DENORMAL_OPERAND: u32 = 0xC000008D;
|
||||||
pub const STATUS_ENTRYPOINT_NOT_FOUND: u32 = 0xC0000139;
|
pub const STATUS_FLOAT_DIVIDE_BY_ZERO: u32 = 0xC000008E;
|
||||||
pub const STATUS_CONTROL_C_EXIT: u32 = 0xC000013A;
|
pub const STATUS_FLOAT_INEXACT_RESULT: u32 = 0xC000008F;
|
||||||
pub const STATUS_DLL_INIT_FAILED: u32 = 0xC0000142;
|
pub const STATUS_FLOAT_INVALID_OPERATION: u32 = 0xC0000090;
|
||||||
pub const STATUS_FLOAT_MULTIPLE_FAULTS: u32 = 0xC00002B4;
|
pub const STATUS_FLOAT_OVERFLOW: u32 = 0xC0000091;
|
||||||
pub const STATUS_FLOAT_MULTIPLE_TRAPS: u32 = 0xC00002B5;
|
pub const STATUS_FLOAT_STACK_CHECK: u32 = 0xC0000092;
|
||||||
pub const STATUS_REG_NAT_CONSUMPTION: u32 = 0xC00002C9;
|
pub const STATUS_FLOAT_UNDERFLOW: u32 = 0xC0000093;
|
||||||
pub const STATUS_HEAP_CORRUPTION: u32 = 0xC0000374;
|
pub const STATUS_INTEGER_DIVIDE_BY_ZERO: u32 = 0xC0000094;
|
||||||
pub const STATUS_STACK_BUFFER_OVERRUN: u32 = 0xC0000409;
|
pub const STATUS_INTEGER_OVERFLOW: u32 = 0xC0000095;
|
||||||
pub const STATUS_INVALID_CRUNTIME_PARAMETER: u32 = 0xC0000417;
|
pub const STATUS_PRIVILEGED_INSTRUCTION: u32 = 0xC0000096;
|
||||||
pub const STATUS_ASSERTION_FAILURE: u32 = 0xC0000420;
|
pub const STATUS_STACK_OVERFLOW: u32 = 0xC00000FD;
|
||||||
pub const STATUS_SXS_EARLY_DEACTIVATION: u32 = 0xC015000F;
|
pub const STATUS_DLL_NOT_FOUND: u32 = 0xC0000135;
|
||||||
pub const STATUS_SXS_INVALID_DEACTIVATION: u32 = 0xC0150010;
|
pub const STATUS_ORDINAL_NOT_FOUND: u32 = 0xC0000138;
|
||||||
|
pub const STATUS_ENTRYPOINT_NOT_FOUND: u32 = 0xC0000139;
|
||||||
#[derive(IntoPrimitive, TryFromPrimitive, Clone, Copy)]
|
pub const STATUS_CONTROL_C_EXIT: u32 = 0xC000013A;
|
||||||
#[repr(u32)]
|
pub const STATUS_DLL_INIT_FAILED: u32 = 0xC0000142;
|
||||||
pub enum ExceptionCode {
|
pub const STATUS_FLOAT_MULTIPLE_FAULTS: u32 = 0xC00002B4;
|
||||||
// From https://docs.microsoft.com/en-us/windows/win32/debug/getexceptioncode
|
pub const STATUS_FLOAT_MULTIPLE_TRAPS: u32 = 0xC00002B5;
|
||||||
AccessViolation = STATUS_ACCESS_VIOLATION,
|
pub const STATUS_REG_NAT_CONSUMPTION: u32 = 0xC00002C9;
|
||||||
ArrayBoundsExceeded = STATUS_ARRAY_BOUNDS_EXCEEDED,
|
pub const STATUS_HEAP_CORRUPTION: u32 = 0xC0000374;
|
||||||
Breakpoint = STATUS_BREAKPOINT,
|
pub const STATUS_STACK_BUFFER_OVERRUN: u32 = 0xC0000409;
|
||||||
DatatypeMisalignment = STATUS_DATATYPE_MISALIGNMENT,
|
pub const STATUS_INVALID_CRUNTIME_PARAMETER: u32 = 0xC0000417;
|
||||||
FltDenormalOperand = STATUS_FLOAT_DENORMAL_OPERAND,
|
pub const STATUS_ASSERTION_FAILURE: u32 = 0xC0000420;
|
||||||
FltDivideByZero = STATUS_FLOAT_DIVIDE_BY_ZERO,
|
pub const STATUS_SXS_EARLY_DEACTIVATION: u32 = 0xC015000F;
|
||||||
FltInexactResult = STATUS_FLOAT_INEXACT_RESULT,
|
pub const STATUS_SXS_INVALID_DEACTIVATION: u32 = 0xC0150010;
|
||||||
FltInvalidOperation = STATUS_FLOAT_INVALID_OPERATION,
|
|
||||||
FltOverflow = STATUS_FLOAT_OVERFLOW,
|
#[derive(IntoPrimitive, TryFromPrimitive, Clone, Copy)]
|
||||||
FltStackCheck = STATUS_FLOAT_STACK_CHECK,
|
#[repr(u32)]
|
||||||
FltUnderflow = STATUS_FLOAT_UNDERFLOW,
|
pub enum ExceptionCode {
|
||||||
GuardPageViolation = STATUS_GUARD_PAGE_VIOLATION,
|
// From https://docs.microsoft.com/en-us/windows/win32/debug/getexceptioncode
|
||||||
IllegalInstruction = STATUS_ILLEGAL_INSTRUCTION,
|
AccessViolation = STATUS_ACCESS_VIOLATION,
|
||||||
InPageError = STATUS_IN_PAGE_ERROR,
|
ArrayBoundsExceeded = STATUS_ARRAY_BOUNDS_EXCEEDED,
|
||||||
IntegerDivideByZero = STATUS_INTEGER_DIVIDE_BY_ZERO,
|
Breakpoint = STATUS_BREAKPOINT,
|
||||||
IntegerOverflow = STATUS_INTEGER_OVERFLOW,
|
DatatypeMisalignment = STATUS_DATATYPE_MISALIGNMENT,
|
||||||
InvalidDisposition = STATUS_INVALID_DISPOSITION,
|
FltDenormalOperand = STATUS_FLOAT_DENORMAL_OPERAND,
|
||||||
InvalidHandle = STATUS_INVALID_HANDLE,
|
FltDivideByZero = STATUS_FLOAT_DIVIDE_BY_ZERO,
|
||||||
NoncontinuableException = STATUS_NONCONTINUABLE_EXCEPTION,
|
FltInexactResult = STATUS_FLOAT_INEXACT_RESULT,
|
||||||
PrivilegedInstruction = STATUS_PRIVILEGED_INSTRUCTION,
|
FltInvalidOperation = STATUS_FLOAT_INVALID_OPERATION,
|
||||||
SingleStep = STATUS_SINGLE_STEP,
|
FltOverflow = STATUS_FLOAT_OVERFLOW,
|
||||||
StackOverflow = STATUS_STACK_OVERFLOW,
|
FltStackCheck = STATUS_FLOAT_STACK_CHECK,
|
||||||
UnwindConsolidate = STATUS_UNWIND_CONSOLIDATE,
|
FltUnderflow = STATUS_FLOAT_UNDERFLOW,
|
||||||
// Addition exceptions
|
GuardPageViolation = STATUS_GUARD_PAGE_VIOLATION,
|
||||||
Wait0 = STATUS_WAIT_0,
|
IllegalInstruction = STATUS_ILLEGAL_INSTRUCTION,
|
||||||
AbandonedWait0 = STATUS_ABANDONED_WAIT_0,
|
InPageError = STATUS_IN_PAGE_ERROR,
|
||||||
UserAPC = STATUS_USER_APC,
|
IntegerDivideByZero = STATUS_INTEGER_DIVIDE_BY_ZERO,
|
||||||
Timeout = STATUS_TIMEOUT,
|
IntegerOverflow = STATUS_INTEGER_OVERFLOW,
|
||||||
Pending = STATUS_PENDING,
|
InvalidDisposition = STATUS_INVALID_DISPOSITION,
|
||||||
SegmentNotification = STATUS_SEGMENT_NOTIFICATION,
|
InvalidHandle = STATUS_INVALID_HANDLE,
|
||||||
FatalAppExit = STATUS_FATAL_APP_EXIT,
|
NoncontinuableException = STATUS_NONCONTINUABLE_EXCEPTION,
|
||||||
Longjump = STATUS_LONGJUMP,
|
PrivilegedInstruction = STATUS_PRIVILEGED_INSTRUCTION,
|
||||||
DLLNotFound = STATUS_DLL_NOT_FOUND,
|
SingleStep = STATUS_SINGLE_STEP,
|
||||||
OrdinalNotFound = STATUS_ORDINAL_NOT_FOUND,
|
StackOverflow = STATUS_STACK_OVERFLOW,
|
||||||
EntryPointNotFound = STATUS_ENTRYPOINT_NOT_FOUND,
|
UnwindConsolidate = STATUS_UNWIND_CONSOLIDATE,
|
||||||
ControlCExit = STATUS_CONTROL_C_EXIT,
|
// Addition exceptions
|
||||||
DllInitFailed = STATUS_DLL_INIT_FAILED,
|
Wait0 = STATUS_WAIT_0,
|
||||||
FltMultipleFaults = STATUS_FLOAT_MULTIPLE_FAULTS,
|
AbandonedWait0 = STATUS_ABANDONED_WAIT_0,
|
||||||
FltMultipleTraps = STATUS_FLOAT_MULTIPLE_TRAPS,
|
UserAPC = STATUS_USER_APC,
|
||||||
RegNatConsumption = STATUS_REG_NAT_CONSUMPTION,
|
Timeout = STATUS_TIMEOUT,
|
||||||
HeapCorruption = STATUS_HEAP_CORRUPTION,
|
Pending = STATUS_PENDING,
|
||||||
StackBufferOverrun = STATUS_STACK_BUFFER_OVERRUN,
|
SegmentNotification = STATUS_SEGMENT_NOTIFICATION,
|
||||||
InvalidCRuntimeParameter = STATUS_INVALID_CRUNTIME_PARAMETER,
|
FatalAppExit = STATUS_FATAL_APP_EXIT,
|
||||||
AssertionFailure = STATUS_ASSERTION_FAILURE,
|
Longjump = STATUS_LONGJUMP,
|
||||||
SXSEarlyDeactivation = STATUS_SXS_EARLY_DEACTIVATION,
|
DLLNotFound = STATUS_DLL_NOT_FOUND,
|
||||||
SXSInvalidDeactivation = STATUS_SXS_INVALID_DEACTIVATION,
|
OrdinalNotFound = STATUS_ORDINAL_NOT_FOUND,
|
||||||
}
|
EntryPointNotFound = STATUS_ENTRYPOINT_NOT_FOUND,
|
||||||
|
ControlCExit = STATUS_CONTROL_C_EXIT,
|
||||||
pub static CRASH_EXCEPTIONS: &[ExceptionCode] = &[
|
DllInitFailed = STATUS_DLL_INIT_FAILED,
|
||||||
ExceptionCode::AccessViolation,
|
FltMultipleFaults = STATUS_FLOAT_MULTIPLE_FAULTS,
|
||||||
ExceptionCode::ArrayBoundsExceeded,
|
FltMultipleTraps = STATUS_FLOAT_MULTIPLE_TRAPS,
|
||||||
ExceptionCode::FltDivideByZero,
|
RegNatConsumption = STATUS_REG_NAT_CONSUMPTION,
|
||||||
ExceptionCode::GuardPageViolation,
|
HeapCorruption = STATUS_HEAP_CORRUPTION,
|
||||||
ExceptionCode::IllegalInstruction,
|
StackBufferOverrun = STATUS_STACK_BUFFER_OVERRUN,
|
||||||
ExceptionCode::InPageError,
|
InvalidCRuntimeParameter = STATUS_INVALID_CRUNTIME_PARAMETER,
|
||||||
ExceptionCode::IntegerDivideByZero,
|
AssertionFailure = STATUS_ASSERTION_FAILURE,
|
||||||
ExceptionCode::InvalidHandle,
|
SXSEarlyDeactivation = STATUS_SXS_EARLY_DEACTIVATION,
|
||||||
ExceptionCode::NoncontinuableException,
|
SXSInvalidDeactivation = STATUS_SXS_INVALID_DEACTIVATION,
|
||||||
ExceptionCode::PrivilegedInstruction,
|
}
|
||||||
ExceptionCode::StackOverflow,
|
|
||||||
ExceptionCode::HeapCorruption,
|
pub static CRASH_EXCEPTIONS: &[ExceptionCode] = &[
|
||||||
ExceptionCode::StackBufferOverrun,
|
ExceptionCode::AccessViolation,
|
||||||
ExceptionCode::AssertionFailure,
|
ExceptionCode::ArrayBoundsExceeded,
|
||||||
];
|
ExceptionCode::FltDivideByZero,
|
||||||
|
ExceptionCode::GuardPageViolation,
|
||||||
impl PartialEq for ExceptionCode {
|
ExceptionCode::IllegalInstruction,
|
||||||
fn eq(&self, other: &Self) -> bool {
|
ExceptionCode::InPageError,
|
||||||
*self as u32 == *other as u32
|
ExceptionCode::IntegerDivideByZero,
|
||||||
}
|
ExceptionCode::InvalidHandle,
|
||||||
}
|
ExceptionCode::NoncontinuableException,
|
||||||
|
ExceptionCode::PrivilegedInstruction,
|
||||||
impl Eq for ExceptionCode {}
|
ExceptionCode::StackOverflow,
|
||||||
|
ExceptionCode::HeapCorruption,
|
||||||
unsafe impl Sync for ExceptionCode {}
|
ExceptionCode::StackBufferOverrun,
|
||||||
|
ExceptionCode::AssertionFailure,
|
||||||
impl Display for ExceptionCode {
|
];
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
|
|
||||||
match self {
|
impl PartialEq for ExceptionCode {
|
||||||
ExceptionCode::AccessViolation => write!(f, "STATUS_ACCESS_VIOLATION")?,
|
fn eq(&self, other: &Self) -> bool {
|
||||||
ExceptionCode::ArrayBoundsExceeded => write!(f, "STATUS_ARRAY_BOUNDS_EXCEEDED")?,
|
*self as u32 == *other as u32
|
||||||
ExceptionCode::Breakpoint => write!(f, "STATUS_BREAKPOINT")?,
|
}
|
||||||
ExceptionCode::DatatypeMisalignment => write!(f, "STATUS_DATATYPE_MISALIGNMENT")?,
|
}
|
||||||
ExceptionCode::FltDenormalOperand => write!(f, "STATUS_FLOAT_DENORMAL_OPERAND")?,
|
|
||||||
ExceptionCode::FltDivideByZero => write!(f, "STATUS_FLOAT_DIVIDE_BY_ZERO")?,
|
impl Eq for ExceptionCode {}
|
||||||
ExceptionCode::FltInexactResult => write!(f, "STATUS_FLOAT_INEXACT_RESULT")?,
|
|
||||||
ExceptionCode::FltInvalidOperation => write!(f, "STATUS_FLOAT_INVALID_OPERATION")?,
|
unsafe impl Sync for ExceptionCode {}
|
||||||
ExceptionCode::FltOverflow => write!(f, "STATUS_FLOAT_OVERFLOW")?,
|
|
||||||
ExceptionCode::FltStackCheck => write!(f, "STATUS_FLOAT_STACK_CHECK")?,
|
impl Display for ExceptionCode {
|
||||||
ExceptionCode::FltUnderflow => write!(f, "STATUS_FLOAT_UNDERFLOW")?,
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
ExceptionCode::GuardPageViolation => write!(f, "STATUS_GUARD_PAGE_VIOLATION")?,
|
match self {
|
||||||
ExceptionCode::IllegalInstruction => write!(f, "STATUS_ILLEGAL_INSTRUCTION")?,
|
ExceptionCode::AccessViolation => write!(f, "STATUS_ACCESS_VIOLATION")?,
|
||||||
ExceptionCode::InPageError => write!(f, "STATUS_IN_PAGE_ERROR")?,
|
ExceptionCode::ArrayBoundsExceeded => write!(f, "STATUS_ARRAY_BOUNDS_EXCEEDED")?,
|
||||||
ExceptionCode::IntegerDivideByZero => write!(f, "STATUS_INTEGER_DIVIDE_BY_ZERO")?,
|
ExceptionCode::Breakpoint => write!(f, "STATUS_BREAKPOINT")?,
|
||||||
ExceptionCode::IntegerOverflow => write!(f, "STATUS_INTEGER_OVERFLOW")?,
|
ExceptionCode::DatatypeMisalignment => write!(f, "STATUS_DATATYPE_MISALIGNMENT")?,
|
||||||
ExceptionCode::InvalidDisposition => write!(f, "STATUS_INVALID_DISPOSITION")?,
|
ExceptionCode::FltDenormalOperand => write!(f, "STATUS_FLOAT_DENORMAL_OPERAND")?,
|
||||||
ExceptionCode::InvalidHandle => write!(f, "STATUS_INVALID_HANDLE")?,
|
ExceptionCode::FltDivideByZero => write!(f, "STATUS_FLOAT_DIVIDE_BY_ZERO")?,
|
||||||
ExceptionCode::NoncontinuableException => write!(f, "STATUS_NONCONTINUABLE_EXCEPTION")?,
|
ExceptionCode::FltInexactResult => write!(f, "STATUS_FLOAT_INEXACT_RESULT")?,
|
||||||
ExceptionCode::PrivilegedInstruction => write!(f, "STATUS_PRIVILEGED_INSTRUCTION")?,
|
ExceptionCode::FltInvalidOperation => write!(f, "STATUS_FLOAT_INVALID_OPERATION")?,
|
||||||
ExceptionCode::SingleStep => write!(f, "STATUS_SINGLE_STEP")?,
|
ExceptionCode::FltOverflow => write!(f, "STATUS_FLOAT_OVERFLOW")?,
|
||||||
ExceptionCode::StackOverflow => write!(f, "STATUS_STACK_OVERFLOW")?,
|
ExceptionCode::FltStackCheck => write!(f, "STATUS_FLOAT_STACK_CHECK")?,
|
||||||
ExceptionCode::UnwindConsolidate => write!(f, "STATUS_UNWIND_CONSOLIDATE")?,
|
ExceptionCode::FltUnderflow => write!(f, "STATUS_FLOAT_UNDERFLOW")?,
|
||||||
ExceptionCode::Wait0 => write!(f, "STATUS_WAIT_0")?,
|
ExceptionCode::GuardPageViolation => write!(f, "STATUS_GUARD_PAGE_VIOLATION")?,
|
||||||
ExceptionCode::AbandonedWait0 => write!(f, "STATUS_ABANDONED_WAIT_0")?,
|
ExceptionCode::IllegalInstruction => write!(f, "STATUS_ILLEGAL_INSTRUCTION")?,
|
||||||
ExceptionCode::UserAPC => write!(f, "STATUS_USER_APC")?,
|
ExceptionCode::InPageError => write!(f, "STATUS_IN_PAGE_ERROR")?,
|
||||||
ExceptionCode::Timeout => write!(f, "STATUS_TIMEOUT")?,
|
ExceptionCode::IntegerDivideByZero => write!(f, "STATUS_INTEGER_DIVIDE_BY_ZERO")?,
|
||||||
ExceptionCode::Pending => write!(f, "STATUS_PENDING")?,
|
ExceptionCode::IntegerOverflow => write!(f, "STATUS_INTEGER_OVERFLOW")?,
|
||||||
ExceptionCode::SegmentNotification => write!(f, "STATUS_SEGMENT_NOTIFICATION")?,
|
ExceptionCode::InvalidDisposition => write!(f, "STATUS_INVALID_DISPOSITION")?,
|
||||||
ExceptionCode::FatalAppExit => write!(f, "STATUS_FATAL_APP_EXIT")?,
|
ExceptionCode::InvalidHandle => write!(f, "STATUS_INVALID_HANDLE")?,
|
||||||
ExceptionCode::Longjump => write!(f, "STATUS_LONGJUMP")?,
|
ExceptionCode::NoncontinuableException => write!(f, "STATUS_NONCONTINUABLE_EXCEPTION")?,
|
||||||
ExceptionCode::DLLNotFound => write!(f, "STATUS_DLL_NOT_FOUND")?,
|
ExceptionCode::PrivilegedInstruction => write!(f, "STATUS_PRIVILEGED_INSTRUCTION")?,
|
||||||
ExceptionCode::OrdinalNotFound => write!(f, "STATUS_ORDINAL_NOT_FOUND")?,
|
ExceptionCode::SingleStep => write!(f, "STATUS_SINGLE_STEP")?,
|
||||||
ExceptionCode::EntryPointNotFound => write!(f, "STATUS_ENTRYPOINT_NOT_FOUND")?,
|
ExceptionCode::StackOverflow => write!(f, "STATUS_STACK_OVERFLOW")?,
|
||||||
ExceptionCode::ControlCExit => write!(f, "STATUS_CONTROL_C_EXIT")?,
|
ExceptionCode::UnwindConsolidate => write!(f, "STATUS_UNWIND_CONSOLIDATE")?,
|
||||||
ExceptionCode::DllInitFailed => write!(f, "STATUS_DLL_INIT_FAILED")?,
|
ExceptionCode::Wait0 => write!(f, "STATUS_WAIT_0")?,
|
||||||
ExceptionCode::FltMultipleFaults => write!(f, "STATUS_FLOAT_MULTIPLE_FAULTS")?,
|
ExceptionCode::AbandonedWait0 => write!(f, "STATUS_ABANDONED_WAIT_0")?,
|
||||||
ExceptionCode::FltMultipleTraps => write!(f, "STATUS_FLOAT_MULTIPLE_TRAPS")?,
|
ExceptionCode::UserAPC => write!(f, "STATUS_USER_APC")?,
|
||||||
ExceptionCode::RegNatConsumption => write!(f, "STATUS_REG_NAT_CONSUMPTION")?,
|
ExceptionCode::Timeout => write!(f, "STATUS_TIMEOUT")?,
|
||||||
ExceptionCode::HeapCorruption => write!(f, "STATUS_HEAP_CORRUPTION")?,
|
ExceptionCode::Pending => write!(f, "STATUS_PENDING")?,
|
||||||
ExceptionCode::StackBufferOverrun => write!(f, "STATUS_STACK_BUFFER_OVERRUN")?,
|
ExceptionCode::SegmentNotification => write!(f, "STATUS_SEGMENT_NOTIFICATION")?,
|
||||||
ExceptionCode::InvalidCRuntimeParameter => {
|
ExceptionCode::FatalAppExit => write!(f, "STATUS_FATAL_APP_EXIT")?,
|
||||||
write!(f, "STATUS_INVALID_CRUNTIME_PARAMETER")?
|
ExceptionCode::Longjump => write!(f, "STATUS_LONGJUMP")?,
|
||||||
}
|
ExceptionCode::DLLNotFound => write!(f, "STATUS_DLL_NOT_FOUND")?,
|
||||||
ExceptionCode::AssertionFailure => write!(f, "STATUS_ASSERTION_FAILURE")?,
|
ExceptionCode::OrdinalNotFound => write!(f, "STATUS_ORDINAL_NOT_FOUND")?,
|
||||||
ExceptionCode::SXSEarlyDeactivation => write!(f, "STATUS_SXS_EARLY_DEACTIVATION")?,
|
ExceptionCode::EntryPointNotFound => write!(f, "STATUS_ENTRYPOINT_NOT_FOUND")?,
|
||||||
ExceptionCode::SXSInvalidDeactivation => write!(f, "STATUS_SXS_INVALID_DEACTIVATION")?,
|
ExceptionCode::ControlCExit => write!(f, "STATUS_CONTROL_C_EXIT")?,
|
||||||
};
|
ExceptionCode::DllInitFailed => write!(f, "STATUS_DLL_INIT_FAILED")?,
|
||||||
|
ExceptionCode::FltMultipleFaults => write!(f, "STATUS_FLOAT_MULTIPLE_FAULTS")?,
|
||||||
Ok(())
|
ExceptionCode::FltMultipleTraps => write!(f, "STATUS_FLOAT_MULTIPLE_TRAPS")?,
|
||||||
}
|
ExceptionCode::RegNatConsumption => write!(f, "STATUS_REG_NAT_CONSUMPTION")?,
|
||||||
}
|
ExceptionCode::HeapCorruption => write!(f, "STATUS_HEAP_CORRUPTION")?,
|
||||||
|
ExceptionCode::StackBufferOverrun => write!(f, "STATUS_STACK_BUFFER_OVERRUN")?,
|
||||||
pub static EXCEPTION_CODES_MAPPING: [ExceptionCode; 45] = [
|
ExceptionCode::InvalidCRuntimeParameter => {
|
||||||
ExceptionCode::AccessViolation,
|
write!(f, "STATUS_INVALID_CRUNTIME_PARAMETER")?
|
||||||
ExceptionCode::ArrayBoundsExceeded,
|
}
|
||||||
ExceptionCode::Breakpoint,
|
ExceptionCode::AssertionFailure => write!(f, "STATUS_ASSERTION_FAILURE")?,
|
||||||
ExceptionCode::DatatypeMisalignment,
|
ExceptionCode::SXSEarlyDeactivation => write!(f, "STATUS_SXS_EARLY_DEACTIVATION")?,
|
||||||
ExceptionCode::FltDenormalOperand,
|
ExceptionCode::SXSInvalidDeactivation => write!(f, "STATUS_SXS_INVALID_DEACTIVATION")?,
|
||||||
ExceptionCode::FltDivideByZero,
|
};
|
||||||
ExceptionCode::FltInexactResult,
|
|
||||||
ExceptionCode::FltInvalidOperation,
|
Ok(())
|
||||||
ExceptionCode::FltOverflow,
|
}
|
||||||
ExceptionCode::FltStackCheck,
|
}
|
||||||
ExceptionCode::FltUnderflow,
|
|
||||||
ExceptionCode::GuardPageViolation,
|
pub static EXCEPTION_CODES_MAPPING: [ExceptionCode; 45] = [
|
||||||
ExceptionCode::IllegalInstruction,
|
ExceptionCode::AccessViolation,
|
||||||
ExceptionCode::InPageError,
|
ExceptionCode::ArrayBoundsExceeded,
|
||||||
ExceptionCode::IntegerDivideByZero,
|
ExceptionCode::Breakpoint,
|
||||||
ExceptionCode::IntegerOverflow,
|
ExceptionCode::DatatypeMisalignment,
|
||||||
ExceptionCode::InvalidDisposition,
|
ExceptionCode::FltDenormalOperand,
|
||||||
ExceptionCode::InvalidHandle,
|
ExceptionCode::FltDivideByZero,
|
||||||
ExceptionCode::NoncontinuableException,
|
ExceptionCode::FltInexactResult,
|
||||||
ExceptionCode::PrivilegedInstruction,
|
ExceptionCode::FltInvalidOperation,
|
||||||
ExceptionCode::SingleStep,
|
ExceptionCode::FltOverflow,
|
||||||
ExceptionCode::StackOverflow,
|
ExceptionCode::FltStackCheck,
|
||||||
ExceptionCode::UnwindConsolidate,
|
ExceptionCode::FltUnderflow,
|
||||||
ExceptionCode::Wait0,
|
ExceptionCode::GuardPageViolation,
|
||||||
ExceptionCode::AbandonedWait0,
|
ExceptionCode::IllegalInstruction,
|
||||||
ExceptionCode::UserAPC,
|
ExceptionCode::InPageError,
|
||||||
ExceptionCode::Timeout,
|
ExceptionCode::IntegerDivideByZero,
|
||||||
ExceptionCode::Pending,
|
ExceptionCode::IntegerOverflow,
|
||||||
ExceptionCode::SegmentNotification,
|
ExceptionCode::InvalidDisposition,
|
||||||
ExceptionCode::FatalAppExit,
|
ExceptionCode::InvalidHandle,
|
||||||
ExceptionCode::Longjump,
|
ExceptionCode::NoncontinuableException,
|
||||||
ExceptionCode::DLLNotFound,
|
ExceptionCode::PrivilegedInstruction,
|
||||||
ExceptionCode::OrdinalNotFound,
|
ExceptionCode::SingleStep,
|
||||||
ExceptionCode::EntryPointNotFound,
|
ExceptionCode::StackOverflow,
|
||||||
ExceptionCode::ControlCExit,
|
ExceptionCode::UnwindConsolidate,
|
||||||
ExceptionCode::DllInitFailed,
|
ExceptionCode::Wait0,
|
||||||
ExceptionCode::FltMultipleFaults,
|
ExceptionCode::AbandonedWait0,
|
||||||
ExceptionCode::FltMultipleTraps,
|
ExceptionCode::UserAPC,
|
||||||
ExceptionCode::RegNatConsumption,
|
ExceptionCode::Timeout,
|
||||||
ExceptionCode::HeapCorruption,
|
ExceptionCode::Pending,
|
||||||
ExceptionCode::StackBufferOverrun,
|
ExceptionCode::SegmentNotification,
|
||||||
ExceptionCode::InvalidCRuntimeParameter,
|
ExceptionCode::FatalAppExit,
|
||||||
ExceptionCode::AssertionFailure,
|
ExceptionCode::Longjump,
|
||||||
ExceptionCode::SXSEarlyDeactivation,
|
ExceptionCode::DLLNotFound,
|
||||||
ExceptionCode::SXSInvalidDeactivation,
|
ExceptionCode::OrdinalNotFound,
|
||||||
];
|
ExceptionCode::EntryPointNotFound,
|
||||||
|
ExceptionCode::ControlCExit,
|
||||||
pub trait Handler {
|
ExceptionCode::DllInitFailed,
|
||||||
/// Handle an exception
|
ExceptionCode::FltMultipleFaults,
|
||||||
fn handle(
|
ExceptionCode::FltMultipleTraps,
|
||||||
&mut self,
|
ExceptionCode::RegNatConsumption,
|
||||||
exception_code: ExceptionCode,
|
ExceptionCode::HeapCorruption,
|
||||||
exception_pointers: *mut EXCEPTION_POINTERS,
|
ExceptionCode::StackBufferOverrun,
|
||||||
);
|
ExceptionCode::InvalidCRuntimeParameter,
|
||||||
/// Return a list of exceptions to handle
|
ExceptionCode::AssertionFailure,
|
||||||
fn exceptions(&self) -> Vec<ExceptionCode>;
|
ExceptionCode::SXSEarlyDeactivation,
|
||||||
}
|
ExceptionCode::SXSInvalidDeactivation,
|
||||||
|
];
|
||||||
struct HandlerHolder {
|
|
||||||
handler: UnsafeCell<*mut dyn Handler>,
|
pub trait Handler {
|
||||||
}
|
/// Handle an exception
|
||||||
|
fn handle(
|
||||||
unsafe impl Send for HandlerHolder {}
|
&mut self,
|
||||||
|
exception_code: ExceptionCode,
|
||||||
/// Keep track of which handler is registered for which exception
|
exception_pointers: *mut EXCEPTION_POINTERS,
|
||||||
static mut EXCEPTION_HANDLERS: [Option<HandlerHolder>; 64] = [
|
);
|
||||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
/// Return a list of exceptions to handle
|
||||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
fn exceptions(&self) -> Vec<ExceptionCode>;
|
||||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
}
|
||||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
|
||||||
];
|
struct HandlerHolder {
|
||||||
|
handler: UnsafeCell<*mut dyn Handler>,
|
||||||
type NativeHandlerType = extern "system" fn(*mut EXCEPTION_POINTERS) -> c_long;
|
}
|
||||||
static mut PREVIOUS_HANDLER: Option<NativeHandlerType> = None;
|
|
||||||
|
unsafe impl Send for HandlerHolder {}
|
||||||
/// Internal function that is being called whenever an exception arrives (stdcall).
|
|
||||||
unsafe extern "system" fn handle_exception(exception_pointers: *mut EXCEPTION_POINTERS) -> c_long {
|
/// Keep track of which handler is registered for which exception
|
||||||
let code = exception_pointers
|
static mut EXCEPTION_HANDLERS: [Option<HandlerHolder>; 64] = [
|
||||||
.as_mut()
|
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||||
.unwrap()
|
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||||
.exception_record
|
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||||
.as_mut()
|
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||||
.unwrap()
|
];
|
||||||
.exception_code;
|
|
||||||
let exception_code = ExceptionCode::try_from(code).unwrap();
|
unsafe fn internal_handle_exception(
|
||||||
let index = EXCEPTION_CODES_MAPPING
|
exception_code: ExceptionCode,
|
||||||
.iter()
|
exception_pointers: *mut EXCEPTION_POINTERS,
|
||||||
.position(|x| *x == exception_code)
|
) -> i32 {
|
||||||
.unwrap();
|
let index = EXCEPTION_CODES_MAPPING
|
||||||
let ret = match &EXCEPTION_HANDLERS[index] {
|
.iter()
|
||||||
Some(handler_holder) => {
|
.position(|x| *x == exception_code)
|
||||||
let handler = &mut **handler_holder.handler.get();
|
.unwrap();
|
||||||
handler.handle(exception_code, exception_pointers);
|
match &EXCEPTION_HANDLERS[index] {
|
||||||
EXCEPTION_EXECUTE_HANDLER
|
Some(handler_holder) => {
|
||||||
}
|
let handler = &mut **handler_holder.handler.get();
|
||||||
None => EXCEPTION_EXECUTE_HANDLER,
|
handler.handle(exception_code, exception_pointers);
|
||||||
};
|
EXCEPTION_EXECUTE_HANDLER
|
||||||
if let Some(prev_handler) = PREVIOUS_HANDLER {
|
}
|
||||||
prev_handler(exception_pointers)
|
None => EXCEPTION_EXECUTE_HANDLER,
|
||||||
} else {
|
}
|
||||||
ret
|
}
|
||||||
}
|
|
||||||
}
|
type NativeHandlerType = extern "system" fn(*mut EXCEPTION_POINTERS) -> c_long;
|
||||||
|
static mut PREVIOUS_HANDLER: Option<NativeHandlerType> = None;
|
||||||
/// Setup Win32 exception handlers in a somewhat rusty way.
|
|
||||||
/// # Safety
|
/// Internal function that is being called whenever an exception arrives (stdcall).
|
||||||
/// Exception handlers are usually ugly, handle with care!
|
unsafe extern "system" fn handle_exception(exception_pointers: *mut EXCEPTION_POINTERS) -> c_long {
|
||||||
pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> {
|
let code = exception_pointers
|
||||||
let exceptions = handler.exceptions();
|
.as_mut()
|
||||||
for exception_code in exceptions {
|
.unwrap()
|
||||||
let index = EXCEPTION_CODES_MAPPING
|
.exception_record
|
||||||
.iter()
|
.as_mut()
|
||||||
.position(|x| *x == exception_code)
|
.unwrap()
|
||||||
.unwrap();
|
.exception_code;
|
||||||
write_volatile(
|
let exception_code = ExceptionCode::try_from(code).unwrap();
|
||||||
&mut EXCEPTION_HANDLERS[index],
|
// println!("Received {}", exception_code);
|
||||||
Some(HandlerHolder {
|
let ret = internal_handle_exception(exception_code, exception_pointers);
|
||||||
handler: UnsafeCell::new(handler as *mut dyn Handler),
|
if let Some(prev_handler) = PREVIOUS_HANDLER {
|
||||||
}),
|
prev_handler(exception_pointers)
|
||||||
);
|
} else {
|
||||||
}
|
ret
|
||||||
compiler_fence(Ordering::SeqCst);
|
}
|
||||||
|
}
|
||||||
if let Some(prev) = SetUnhandledExceptionFilter(Some(core::mem::transmute(
|
|
||||||
handle_exception as *const c_void,
|
type NativeSignalHandlerType = unsafe extern "C" fn(i32);
|
||||||
))) {
|
extern "C" {
|
||||||
PREVIOUS_HANDLER = Some(core::mem::transmute(prev as *const c_void));
|
fn signal(signum: i32, func: NativeSignalHandlerType) -> *const c_void;
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
unsafe extern "C" fn handle_signal(_signum: i32) {
|
||||||
|
// println!("Received signal {}", _signum);
|
||||||
|
internal_handle_exception(ExceptionCode::AssertionFailure, ptr::null_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Setup Win32 exception handlers in a somewhat rusty way.
|
||||||
|
/// # Safety
|
||||||
|
/// Exception handlers are usually ugly, handle with care!
|
||||||
|
pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> {
|
||||||
|
let exceptions = handler.exceptions();
|
||||||
|
let mut catch_assertions = false;
|
||||||
|
for exception_code in exceptions {
|
||||||
|
if exception_code == ExceptionCode::AssertionFailure {
|
||||||
|
catch_assertions = true;
|
||||||
|
}
|
||||||
|
let index = EXCEPTION_CODES_MAPPING
|
||||||
|
.iter()
|
||||||
|
.position(|x| *x == exception_code)
|
||||||
|
.unwrap();
|
||||||
|
write_volatile(
|
||||||
|
&mut EXCEPTION_HANDLERS[index],
|
||||||
|
Some(HandlerHolder {
|
||||||
|
handler: UnsafeCell::new(handler as *mut dyn Handler),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
if catch_assertions {
|
||||||
|
signal(SIGABRT, handle_signal);
|
||||||
|
}
|
||||||
|
if let Some(prev) = SetUnhandledExceptionFilter(Some(core::mem::transmute(
|
||||||
|
handle_exception as *const c_void,
|
||||||
|
))) {
|
||||||
|
PREVIOUS_HANDLER = Some(core::mem::transmute(prev as *const c_void));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user