1*652707a6SFangrui Song // RUN: %clangxx_nsan %s -o %t && %run %t 2>&1 | FileCheck %s 2*652707a6SFangrui Song 3*652707a6SFangrui Song #include <sanitizer/allocator_interface.h> 4*652707a6SFangrui Song #include <stdlib.h> 5*652707a6SFangrui Song #include <unistd.h> 6*652707a6SFangrui Song 7*652707a6SFangrui Song extern "C" { 8*652707a6SFangrui Song const volatile void *global_ptr; 9*652707a6SFangrui Song 10*652707a6SFangrui Song #define WRITE(s) write(1, s, sizeof(s)) 11*652707a6SFangrui Song 12*652707a6SFangrui Song // Note: avoid calling functions that allocate memory in malloc/free 13*652707a6SFangrui Song // to avoid infinite recursion. 14*652707a6SFangrui Song void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) { 15*652707a6SFangrui Song if (__sanitizer_get_ownership(ptr) && sz == 4) { 16*652707a6SFangrui Song WRITE("MallocHook\n"); 17*652707a6SFangrui Song global_ptr = ptr; 18*652707a6SFangrui Song } 19*652707a6SFangrui Song } 20*652707a6SFangrui Song void __sanitizer_free_hook(const volatile void *ptr) { 21*652707a6SFangrui Song if (__sanitizer_get_ownership(ptr) && ptr == global_ptr) 22*652707a6SFangrui Song WRITE("FreeHook\n"); 23*652707a6SFangrui Song } 24*652707a6SFangrui Song } // extern "C" 25*652707a6SFangrui Song 26*652707a6SFangrui Song volatile int *x; 27*652707a6SFangrui Song 28*652707a6SFangrui Song void MallocHook1(const volatile void *ptr, size_t sz) { WRITE("MH1\n"); } 29*652707a6SFangrui Song void MallocHook2(const volatile void *ptr, size_t sz) { WRITE("MH2\n"); } 30*652707a6SFangrui Song void FreeHook1(const volatile void *ptr) { WRITE("FH1\n"); } 31*652707a6SFangrui Song void FreeHook2(const volatile void *ptr) { WRITE("FH2\n"); } 32*652707a6SFangrui Song // Call this function with uninitialized arguments to poison 33*652707a6SFangrui Song // TLS shadow for function parameters before calling operator 34*652707a6SFangrui Song // new and, eventually, user-provided hook. 35*652707a6SFangrui Song __attribute__((noinline)) void allocate(int *unused1, int *unused2) { 36*652707a6SFangrui Song x = new int; 37*652707a6SFangrui Song } 38*652707a6SFangrui Song 39*652707a6SFangrui Song int main() { 40*652707a6SFangrui Song __sanitizer_install_malloc_and_free_hooks(MallocHook1, FreeHook1); 41*652707a6SFangrui Song __sanitizer_install_malloc_and_free_hooks(MallocHook2, FreeHook2); 42*652707a6SFangrui Song int *undef1, *undef2; 43*652707a6SFangrui Song allocate(undef1, undef2); 44*652707a6SFangrui Song // CHECK: MallocHook 45*652707a6SFangrui Song // CHECK: MH1 46*652707a6SFangrui Song // CHECK: MH2 47*652707a6SFangrui Song // Check that malloc hook was called with correct argument. 48*652707a6SFangrui Song if (global_ptr != (void *)x) { 49*652707a6SFangrui Song _exit(1); 50*652707a6SFangrui Song } 51*652707a6SFangrui Song *x = 0; 52*652707a6SFangrui Song delete x; 53*652707a6SFangrui Song // CHECK: FreeHook 54*652707a6SFangrui Song // CHECK: FH1 55*652707a6SFangrui Song // CHECK: FH2 56*652707a6SFangrui Song return 0; 57*652707a6SFangrui Song } 58