diff --git a/src/panic.rs b/src/panic.rs index d61f5e9..b69e958 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -7,6 +7,8 @@ use crate::abi::*; pub use crate::panic_handler::*; use crate::panicking::Exception; +static CANARY: u8 = 0; + #[repr(transparent)] struct RustPanic(Box, DropGuard); @@ -25,6 +27,8 @@ impl Drop for DropGuard { #[repr(C)] struct ExceptionWithPayload { exception: MaybeUninit, + // See rust/library/panic_unwind/src/gcc.rs for the canary values + canary: *const u8, payload: RustPanic, } @@ -34,12 +38,23 @@ unsafe impl Exception for RustPanic { fn wrap(this: Self) -> *mut UnwindException { Box::into_raw(Box::new(ExceptionWithPayload { exception: MaybeUninit::uninit(), + canary: &CANARY, payload: this, })) as *mut UnwindException } unsafe fn unwrap(ex: *mut UnwindException) -> Self { - let ex = unsafe { Box::from_raw(ex as *mut ExceptionWithPayload) }; + let ex = ex as *mut ExceptionWithPayload; + let canary = unsafe { core::ptr::addr_of!((*ex).canary).read() }; + if !core::ptr::eq(canary, &CANARY) { + // This is a Rust exception but not generated by us. + #[cfg(feature = "panic-handler")] + { + foreign_exception(); + } + crate::util::abort(); + } + let ex = unsafe { Box::from_raw(ex) }; ex.payload } }