1// RUN: %clangxx_hwasan -O2 %s -o %t -DTEST=basic_hook_works && not %run %t \
2// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-BASIC
3// RUN: %clangxx_hwasan -O2 %s -o %t -DTEST=ignore && %run %t \
4// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-IGNORE
5// RUN: %clangxx_hwasan -O2 %s -o %t -DTEST=ignore_twice && not %run %t \
6// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-IGNORE-2
7// RUN: %clangxx_hwasan -O2 %s -o %t -DTEST=double_delete && not %run %t \
8// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-DOUBLE-DELETE
9
10#include <sanitizer/hwasan_interface.h>
11#include <stdio.h>
12#include <stdlib.h>
13
14static char *volatile glob_ptr;
15bool ignore_free = false;
16
17#if (__APPLE__)
18// Required for dyld macOS 12.0+
19# define WEAK_ON_APPLE __attribute__((weak))
20#else // !(__APPLE__)
21# define WEAK_ON_APPLE
22#endif // (__APPLE__)
23
24extern "C" {
25WEAK_ON_APPLE void __sanitizer_free_hook(const volatile void *ptr) {
26 if (ptr == glob_ptr)
27 fprintf(stderr, format: "Free Hook\n");
28}
29
30WEAK_ON_APPLE int __sanitizer_ignore_free_hook(const volatile void *ptr) {
31 if (ptr != glob_ptr)
32 return 0;
33 fprintf(stderr, format: ignore_free ? "Free Ignored\n" : "Free Respected\n");
34 return ignore_free;
35}
36} // extern "C"
37
38void allocate() { glob_ptr = reinterpret_cast<char *volatile>(malloc(size: 100)); }
39void deallocate() { free(ptr: reinterpret_cast<void *>(glob_ptr)); }
40
41void basic_hook_works() {
42 allocate();
43 deallocate(); // CHECK-BASIC-NOT: Free Ignored
44 // CHECK-BASIC: Free Respected
45 // CHECK-BASIC: Free Hook
46 *glob_ptr = 0; // CHECK-BASIC: HWAddressSanitizer: tag-mismatch
47}
48
49void ignore() {
50 allocate();
51 ignore_free = true;
52 deallocate();
53 // CHECK-IGNORE: Free Ignored
54 // CHECK-IGNORE-NOT: Free Respected
55 // CHECK-IGNORE-NOT: Free Hook
56 // CHECK-IGNORE-NOT: HWAddressSanitizer
57 *glob_ptr = 0;
58}
59
60void ignore_twice() {
61 allocate();
62 ignore_free = true;
63 deallocate(); // CHECK-IGNORE-2: Free Ignored
64 *glob_ptr = 0;
65 ignore_free = false;
66 deallocate(); // CHECK-IGNORE-2-NOT: Free Ignored
67 // CHECK-IGNORE-2: Free Respected
68 // CHECK-IGNORE-2: Free Hook
69 *glob_ptr = 0; // CHECK-IGNORE-2: HWAddressSanitizer: tag-mismatch
70}
71
72void ignore_a_lot() {
73 allocate();
74 ignore_free = true;
75 for (int i = 0; i < 10000; ++i) {
76 deallocate(); // CHECK-IGNORE-3: Free Ignored
77 *glob_ptr = 0;
78 }
79 ignore_free = false;
80 deallocate(); // CHECK-IGNORE-3: Free Respected
81 // CHECK-IGNORE-3: Free Hook
82 *glob_ptr = 0; // CHECK-IGNORE-3: HWAddressSanitizer: tag-mismatch
83}
84
85void double_delete() {
86 allocate();
87 ignore_free = true;
88 deallocate(); // CHECK-DOUBLE-DELETE: Free Ignored
89 deallocate(); // CHECK-DOUBLE-DELETE: Free Ignored
90 ignore_free = false;
91 deallocate(); // CHECK-DOUBLE-DELETE: Free Respected
92 // CHECK-DOUBLE-DELETE: Free Hook
93 deallocate(); // CHECK-DOUBLE-DELETE: HWAddressSanitizer: invalid-free
94}
95
96int main() {
97 __hwasan_enable_allocator_tagging();
98 TEST();
99 return 0;
100}
101

source code of compiler-rt/test/hwasan/TestCases/Posix/ignore_free_hook.cpp