From 10720b418ecc72709adddba1b26e2cb293558e1b Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 26 Dec 2019 10:46:32 -0500 Subject: [PATCH] Fix a memory leak in emcc if a Rust panic is caught by C++ and discarded --- src/libpanic_unwind/emcc.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index 9d3fe5254f8..61f33fd4d5d 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -52,22 +52,32 @@ pub fn payload() -> *mut u8 { ptr::null_mut() } +struct Exception { + data: Option>, +} + pub unsafe fn cleanup(ptr: *mut u8) -> Box { assert!(!ptr.is_null()); - let adjusted_ptr = __cxa_begin_catch(ptr as *mut libc::c_void); - let ex = ptr::read(adjusted_ptr as *mut _); + let adjusted_ptr = __cxa_begin_catch(ptr as *mut libc::c_void) as *mut Exception; + let ex = (*adjusted_ptr).data.take(); __cxa_end_catch(); - ex + ex.unwrap() } pub unsafe fn panic(data: Box) -> u32 { let sz = mem::size_of_val(&data); - let exception = __cxa_allocate_exception(sz); + let exception = __cxa_allocate_exception(sz) as *mut Exception; if exception.is_null() { return uw::_URC_FATAL_PHASE1_ERROR as u32; } - ptr::write(exception as *mut _, data); - __cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, ptr::null_mut()); + ptr::write(exception, Exception { data: Some(data) }); + __cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup); + + extern "C" fn exception_cleanup(ptr: *mut libc::c_void) { + unsafe { + ptr::drop_in_place(ptr as *mut Exception); + } + } } #[lang = "eh_personality"] @@ -89,7 +99,7 @@ pub unsafe fn panic(data: Box) -> u32 { fn __cxa_throw( thrown_exception: *mut libc::c_void, tinfo: *const TypeInfo, - dest: *mut libc::c_void, + dest: extern "C" fn(*mut libc::c_void), ) -> !; fn __gxx_personality_v0( version: c_int, -- 2.44.0