1 | // Test basic new functionality. |
2 | // RUN: %clangxx_hwasan -std=c++17 %s -o %t -fsized-deallocation |
3 | // RUN: %run %t |
4 | |
5 | #include <cassert> |
6 | #include <cstdint> |
7 | #include <cstdlib> |
8 | #include <new> |
9 | #include <sanitizer/allocator_interface.h> |
10 | #include <sanitizer/hwasan_interface.h> |
11 | |
12 | void operator_new_delete(size_t size) { |
13 | void *alloc = operator new(size); |
14 | assert(alloc != nullptr); |
15 | assert(__sanitizer_get_allocated_size(p: alloc) == size); |
16 | operator delete(alloc); |
17 | |
18 | alloc = operator new(size); |
19 | assert(alloc != nullptr); |
20 | assert(__sanitizer_get_allocated_size(p: alloc) == size); |
21 | operator delete(alloc, size); |
22 | } |
23 | |
24 | void operator_new_delete_array(size_t size) { |
25 | void *alloc = operator new[](size); |
26 | assert(alloc != nullptr); |
27 | assert(__sanitizer_get_allocated_size(p: alloc) == size); |
28 | operator delete[](alloc); |
29 | |
30 | alloc = operator new[](size); |
31 | assert(alloc != nullptr); |
32 | assert(__sanitizer_get_allocated_size(p: alloc) == size); |
33 | operator delete[](alloc, size); |
34 | } |
35 | |
36 | void operator_new_delete(size_t size, std::align_val_t align) { |
37 | void *alloc = operator new(size, align); |
38 | assert(alloc != nullptr); |
39 | assert(reinterpret_cast<uintptr_t>(alloc) % static_cast<uintptr_t>(align) == 0); |
40 | assert(__sanitizer_get_allocated_size(p: alloc) >= size); |
41 | operator delete(alloc, align); |
42 | |
43 | alloc = operator new(size, align); |
44 | assert(alloc != nullptr); |
45 | assert(reinterpret_cast<uintptr_t>(alloc) % static_cast<uintptr_t>(align) == 0); |
46 | assert(__sanitizer_get_allocated_size(p: alloc) >= size); |
47 | operator delete(alloc, size, align); |
48 | } |
49 | |
50 | void operator_new_delete_array(size_t size, std::align_val_t align) { |
51 | void *alloc = operator new[](size, align); |
52 | assert(alloc != nullptr); |
53 | assert(reinterpret_cast<uintptr_t>(alloc) % static_cast<uintptr_t>(align) == 0); |
54 | assert(__sanitizer_get_allocated_size(p: alloc) >= size); |
55 | operator delete[](alloc, align); |
56 | |
57 | alloc = operator new[](size, align); |
58 | assert(alloc != nullptr); |
59 | assert(reinterpret_cast<uintptr_t>(alloc) % static_cast<uintptr_t>(align) == 0); |
60 | assert(__sanitizer_get_allocated_size(p: alloc) >= size); |
61 | operator delete[](alloc, size, align); |
62 | } |
63 | |
64 | void operator_new_delete(size_t size, const std::nothrow_t &tag) { |
65 | void *alloc = operator new(size, tag); |
66 | assert(alloc != nullptr); |
67 | assert(__sanitizer_get_allocated_size(p: alloc) == size); |
68 | operator delete(alloc, tag); |
69 | } |
70 | |
71 | void operator_new_delete_array(size_t size, const std::nothrow_t &tag) { |
72 | void *alloc = operator new[](size, tag); |
73 | assert(alloc != nullptr); |
74 | assert(__sanitizer_get_allocated_size(p: alloc) == size); |
75 | operator delete[](alloc, tag); |
76 | } |
77 | |
78 | void operator_new_delete(size_t size, std::align_val_t align, const std::nothrow_t &tag) { |
79 | void *alloc = operator new(size, align, tag); |
80 | assert(alloc != nullptr); |
81 | assert(reinterpret_cast<uintptr_t>(alloc) % static_cast<uintptr_t>(align) == 0); |
82 | assert(__sanitizer_get_allocated_size(p: alloc) >= size); |
83 | operator delete(alloc, align, tag); |
84 | } |
85 | |
86 | void operator_new_delete_array(size_t size, std::align_val_t align, const std::nothrow_t &tag) { |
87 | void *alloc = operator new[](size, align, tag); |
88 | assert(alloc != nullptr); |
89 | assert(reinterpret_cast<uintptr_t>(alloc) % static_cast<uintptr_t>(align) == 0); |
90 | assert(__sanitizer_get_allocated_size(p: alloc) >= size); |
91 | operator delete[](alloc, align, tag); |
92 | } |
93 | |
94 | void operator_new_delete(size_t size, void *ptr) { |
95 | void *alloc = operator new(size, ptr); |
96 | assert(alloc == ptr); |
97 | operator delete(alloc, ptr); |
98 | } |
99 | |
100 | void operator_new_delete_array(size_t size, void *ptr) { |
101 | void *alloc = operator new[](size, ptr); |
102 | assert(alloc == ptr); |
103 | operator delete[](alloc, ptr); |
104 | } |
105 | |
106 | int main() { |
107 | __hwasan_enable_allocator_tagging(); |
108 | |
109 | size_t volatile n = 0; |
110 | char *a1 = new char[n]; |
111 | assert(a1 != nullptr); |
112 | assert(__sanitizer_get_allocated_size(p: a1) == 1); |
113 | delete[] a1; |
114 | |
115 | constexpr size_t kSize = 8; |
116 | operator_new_delete(size: kSize); |
117 | operator_new_delete_array(size: kSize); |
118 | operator_new_delete(kSize, std::nothrow); |
119 | operator_new_delete_array(kSize, std::nothrow); |
120 | |
121 | char buffer[kSize]; |
122 | operator_new_delete(size: kSize, ptr: buffer); |
123 | operator_new_delete_array(size: kSize, ptr: buffer); |
124 | |
125 | #if defined(__cpp_aligned_new) && \ |
126 | (!defined(__GLIBCXX__) || \ |
127 | (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7)) |
128 | // Aligned new/delete |
129 | constexpr auto kAlign = std::align_val_t{8}; |
130 | void *a2 = ::operator new(4, kAlign); |
131 | assert(a2 != nullptr); |
132 | assert(reinterpret_cast<uintptr_t>(a2) % static_cast<uintptr_t>(kAlign) == 0); |
133 | assert(__sanitizer_get_allocated_size(p: a2) >= 4); |
134 | ::operator delete(a2, kAlign); |
135 | |
136 | operator_new_delete(kSize, std::align_val_t{kSize}); |
137 | operator_new_delete_array(kSize, std::align_val_t{kSize}); |
138 | operator_new_delete(kSize, std::align_val_t{kSize * 2}); |
139 | operator_new_delete_array(kSize, std::align_val_t{kSize * 2}); |
140 | operator_new_delete(kSize, std::align_val_t{kSize}, std::nothrow); |
141 | operator_new_delete_array(kSize, std::align_val_t{kSize}, std::nothrow); |
142 | operator_new_delete(kSize, std::align_val_t{kSize * 2}, std::nothrow); |
143 | operator_new_delete_array(kSize, std::align_val_t{kSize * 2}, std::nothrow); |
144 | #endif |
145 | } |
146 | |