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
|
||||||
@ -21,5 +22,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
|||||||
|
|
||||||
free(img);
|
free(img);
|
||||||
|
|
||||||
|
// if (x > 10000) free(img); // free crash
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use core::{
|
|||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
convert::TryFrom,
|
convert::TryFrom,
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
|
ptr,
|
||||||
ptr::write_volatile,
|
ptr::write_volatile,
|
||||||
sync::atomic::{compiler_fence, Ordering},
|
sync::atomic::{compiler_fence, Ordering},
|
||||||
};
|
};
|
||||||
@ -18,6 +19,17 @@ use num_enum::{IntoPrimitive, TryFromPrimitive};
|
|||||||
//const EXCEPTION_CONTINUE_SEARCH: c_long = 0;
|
//const EXCEPTION_CONTINUE_SEARCH: c_long = 0;
|
||||||
const EXCEPTION_EXECUTE_HANDLER: c_long = 1;
|
const EXCEPTION_EXECUTE_HANDLER: c_long = 1;
|
||||||
|
|
||||||
|
// From https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-headers/crt/signal.h
|
||||||
|
pub const SIGINT: i32 = 2;
|
||||||
|
pub const SIGILL: i32 = 4;
|
||||||
|
pub const SIGABRT_COMPAT: i32 = 6;
|
||||||
|
pub const SIGFPE: i32 = 8;
|
||||||
|
pub const SIGSEGV: i32 = 11;
|
||||||
|
pub const SIGTERM: i32 = 15;
|
||||||
|
pub const SIGBREAK: i32 = 21;
|
||||||
|
pub const SIGABRT: i32 = 22;
|
||||||
|
pub const SIGABRT2: i32 = 22;
|
||||||
|
|
||||||
// From https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L611
|
// From https://github.com/wine-mirror/wine/blob/master/include/winnt.h#L611
|
||||||
pub const STATUS_WAIT_0: u32 = 0x00000000;
|
pub const STATUS_WAIT_0: u32 = 0x00000000;
|
||||||
pub const STATUS_ABANDONED_WAIT_0: u32 = 0x00000080;
|
pub const STATUS_ABANDONED_WAIT_0: u32 = 0x00000080;
|
||||||
@ -274,6 +286,24 @@ static mut EXCEPTION_HANDLERS: [Option<HandlerHolder>; 64] = [
|
|||||||
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,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
unsafe fn internal_handle_exception(
|
||||||
|
exception_code: ExceptionCode,
|
||||||
|
exception_pointers: *mut EXCEPTION_POINTERS,
|
||||||
|
) -> i32 {
|
||||||
|
let index = EXCEPTION_CODES_MAPPING
|
||||||
|
.iter()
|
||||||
|
.position(|x| *x == exception_code)
|
||||||
|
.unwrap();
|
||||||
|
match &EXCEPTION_HANDLERS[index] {
|
||||||
|
Some(handler_holder) => {
|
||||||
|
let handler = &mut **handler_holder.handler.get();
|
||||||
|
handler.handle(exception_code, exception_pointers);
|
||||||
|
EXCEPTION_EXECUTE_HANDLER
|
||||||
|
}
|
||||||
|
None => EXCEPTION_EXECUTE_HANDLER,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type NativeHandlerType = extern "system" fn(*mut EXCEPTION_POINTERS) -> c_long;
|
type NativeHandlerType = extern "system" fn(*mut EXCEPTION_POINTERS) -> c_long;
|
||||||
static mut PREVIOUS_HANDLER: Option<NativeHandlerType> = None;
|
static mut PREVIOUS_HANDLER: Option<NativeHandlerType> = None;
|
||||||
|
|
||||||
@ -287,18 +317,8 @@ unsafe extern "system" fn handle_exception(exception_pointers: *mut EXCEPTION_PO
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.exception_code;
|
.exception_code;
|
||||||
let exception_code = ExceptionCode::try_from(code).unwrap();
|
let exception_code = ExceptionCode::try_from(code).unwrap();
|
||||||
let index = EXCEPTION_CODES_MAPPING
|
// println!("Received {}", exception_code);
|
||||||
.iter()
|
let ret = internal_handle_exception(exception_code, exception_pointers);
|
||||||
.position(|x| *x == exception_code)
|
|
||||||
.unwrap();
|
|
||||||
let ret = match &EXCEPTION_HANDLERS[index] {
|
|
||||||
Some(handler_holder) => {
|
|
||||||
let handler = &mut **handler_holder.handler.get();
|
|
||||||
handler.handle(exception_code, exception_pointers);
|
|
||||||
EXCEPTION_EXECUTE_HANDLER
|
|
||||||
}
|
|
||||||
None => EXCEPTION_EXECUTE_HANDLER,
|
|
||||||
};
|
|
||||||
if let Some(prev_handler) = PREVIOUS_HANDLER {
|
if let Some(prev_handler) = PREVIOUS_HANDLER {
|
||||||
prev_handler(exception_pointers)
|
prev_handler(exception_pointers)
|
||||||
} else {
|
} else {
|
||||||
@ -306,12 +326,26 @@ unsafe extern "system" fn handle_exception(exception_pointers: *mut EXCEPTION_PO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NativeSignalHandlerType = unsafe extern "C" fn(i32);
|
||||||
|
extern "C" {
|
||||||
|
fn signal(signum: i32, func: NativeSignalHandlerType) -> *const c_void;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
/// Setup Win32 exception handlers in a somewhat rusty way.
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// Exception handlers are usually ugly, handle with care!
|
/// Exception handlers are usually ugly, handle with care!
|
||||||
pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> {
|
pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> {
|
||||||
let exceptions = handler.exceptions();
|
let exceptions = handler.exceptions();
|
||||||
|
let mut catch_assertions = false;
|
||||||
for exception_code in exceptions {
|
for exception_code in exceptions {
|
||||||
|
if exception_code == ExceptionCode::AssertionFailure {
|
||||||
|
catch_assertions = true;
|
||||||
|
}
|
||||||
let index = EXCEPTION_CODES_MAPPING
|
let index = EXCEPTION_CODES_MAPPING
|
||||||
.iter()
|
.iter()
|
||||||
.position(|x| *x == exception_code)
|
.position(|x| *x == exception_code)
|
||||||
@ -324,7 +358,9 @@ pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) ->
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
if catch_assertions {
|
||||||
|
signal(SIGABRT, handle_signal);
|
||||||
|
}
|
||||||
if let Some(prev) = SetUnhandledExceptionFilter(Some(core::mem::transmute(
|
if let Some(prev) = SetUnhandledExceptionFilter(Some(core::mem::transmute(
|
||||||
handle_exception as *const c_void,
|
handle_exception as *const c_void,
|
||||||
))) {
|
))) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user