Skip to content
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

False positive with -fsanitize=function on macOS #109074

Open
neildhar opened this issue Sep 18, 2024 · 2 comments
Open

False positive with -fsanitize=function on macOS #109074

neildhar opened this issue Sep 18, 2024 · 2 comments
Labels
compiler-rt false-positive Warning fires when it should not platform:macos

Comments

@neildhar
Copy link

neildhar commented Sep 18, 2024

Seeing failures with -fsanitize=function when building on macOS for function calls where the type signature is actually correct. It seems like the type hash is not being preserved through linking.

Verified with:

  • Apple Clang from Xcode 16 (only when building for x64)
  • Clang from LLVM 18.1.4 (both x64 and arm64 macOS)

Minimised repro (note that the exact ordering is important to get things in the right order in the final binary):

foo.cpp:

void callPtr(void (*fn)());

void myFn();

template <typename T>
int myT(){ return 5; }

int main(){
  myT<void>();
  callPtr(&myFn);
  return 0;
}

void myFn(){}

foo2.cpp:

template <typename T>
int myT(){ return 5; }

void callPtr(void (*fn)()){
    myT<void>();
    fn();
}

Build and run (add -arch x86_64 if needed):

clang++ foo2.cpp foo.cpp -fsanitize=function && ./a.out

Result:

/Users/neildhar/foo2.cpp:6:5: runtime error: call to function myFn() through pointer to incorrect function type 'void (*)()'
(a.out:arm64+0x100003f38): note: myFn() defined here
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /Users/neildhar/foo2.cpp:6:5

To my untrained eye, it looks like the linker may be treating the type hash placed before myFn as part of the preceding function, and when that function occurs in multiple object files (as is the case for myT<void>), only one copy is kept. As a result, the bytes preceding myFn no longer represent its correct type hash.

@MaskRay
Copy link
Member

MaskRay commented Sep 18, 2024

To my untrained eye, it looks like the linker may be treating the type hash placed before myFn as part of the preceding function, and when that function occurs in multiple object files (as is the case for myT), only one copy is kept. As a result, the bytes preceding myFn no longer represent its correct type hash.

Yes. Mach-O's .subsections_via_symbols mechanism conceptually divides a sections with atoms (non-temporary symbols that are not .alt_entry).
For the following assembly, the two .long conceptually belongs to the previous function.

.long ...
.long ...

_f:
  nop

Some linker features (-dead_strip, -order_file) might move the .long relative to the function (and its body).

Perhaps we should just make -fsanitize=function unsupported on Mach-O platforms, but there are some cases that it would work.

@EugeneZelenko EugeneZelenko added compiler-rt platform:macos false-positive Warning fires when it should not and removed new issue labels Sep 18, 2024
@neildhar
Copy link
Author

Thank you for the background, that certainly explains the behaviour I observed.

Perhaps we should just make -fsanitize=function unsupported on Mach-O platforms, but there are some cases that it would work.

To me, it would be preferable to disable it for Mach-O. Having UBSan fail unpredictably on correct code seems like a serious issue.

facebook-github-bot pushed a commit to facebook/hermes that referenced this issue Sep 20, 2024
Summary:
`-fsanitize=function` relies on storing data before a function pointer
that describes the type of the function. However, on Apple platforms,
this data gets treated as part of the preceding function and can be
moved around or deleted. This results in UBSan false positives.

To address this, pass `-fno-sanitize=function` when compiling for Apple
platforms with UBSan enabled.

See llvm/llvm-project#109074

Reviewed By: fbmal7

Differential Revision: D62921741

fbshipit-source-id: da7fe78fc09840c90a48e6dfcf32ed14c514c323
hubot pushed a commit to google/skia that referenced this issue Sep 27, 2024
"-fsanitize=function" is designed to catch when calling a function
through a pointer of the wrong type (much like "-fsanitize=cfi-*call",
but a completely different mechanism). However, this is currently known
to have issues on macOS [0].

[0] llvm/llvm-project#109074

Change-Id: I66f51d8190f6105f852676a8faaf694e7f0dbcca
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/903958
Reviewed-by: Kaylee Lubick <kjlubick@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler-rt false-positive Warning fires when it should not platform:macos
Projects
None yet
Development

No branches or pull requests

3 participants