Skip to content

UBSan function pointer mismatch reporting not working #26600

@kripken

Description

@kripken

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions