-
Notifications
You must be signed in to change notification settings - Fork 3.4k
How to discover what kind of bad function pointer casts occur? #16126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
For C code, you can detect such issues at compile-time by enabling the $ emcc -Wbad-function-cast -Wcast-function-type a.c -o a.js
a.c:10:12: warning: cast from 'void (*)()' to 'foo' (aka 'int (*)(void)') converts to incompatible function type [-Wcast-function-type]
foo ptr = (foo)&func;
^~~~~~~~~~
1 warning generated. For C++ code, it's not possible to detect that at compile-time (AFAIK). Such conversions were not allowed in C++03, but most compilers didn't issue a diagnostic. In C++11 these are "conditionally supported", no diagnostics are printed. An option that prints more details when the generic
(i.e. in the above example it's calling a |
Thanks @kleisauke , did not know about those |
Yes, but it would take some work. Cool about that C warning! I was not aware of that either. |
FYI you can use UBSan to get a runtime warning:
|
Nice, does that work for C for as well as C++ code? |
Yes. C, C++, Objective-C. |
FWIW, the forthcoming Clang 16 will introduce a new stricter warning for casts of function types (see llvm/llvm-project@1aad641), which is included as part of the existing error diagnostic setting of |
Corresponds to the fix introduced in commit harfbuzz/harfbuzz@60c6b77. Context: #16126 (comment).
I tried compiling with UBSan, but now it says "Compiling function ... failed: local count too large". (It also required a huge amount of RAM to compile.) So helpful in some situations, but not all unfortunately. |
Recently we have run into yet another bad function pointer cast issue. This time it looks like the root cause is from google/draco library, but we only have a precompiled program to debug, so we are unable to find if the pointer cast is an actual source code issue, or if it is a memory overrun issue - and we are unable to use Chrome or Firefox debugger or DevTools console to see which one it is. I started implementing a pass to Binaryen to let one diagnose these types of errors, at WebAssembly/binaryen#5864 . Additionally, I've opened a ticket on LLVM repository side regarding adding a more precise diagnostic flag to LLVM: llvm/llvm-project#64526 so that these issues would be traceable at compile-time. |
Consider the following C++ code that is undefined behavior:
Building this code natively with GCC or Clang succeeds and runs fine. However building it with Emscripten with
and running it in node, crashes with
which is all as expected, given that Wasm is strict with function pointer signatures, and cannot relax the calling conventions.
Building with
-s EMULATE_FUNCTION_POINTER_CASTS=1
linker flag makes the code also work on Emscripten. However, imagine a user is dealing with a large codebase, and they would want to avoid using the linker flag-s EMULATE_FUNCTION_POINTER_CASTS=1
due to its runtime overhead.Unfortunately there is no machinery that would help the user to diagnose where these bad casts occur, since
-s EMULATE_FUNCTION_POINTER_CASTS=1
silently passes such code.When building without the flag, one gets a crash callstack to the call site where the first bad function pointer cast call is attempted, but this has two issues:
It would be nice to have a mode
-s EMULATE_FUNCTION_POINTER_CASTS=2
or similar, which would for each mismatching function pointer signature call, log the callstack and the signatures in question (via e.g. awarnOnce
style logger), but still keep on executing the program. Would this be doable?The text was updated successfully, but these errors were encountered: