
* The performance is better than the glibc allocator. * Allocator interface functions, sanitizer allocator options, and MallocHooks/FreeHooks are supported. * Shadow memory has specific memory layout requirement. Using libc allocator could lead to conflicts. * When we add a mmap interceptor for reliability (the VMA could reuse a previously released VMA that is poisoned): glibc may invoke an internal system call to call unmmap, which cannot be intercepted. We will not be able to return the shadow memory to the OS. Similar to dfsan https://reviews.llvm.org/D101204 . Also intercept operator new/delete to be similar to other sanitizers using the sanitizer allocator. The align_val_t overload of operator new has slightly less overhead. Pull Request: https://github.com/llvm/llvm-project/pull/102764
58 lines
1.6 KiB
C++
58 lines
1.6 KiB
C++
// RUN: %clangxx_nsan %s -o %t && %run %t 2>&1 | FileCheck %s
|
|
|
|
#include <sanitizer/allocator_interface.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
extern "C" {
|
|
const volatile void *global_ptr;
|
|
|
|
#define WRITE(s) write(1, s, sizeof(s))
|
|
|
|
// Note: avoid calling functions that allocate memory in malloc/free
|
|
// to avoid infinite recursion.
|
|
void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) {
|
|
if (__sanitizer_get_ownership(ptr) && sz == 4) {
|
|
WRITE("MallocHook\n");
|
|
global_ptr = ptr;
|
|
}
|
|
}
|
|
void __sanitizer_free_hook(const volatile void *ptr) {
|
|
if (__sanitizer_get_ownership(ptr) && ptr == global_ptr)
|
|
WRITE("FreeHook\n");
|
|
}
|
|
} // extern "C"
|
|
|
|
volatile int *x;
|
|
|
|
void MallocHook1(const volatile void *ptr, size_t sz) { WRITE("MH1\n"); }
|
|
void MallocHook2(const volatile void *ptr, size_t sz) { WRITE("MH2\n"); }
|
|
void FreeHook1(const volatile void *ptr) { WRITE("FH1\n"); }
|
|
void FreeHook2(const volatile void *ptr) { WRITE("FH2\n"); }
|
|
// Call this function with uninitialized arguments to poison
|
|
// TLS shadow for function parameters before calling operator
|
|
// new and, eventually, user-provided hook.
|
|
__attribute__((noinline)) void allocate(int *unused1, int *unused2) {
|
|
x = new int;
|
|
}
|
|
|
|
int main() {
|
|
__sanitizer_install_malloc_and_free_hooks(MallocHook1, FreeHook1);
|
|
__sanitizer_install_malloc_and_free_hooks(MallocHook2, FreeHook2);
|
|
int *undef1, *undef2;
|
|
allocate(undef1, undef2);
|
|
// CHECK: MallocHook
|
|
// CHECK: MH1
|
|
// CHECK: MH2
|
|
// Check that malloc hook was called with correct argument.
|
|
if (global_ptr != (void *)x) {
|
|
_exit(1);
|
|
}
|
|
*x = 0;
|
|
delete x;
|
|
// CHECK: FreeHook
|
|
// CHECK: FH1
|
|
// CHECK: FH2
|
|
return 0;
|
|
}
|