Skip to content

Commit d124ba1

Browse files
authored
[EH] Fix __get_exception_message for multiple virtual inheritance (#26946)
This fixes `__get_exception_message` so it works with multiple virtual inheritance. #24008 tried to fix this, but the test case there didn't `virtual` in the line where the inheritance happens. In case of dependent exceptions (= the exceptions thrown by `std::rethrow_exception`), we should not even dereference `thrown_object`, because it doesn't contain anything. #24008 ran `can_catch` on the currect primary exception but before that it called `can_catch` on the dependent exception first, which caused the memory error. #24008's test case was fine because it didn't have `virtual`, we didn't have to dereference `thrown_object` (`adjustedPtr` in this method) directly: https://github.com/emscripten-core/emscripten/blob/b2e19a341ac53b33de3aae7b4ea7bf7168ebace7/system/lib/libcxxabi/src/private_typeinfo.cpp#L572-L579 This computes the primary exception pointer first and then call `can_catch`. Fixes #26771.
1 parent b2e19a3 commit d124ba1

2 files changed

Lines changed: 27 additions & 24 deletions

File tree

system/lib/libcxxabi/src/cxa_exception_js_utils.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,17 @@ void __get_exception_message(void* thrown_object, char** type, char** message) {
8585
*message = NULL;
8686
const __shim_type_info* catch_type =
8787
static_cast<const __shim_type_info*>(&typeid(std::exception));
88-
int can_catch = catch_type->can_catch(thrown_type, thrown_object);
89-
if (can_catch) {
88+
9089
#if __WASM_EXCEPTIONS__
91-
if (isDependentException(&exception_header->unwindHeader)) {
92-
thrown_object =
93-
reinterpret_cast<__cxa_dependent_exception*>(exception_header)
94-
->primaryException;
95-
// can_catch can adjust thrown_object ptr, so rerun it
96-
[[maybe_unused]] bool ret =
97-
catch_type->can_catch(thrown_type, thrown_object);
98-
assert(ret);
99-
}
90+
if (isDependentException(&exception_header->unwindHeader)) {
91+
thrown_object =
92+
reinterpret_cast<__cxa_dependent_exception*>(exception_header)
93+
->primaryException;
94+
}
10095
#endif
10196

97+
int can_catch = catch_type->can_catch(thrown_type, thrown_object);
98+
if (can_catch) {
10299
const char* what =
103100
static_cast<const std::exception*>(thrown_object)->what();
104101
*message = (char*)malloc(strlen(what) + 1);

test/test_other.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8742,30 +8742,36 @@ def test_multi_inheritance_exception_message(self):
87428742
# did not retrieve the correct thrown object pointer in case of multiple
87438743
# inheritance
87448744
create_file('src.cpp', r'''
8745-
#include <iostream>
8745+
#include <exception>
8746+
#include <string>
87468747

8747-
struct Virt {
8748-
virtual void virt1() {}
8749-
};
8748+
class MyException : public virtual std::exception {
8749+
public:
8750+
MyException(const char *msg) : m_message(msg) {}
8751+
const char *what() const noexcept override { return m_message.c_str(); }
87508752

8751-
struct MyEx : Virt, public std::runtime_error {
8752-
explicit MyEx(std::string msg) : std::runtime_error(std::move(msg)) {}
8753+
private:
8754+
std::string m_message;
87538755
};
87548756

87558757
int main() {
8758+
std::exception_ptr ep;
87568759
try {
8757-
throw MyEx("ERROR");
8760+
throw MyException("hello");
87588761
} catch (...) {
8759-
try {
8760-
std::rethrow_exception(std::current_exception());
8761-
} catch (const std::exception &ex) {
8762-
std::cout << ex.what() << '\n';
8763-
}
8762+
ep = std::current_exception();
8763+
}
8764+
8765+
try {
8766+
std::rethrow_exception(ep);
8767+
} catch (const std::exception &e) {
8768+
std::printf("caught: %s\n", e.what());
87648769
}
8770+
return 0;
87658771
}
87668772
''')
87678773
self.set_setting('ASSERTIONS')
8768-
self.do_runf('src.cpp', 'ERROR\n')
8774+
self.do_runf('src.cpp', 'caught: hello\n')
87698775

87708776
@with_all_eh_sjlj
87718777
def test_unused_eh_dce(self):

0 commit comments

Comments
 (0)