Skip to content

Commit d50043f

Browse files
authored
[EH] Make lsan/asan work with Wasm EH (#23552)
`std::rethrow_exception` leaked memory because dependent exceptions were not recognized as such and thus not freed properly here: https://github.com/emscripten-core/emscripten/blob/44fd294e8244afa710cecb2c10c9a644a6549b8e/system/lib/libcxxabi/src/cxa_exception.cpp#L575-L583 The reason for that was, in `__cxa_rethrow_primary_exception`, we were incorrectly throwing the primary exception, not the dependent one. I think the error was introduced during copy-pasting. `isDependentException` method was copied from `cxa_exception.cpp`, because it is a static function, as in the case for other utility functions in that file. This also adds handling for dependent exceptions in `__get_exception_message`. Fixes #21124.
1 parent 44fd294 commit d50043f

File tree

4 files changed

+17
-14
lines changed

4 files changed

+17
-14
lines changed

system/lib/libcxxabi/src/cxa_exception.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,9 +789,9 @@ __cxa_rethrow_primary_exception(void* thrown_object)
789789
// In debug mode, call a JS library function to use
790790
// WebAssembly.Exception JS API, which enables us to include stack
791791
// traces
792-
__throw_exception_with_stack_trace(&exception_header->unwindHeader);
792+
__throw_exception_with_stack_trace(&dep_exception_header->unwindHeader);
793793
#else
794-
_Unwind_RaiseException(&exception_header->unwindHeader);
794+
_Unwind_RaiseException(&dep_exception_header->unwindHeader);
795795
#endif
796796
// Some sort of unwinding error. Note that terminate is a handler.
797797
__cxa_begin_catch(&dep_exception_header->unwindHeader);

system/lib/libcxxabi/src/cxa_exception_js_utils.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ static inline __cxa_exception* cxa_exception_from_unwind_exception(
3838
return cxa_exception_from_thrown_object(unwind_exception + 1);
3939
}
4040

41+
#ifdef __WASM_EXCEPTIONS__
42+
struct __cxa_dependent_exception;
43+
uint64_t __getExceptionClass(const _Unwind_Exception* unwind_exception);
44+
static bool isDependentException(_Unwind_Exception* unwind_exception) {
45+
return (__getExceptionClass(unwind_exception) & 0xFF) == 0x01;
46+
}
47+
#endif
48+
4149
extern "C" {
4250

4351
void* __thrown_object_from_unwind_exception(
@@ -78,6 +86,13 @@ void __get_exception_message(void* thrown_object, char** type, char** message) {
7886
static_cast<const __shim_type_info*>(&typeid(std::exception));
7987
int can_catch = catch_type->can_catch(thrown_type, thrown_object);
8088
if (can_catch) {
89+
#if __WASM_EXCEPTIONS__
90+
if (isDependentException(&exception_header->unwindHeader))
91+
thrown_object =
92+
reinterpret_cast<__cxa_dependent_exception*>(exception_header)
93+
->primaryException;
94+
#endif
95+
8196
const char* what =
8297
static_cast<const std::exception*>(thrown_object)->what();
8398
*message = (char*)malloc(strlen(what) + 1);

test/common.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -641,9 +641,6 @@ def metafunc(self, mode, *args, **kwargs):
641641
# Wasm EH is currently supported only in wasm backend and V8
642642
if self.is_wasm2js():
643643
self.skipTest('wasm2js does not support wasm EH/SjLj')
644-
# FIXME Temporarily disabled. Enable this later when the bug is fixed.
645-
if '-fsanitize=address' in self.emcc_args:
646-
self.skipTest('Wasm EH does not work with asan yet')
647644
self.emcc_args.append('-fwasm-exceptions')
648645
self.set_setting('SUPPORT_LONGJMP', 'wasm')
649646
if mode == 'wasm':
@@ -677,9 +674,6 @@ def metafunc(self, mode, *args, **kwargs):
677674
if mode in {'wasm', 'wasm_legacy'}:
678675
if self.is_wasm2js():
679676
self.skipTest('wasm2js does not support wasm SjLj')
680-
# FIXME Temporarily disabled. Enable this later when the bug is fixed.
681-
if '-fsanitize=address' in self.emcc_args:
682-
self.skipTest('Wasm EH does not work with asan yet')
683677
self.set_setting('SUPPORT_LONGJMP', 'wasm')
684678
if mode == 'wasm':
685679
self.require_wasm_eh()

test/test_core.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,8 +1328,6 @@ def test_exceptions_refcount(self):
13281328

13291329
@with_all_eh_sjlj
13301330
def test_exceptions_primary(self):
1331-
if '-fsanitize=leak' in self.emcc_args and '-fwasm-exceptions' in self.emcc_args:
1332-
self.skipTest('https://github.com/emscripten-core/emscripten/issues/21124')
13331331
self.do_core_test('test_exceptions_primary.cpp')
13341332

13351333
@with_all_eh_sjlj
@@ -1346,8 +1344,6 @@ def test_exceptions_multiple_inherit(self):
13461344

13471345
@with_all_eh_sjlj
13481346
def test_exceptions_multiple_inherit_rethrow(self):
1349-
if '-fsanitize=leak' in self.emcc_args and '-fwasm-exceptions' in self.emcc_args:
1350-
self.skipTest('https://github.com/emscripten-core/emscripten/issues/21124')
13511347
self.do_core_test('test_exceptions_multiple_inherit_rethrow.cpp')
13521348

13531349
@with_all_eh_sjlj
@@ -1499,8 +1495,6 @@ def test_exceptions_longjmp2(self):
14991495

15001496
@with_all_eh_sjlj
15011497
def test_exceptions_longjmp3(self):
1502-
if '-fwasm-exceptions' in self.emcc_args:
1503-
self.skipTest('https://github.com/emscripten-core/emscripten/issues/17004')
15041498
self.do_core_test('test_exceptions_longjmp3.cpp')
15051499

15061500
@with_all_eh_sjlj

0 commit comments

Comments
 (0)