emscripten-core / emscripten-core/emscripten

Misleading C++ exception handling example

Open
#19,764 23 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
27.6k
Forks
3.6k
Avg merge
1d 1h
Merged PRs (30d)
105

Description

**Version of emscripten/emsdk:**
[Documentation](https://emscripten.org/docs/porting/Debugging.html#handling-c-exceptions-from-javascript) - all version from [here](https://github.com/emscripten-core/emscripten/pull/11073).

```cpp
std::string getExceptionMessage(intptr_t exceptionPtr) {
return std::string(reinterpret_cast(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](https://github.com/emscripten-core/emscripten/blob/3.1.42/system/lib/libcxxabi/src/cxa_exception_js_utils.cpp#L55).

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` 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:

```cpp
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](https://github.com/vizzuhq) 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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.