emscripten-core / emscripten-core/emscripten
UBSan function pointer mismatch reporting not working
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
Taking the example from
https://emscripten.org/docs/porting/guidelines/function_pointer_issues.html#working-around-function-pointer-issues
It generates a nice error in a native build:
```
$ clang-19 -fsanitize=undefined a.cpp
$ ./a.out
voidReturn: hello world
a.cpp:22:5: runtime error: call to function intReturn(char const*) through pointer to incorrect function type 'void (*)(const char *)'
(a.out+0x31b68): note: intReturn(char const*) defined here
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior a.cpp:22:5
intReturn: hello world
voidReturnNoParam:
```
However, in wasm it doesn't:
```
$ ./emcc a.cpp -g -fsanitize=undefined
$ nodejs a.out.js
voidReturn: hello world
wasm://wasm/a.out.wasm-00a00baa:1
RuntimeError: null function or function signature mismatch
at a.out.wasm.callFunctions(void (* const*)(char const*), unsigned long) (wasm://wasm/a.out.wasm-00a00baa:wasm-function[36]:0xdbb)
at a.out.wasm.__original_main (wasm://wasm/a.out.wasm-00a00baa:wasm-function[37]:0xee2)
at a.out.wasm.main (wasm://wasm/a.out.wasm-00a00baa:wasm-function[42]:0xfb4)
at a.out.js:545:12
at callMain (a.out.js:4310:15)
at doRun (a.out.js:4352:24)
at run (a.out.js:4362:5)
at removeRunDependency (a.out.js:742:7)
at receiveInstance (a.out.js:632:5)
at receiveInstantiationResult (a.out.js:648:12)
Node.js v22.22.0
```
UBSan just doesn't do anything here, and we get the low-level error.
I wonder if the issue is that UBSan checks this *after* the call, that is, each function prologue checks if it was indirect-called, and it knows its signature, and reports any mismatch. That seems plausible, and then it would not work in wasm since we trap *before* we reach that code. However, if so, then I'd expect our function pointer cast emulation to fix things, as it avoids the low-level trap, but UBSan's check should still be there (since we do this after UBSan runs), and it doesn't:
```
$ ./emcc a.cpp -g -fsanitize=undefined -sEMULATE_FUNCTION_POINTER_CASTS
$ nodejs a.out.js
voidReturn: hello world
intReturn: hello world
voidReturnNoParam:
```
The program just runs ok, with no report from UBSan despite the undefined behavior.
If we get UBSan working here, it could make debugging this a lot easier for people.
Contributor guide
Assessment
This issue has not been assessed yet.