[Darwin][ASan][Test] Create a unoptimized wrapper function in unsanitized dylib for reliable suppression in test. (#131906)

CFStringCreateWithBytes may not always appear on stack due to
optimizations.

Create a wrapper function for the purposes of testing suppression files
that will always appear on stack for test stability.

Test should be suppressing ASan for a function outside of sanitized
code.
Update function to be extern "C" to match function decoration in
original framework and avoid the leak caused by DemangleCXXABI.

rdar://144800068
This commit is contained in:
Paddy McDonald
2025-03-21 17:17:32 -07:00
committed by GitHub
parent 6419905f53
commit 4517a332df

View File

@@ -1,9 +1,13 @@
// Compile the intermediate function to a dylib without -fsanitize to avoid
// suppressing symbols in sanitized code.
// RUN: %clangxx -O0 -DSHARED_LIB %s -dynamiclib -o %t.dylib -framework Foundation
// Check that without suppressions, we catch the issue.
// RUN: %clangxx_asan -O0 %s -o %t -framework Foundation
// RUN: %clangxx_asan -O0 %s -o %t -framework Foundation %t.dylib
// RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
// Check that suppressing a function name works within a no-fork sandbox
// RUN: echo "interceptor_via_fun:CFStringCreateWithBytes" > %t.supp
// RUN: echo "interceptor_via_fun:createCFString" > %t.supp
// RUN: %env_asan_opts=suppressions='"%t.supp"' \
// RUN: sandbox-exec -p '(version 1)(allow default)(deny process-fork)' \
// RUN: %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s
@@ -13,17 +17,37 @@
#include <CoreFoundation/CoreFoundation.h>
#if defined(SHARED_LIB)
extern "C" {
// Disable optimizations to ensure that this function appears on the stack trace so our
// configured suppressions `interceptor_via_fun:createCFString` can take effect.
__attribute__((disable_tail_calls)) CFStringRef
createCFString(const unsigned char *bytes, CFIndex length) {
return CFStringCreateWithBytes(kCFAllocatorDefault, bytes, length,
kCFStringEncodingUTF8, FALSE);
}
}
#else
extern "C" {
CFStringRef createCFString(const unsigned char *bytes, CFIndex length);
}
int main() {
char *a = (char *)malloc(6);
strcpy(a, "hello");
CFStringRef str =
CFStringCreateWithBytes(kCFAllocatorDefault, (unsigned char *)a, 10,
kCFStringEncodingUTF8, FALSE); // BOOM
// Intentional out-of-bounds access that will be caught unless an ASan suppression is provided.
CFStringRef str = createCFString((unsigned char *)a, 10); // BOOM
// If this is printed to stderr then the ASan suppression has worked.
fprintf(stderr, "Ignored.\n");
free(a);
CFRelease(str);
}
#endif
// CHECK-CRASH: AddressSanitizer: heap-buffer-overflow
// CHECK-CRASH-NOT: Ignored.
// CHECK-IGNORE-NOT: AddressSanitizer: heap-buffer-overflow