1 | //===-- hwasan_new_delete.cpp ---------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file is a part of HWAddressSanitizer. |
10 | // |
11 | // Interceptors for operators new and delete. |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "hwasan.h" |
15 | #include "interception/interception.h" |
16 | #include "sanitizer_common/sanitizer_allocator.h" |
17 | #include "sanitizer_common/sanitizer_allocator_report.h" |
18 | |
19 | #include <stddef.h> |
20 | #include <stdlib.h> |
21 | |
22 | #if HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE |
23 | |
24 | // TODO(alekseys): throw std::bad_alloc instead of dying on OOM. |
25 | # define OPERATOR_NEW_BODY(nothrow) \ |
26 | GET_MALLOC_STACK_TRACE; \ |
27 | void *res = hwasan_malloc(size, &stack); \ |
28 | if (!nothrow && UNLIKELY(!res)) \ |
29 | ReportOutOfMemory(size, &stack); \ |
30 | return res |
31 | # define OPERATOR_NEW_ALIGN_BODY(nothrow) \ |
32 | GET_MALLOC_STACK_TRACE; \ |
33 | void *res = hwasan_memalign(static_cast<uptr>(align), size, &stack); \ |
34 | if (!nothrow && UNLIKELY(!res)) \ |
35 | ReportOutOfMemory(size, &stack); \ |
36 | return res |
37 | |
38 | # define OPERATOR_DELETE_BODY \ |
39 | GET_MALLOC_STACK_TRACE; \ |
40 | if (ptr) \ |
41 | hwasan_free(ptr, &stack) |
42 | |
43 | #elif defined(__ANDROID__) |
44 | |
45 | // We don't actually want to intercept operator new and delete on Android, but |
46 | // since we previously released a runtime that intercepted these functions, |
47 | // removing the interceptors would break ABI. Therefore we simply forward to |
48 | // malloc and free. |
49 | # define OPERATOR_NEW_BODY(nothrow) return malloc(size) |
50 | # define OPERATOR_DELETE_BODY free(ptr) |
51 | |
52 | #endif |
53 | |
54 | #ifdef OPERATOR_NEW_BODY |
55 | |
56 | using namespace __hwasan; |
57 | |
58 | // Fake std::nothrow_t to avoid including <new>. |
59 | namespace std { |
60 | struct nothrow_t {}; |
61 | } // namespace std |
62 | |
63 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new(size_t size) { |
64 | OPERATOR_NEW_BODY(false /*nothrow*/); |
65 | } |
66 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[]( |
67 | size_t size) { |
68 | OPERATOR_NEW_BODY(false /*nothrow*/); |
69 | } |
70 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new( |
71 | size_t size, std::nothrow_t const &) { |
72 | OPERATOR_NEW_BODY(true /*nothrow*/); |
73 | } |
74 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[]( |
75 | size_t size, std::nothrow_t const &) { |
76 | OPERATOR_NEW_BODY(true /*nothrow*/); |
77 | } |
78 | |
79 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete( |
80 | void *ptr) NOEXCEPT { |
81 | OPERATOR_DELETE_BODY; |
82 | } |
83 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[]( |
84 | void *ptr) NOEXCEPT { |
85 | OPERATOR_DELETE_BODY; |
86 | } |
87 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete( |
88 | void *ptr, std::nothrow_t const &) { |
89 | OPERATOR_DELETE_BODY; |
90 | } |
91 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[]( |
92 | void *ptr, std::nothrow_t const &) { |
93 | OPERATOR_DELETE_BODY; |
94 | } |
95 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete( |
96 | void *ptr, size_t) NOEXCEPT { |
97 | OPERATOR_DELETE_BODY; |
98 | } |
99 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[]( |
100 | void *ptr, size_t) NOEXCEPT { |
101 | OPERATOR_DELETE_BODY; |
102 | } |
103 | |
104 | #endif // OPERATOR_NEW_BODY |
105 | |
106 | #ifdef OPERATOR_NEW_ALIGN_BODY |
107 | |
108 | namespace std { |
109 | enum class align_val_t : size_t {}; |
110 | } // namespace std |
111 | |
112 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new( |
113 | size_t size, std::align_val_t align) { |
114 | OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/); |
115 | } |
116 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[]( |
117 | size_t size, std::align_val_t align) { |
118 | OPERATOR_NEW_ALIGN_BODY(false /*nothrow*/); |
119 | } |
120 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new( |
121 | size_t size, std::align_val_t align, std::nothrow_t const &) { |
122 | OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/); |
123 | } |
124 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *operator new[]( |
125 | size_t size, std::align_val_t align, std::nothrow_t const &) { |
126 | OPERATOR_NEW_ALIGN_BODY(true /*nothrow*/); |
127 | } |
128 | |
129 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete( |
130 | void *ptr, std::align_val_t align) NOEXCEPT { |
131 | OPERATOR_DELETE_BODY; |
132 | } |
133 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[]( |
134 | void *ptr, std::align_val_t) NOEXCEPT { |
135 | OPERATOR_DELETE_BODY; |
136 | } |
137 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete( |
138 | void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT { |
139 | OPERATOR_DELETE_BODY; |
140 | } |
141 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[]( |
142 | void *ptr, std::align_val_t, std::nothrow_t const &) NOEXCEPT { |
143 | OPERATOR_DELETE_BODY; |
144 | } |
145 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete( |
146 | void *ptr, size_t, std::align_val_t) NOEXCEPT { |
147 | OPERATOR_DELETE_BODY; |
148 | } |
149 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[]( |
150 | void *ptr, size_t, std::align_val_t) NOEXCEPT { |
151 | OPERATOR_DELETE_BODY; |
152 | } |
153 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete( |
154 | void *ptr, size_t, std::align_val_t, std::nothrow_t const &) NOEXCEPT { |
155 | OPERATOR_DELETE_BODY; |
156 | } |
157 | INTERCEPTOR_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void operator delete[]( |
158 | void *ptr, size_t, std::align_val_t, std::nothrow_t const &) NOEXCEPT { |
159 | OPERATOR_DELETE_BODY; |
160 | } |
161 | |
162 | #endif // OPERATOR_NEW_ALIGN_BODY |
163 | |