diff --git a/src/shims/panic.rs b/src/shims/panic.rs index abc7aa2ad1..8f06e5276f 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -45,7 +45,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx trace!("miri_start_panic: {:?}", this.frame().instance); // Make sure we only start unwinding when this matches our panic strategy. - assert_eq!(this.tcx.sess.panic_strategy(), PanicStrategy::Unwind); + if this.tcx.sess.panic_strategy() != PanicStrategy::Unwind { + throw_ub_format!("unwinding despite panic=abort"); + } // Get the raw pointer stored in arg[0] (the panic payload). let &[ref payload] = check_arg_count(args)?; diff --git a/tests/compile-fail/panic/bad_unwind.rs b/tests/compile-fail/panic/bad_unwind.rs new file mode 100644 index 0000000000..fde2c19af0 --- /dev/null +++ b/tests/compile-fail/panic/bad_unwind.rs @@ -0,0 +1,16 @@ +// error-pattern: calling a function with ABI C-unwind using caller ABI C +#![feature(c_unwind)] + +//! Unwinding when the caller ABI is "C" (without "-unwind") is UB. +//! Currently we detect the ABI mismatch; we could probably allow such calls in principle one day +//! but then we have to detect the unexpected unwinding. + +extern "C-unwind" fn unwind() { + panic!(); +} + +fn main() { + let unwind: extern "C-unwind" fn() = unwind; + let unwind: extern "C" fn() = unsafe { std::mem::transmute(unwind) }; + std::panic::catch_unwind(|| unwind()).unwrap_err(); +} diff --git a/tests/compile-fail/panic/unwind_panic_abort.rs b/tests/compile-fail/panic/unwind_panic_abort.rs new file mode 100644 index 0000000000..05284eb770 --- /dev/null +++ b/tests/compile-fail/panic/unwind_panic_abort.rs @@ -0,0 +1,11 @@ +// compile-flags: -Cpanic=abort + +//! Unwinding despite `-C panic=abort` is an error. + +extern "Rust" { + fn miri_start_panic(payload: *mut u8) -> !; +} + +fn main() { + unsafe { miri_start_panic(&mut 0); } //~ ERROR unwinding despite panic=abort +}