-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
Version of emscripten/emsdk:
Documentation - all version from here.
std::string getExceptionMessage(intptr_t exceptionPtr) {
return std::string(reinterpret_cast<std::exception *>(exceptionPtr)->what());
}According to the documentation, this code snippet appears to be a handler function for getExceptionMessage. However, it is much simpler than the current implementation found here.
The documentation also mentions that "this example code will only work for thrown statically allocated exceptions" but in reality, it only works if the exception type is exactly std::exception. It will not work (according to the standard C++) if the exception is a child of std::exception because is_pointer_interconvertible_base_of_v<std::exception, std::[any other std exception]> evaluates to false. Therefore, the reinterpret casting is not safe and results in undefined behavior.
Another issue is that this code can be exploited using the following structure:
struct BaseException {
virtual ~BaseException() = default;
virtual const char* hack() const noexcept { return "HACKED"; }
};
struct MyEx : BaseException, std::exception {
virtual const char* what() const noexcept { return "This won't be returned"; }
};
throw MyEx();We are using Emscripten with the following switches: -s DISABLE_EXCEPTION_CATCHING=1 -fno-rtti. This means that we don't have a bound __get_exception_message, but we still have exceptions and we want to retrieve the reason using .what(). We thought that this code snippet would be sufficient for handling .what(), but it turns out it's not. Therefore, this part of the documentation is misleading.