Skip to content

Commit bd03606

Browse files
committed
Fix a memory leak in emcc if a Rust panic is caught by C++ and discarded
1 parent bbf1372 commit bd03606

File tree

1 file changed

+18
-8
lines changed

1 file changed

+18
-8
lines changed

src/libpanic_unwind/emcc.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,32 @@ pub fn payload() -> *mut u8 {
5252
ptr::null_mut()
5353
}
5454

55+
struct Exception {
56+
data: Option<Box<dyn Any + Send>>,
57+
}
58+
5559
pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
5660
assert!(!ptr.is_null());
57-
let adjusted_ptr = __cxa_begin_catch(ptr as *mut libc::c_void);
58-
let ex = ptr::read(adjusted_ptr as *mut _);
61+
let adjusted_ptr = __cxa_begin_catch(ptr as *mut libc::c_void) as *mut Exception;
62+
let ex = (*adjusted_ptr).data.take();
5963
__cxa_end_catch();
60-
ex
64+
ex.unwrap()
6165
}
6266

6367
pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
6468
let sz = mem::size_of_val(&data);
65-
let exception = __cxa_allocate_exception(sz);
66-
if exception == ptr::null_mut() {
69+
let exception = __cxa_allocate_exception(sz) as *mut Exception;
70+
if exception.is_null() {
6771
return uw::_URC_FATAL_PHASE1_ERROR as u32;
6872
}
69-
ptr::write(exception as *mut _, data);
70-
__cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, ptr::null_mut());
73+
ptr::write(exception, Exception { data: Some(data) });
74+
__cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup);
75+
76+
extern "C" fn exception_cleanup(ptr: *mut libc::c_void) {
77+
unsafe {
78+
ptr::drop_in_place(ptr as *mut Exception);
79+
}
80+
}
7181
}
7282

7383
#[lang = "eh_personality"]
@@ -89,7 +99,7 @@ extern "C" {
8999
fn __cxa_throw(
90100
thrown_exception: *mut libc::c_void,
91101
tinfo: *const TypeInfo,
92-
dest: *mut libc::c_void,
102+
dest: extern "C" fn(*mut libc::c_void),
93103
) -> !;
94104
fn __gxx_personality_v0(
95105
version: c_int,

0 commit comments

Comments
 (0)