Skip to content

Commit 3a02576

Browse files
committed
Abort if C++ tries to swallow a Rust panic
1 parent 757ed07 commit 3a02576

File tree

7 files changed

+17
-46
lines changed

7 files changed

+17
-46
lines changed

src/libpanic_unwind/emcc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
8080
extern "C" fn exception_cleanup(ptr: *mut libc::c_void) {
8181
unsafe {
8282
ptr::drop_in_place(ptr as *mut Exception);
83+
super::__rust_drop_panic();
8384
}
8485
}
8586
}

src/libpanic_unwind/gcc.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
7878
) {
7979
unsafe {
8080
let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
81+
super::__rust_drop_panic();
8182
}
8283
}
8384
}

src/libpanic_unwind/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ cfg_if::cfg_if! {
6161
}
6262
}
6363

64+
extern "C" {
65+
/// Handler in libstd called when a panic object is dropped outside of
66+
/// `catch_unwind`.
67+
fn __rust_drop_panic() -> !;
68+
}
69+
6470
mod dwarf;
6571

6672
// Entry point for catching an exception, implemented using the `try` intrinsic

src/libpanic_unwind/seh.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ macro_rules! define_cleanup {
229229
unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) {
230230
if (*e)[0] != 0 {
231231
cleanup(*e);
232+
super::__rust_drop_panic();
232233
}
233234
}
234235
#[unwind(allowed)]

src/libstd/panicking.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ extern "C" {
5555
fn __rust_start_panic(payload: usize) -> u32;
5656
}
5757

58+
/// This function is called by the panic runtime if FFI code catches a Rust
59+
/// panic but doesn't rethrow it. We don't support this case since it messes
60+
/// with our panic count.
61+
#[rustc_std_internal_symbol]
62+
extern "C" fn __rust_drop_panic() -> ! {
63+
rtabort!("Rust panics must be rethrown");
64+
}
65+
5866
#[derive(Copy, Clone)]
5967
enum Hook {
6068
Default,

src/test/run-make-fulldeps/foreign-exceptions/foo.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,4 @@ extern "C" {
5757
throw;
5858
}
5959
}
60-
61-
void swallow_exception(void (*cb)()) {
62-
try {
63-
// Do a rethrow to ensure that the exception is only dropped once.
64-
// This is necessary since we don't support copying exceptions.
65-
try {
66-
cb();
67-
} catch (...) {
68-
println("rethrowing Rust panic");
69-
throw;
70-
};
71-
} catch (rust_panic e) {
72-
assert(false && "shouldn't be able to catch a rust panic");
73-
} catch (...) {
74-
println("swallowing foreign exception in catch (...)");
75-
}
76-
}
7760
}

src/test/run-make-fulldeps/foreign-exceptions/foo.rs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ impl<'a> Drop for DropCheck<'a> {
1919
extern "C" {
2020
fn throw_cxx_exception();
2121

22-
fn swallow_exception(cb: extern "C" fn());
23-
2422
#[unwind(allowed)]
2523
fn cxx_catch_callback(cb: extern "C" fn(), ok: *mut bool);
2624
}
@@ -61,34 +59,7 @@ fn throw_rust_panic() {
6159
assert!(cxx_ok);
6260
}
6361

64-
fn check_exception_drop() {
65-
static mut DROP_COUNT: usize = 0;
66-
67-
struct CountDrop;
68-
impl Drop for CountDrop {
69-
fn drop(&mut self) {
70-
println!("CountDrop::drop");
71-
unsafe {
72-
DROP_COUNT += 1;
73-
}
74-
}
75-
}
76-
77-
78-
#[unwind(allowed)]
79-
extern "C" fn callback() {
80-
println!("throwing rust panic #2");
81-
panic!(CountDrop);
82-
}
83-
84-
unsafe {
85-
swallow_exception(callback);
86-
assert_eq!(DROP_COUNT, 1);
87-
}
88-
}
89-
9062
fn main() {
9163
unsafe { throw_cxx_exception() };
9264
throw_rust_panic();
93-
check_exception_drop();
9465
}

0 commit comments

Comments
 (0)