1 | // RUN: %clangxx -O2 %s -o %t && %run %t 2>&1 |
2 | |
3 | // Malloc/free hooks are not supported on Windows. |
4 | // XFAIL: target={{.*windows-msvc.*}} |
5 | |
6 | // Must not be implemented, no other reason to install interceptors. |
7 | // XFAIL: ubsan |
8 | |
9 | #include <assert.h> |
10 | #include <sanitizer/allocator_interface.h> |
11 | #include <stdlib.h> |
12 | #include <unistd.h> |
13 | |
14 | extern "C" { |
15 | const volatile void *global_ptr; |
16 | |
17 | // Note: avoid calling functions that allocate memory in malloc/free |
18 | // to avoid infinite recursion. |
19 | void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) { |
20 | if (__sanitizer_get_ownership(p: ptr) && sz == sizeof(int)) { |
21 | global_ptr = ptr; |
22 | assert(__sanitizer_get_allocated_size_fast(ptr) == sizeof(int)); |
23 | } |
24 | } |
25 | void __sanitizer_free_hook(const volatile void *ptr) { |
26 | if (__sanitizer_get_ownership(p: ptr) && ptr == global_ptr) |
27 | assert(__sanitizer_get_allocated_size_fast(ptr) == sizeof(int)); |
28 | } |
29 | } // extern "C" |
30 | |
31 | volatile int *x; |
32 | |
33 | // Call this function with uninitialized arguments to poison |
34 | // TLS shadow for function parameters before calling operator |
35 | // new and, eventually, user-provided hook. |
36 | __attribute__((noinline)) void allocate(int *unused1, int *unused2) { |
37 | x = reinterpret_cast<int *>(malloc(size: sizeof(int))); |
38 | } |
39 | |
40 | int main() { |
41 | int *undef1, *undef2; |
42 | allocate(unused1: undef1, unused2: undef2); |
43 | |
44 | // Check that malloc hook was called with correct argument. |
45 | if (global_ptr != (void *)x) { |
46 | _exit(status: 1); |
47 | } |
48 | |
49 | *x = -8; |
50 | free(ptr: (void *)x); |
51 | |
52 | return 0; |
53 | } |
54 | |