1 //===-- asan_interface_test.cc --------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of AddressSanitizer, an address sanity checker.
12 //===----------------------------------------------------------------------===//
13 #include "asan_test_utils.h"
14 #include <sanitizer/allocator_interface.h>
15 #include <sanitizer/asan_interface.h>
17 TEST(AddressSanitizerInterface
, GetEstimatedAllocatedSize
) {
18 EXPECT_EQ(0U, __sanitizer_get_estimated_allocated_size(0));
19 const size_t sizes
[] = { 1, 30, 1<<30 };
20 for (size_t i
= 0; i
< 3; i
++) {
21 EXPECT_EQ(sizes
[i
], __sanitizer_get_estimated_allocated_size(sizes
[i
]));
25 static const char* kGetAllocatedSizeErrorMsg
=
26 "attempting to call __sanitizer_get_allocated_size";
28 TEST(AddressSanitizerInterface
, GetAllocatedSizeAndOwnershipTest
) {
29 const size_t kArraySize
= 100;
30 char *array
= Ident((char*)malloc(kArraySize
));
31 int *int_ptr
= Ident(new int);
33 // Allocated memory is owned by allocator. Allocated size should be
34 // equal to requested size.
35 EXPECT_EQ(true, __sanitizer_get_ownership(array
));
36 EXPECT_EQ(kArraySize
, __sanitizer_get_allocated_size(array
));
37 EXPECT_EQ(true, __sanitizer_get_ownership(int_ptr
));
38 EXPECT_EQ(sizeof(int), __sanitizer_get_allocated_size(int_ptr
));
40 // We cannot call GetAllocatedSize from the memory we didn't map,
41 // and from the interior pointers (not returned by previous malloc).
42 void *wild_addr
= (void*)0x1;
43 EXPECT_FALSE(__sanitizer_get_ownership(wild_addr
));
44 EXPECT_DEATH(__sanitizer_get_allocated_size(wild_addr
),
45 kGetAllocatedSizeErrorMsg
);
46 EXPECT_FALSE(__sanitizer_get_ownership(array
+ kArraySize
/ 2));
47 EXPECT_DEATH(__sanitizer_get_allocated_size(array
+ kArraySize
/ 2),
48 kGetAllocatedSizeErrorMsg
);
50 // NULL is not owned, but is a valid argument for
51 // __sanitizer_get_allocated_size().
52 EXPECT_FALSE(__sanitizer_get_ownership(NULL
));
53 EXPECT_EQ(0U, __sanitizer_get_allocated_size(NULL
));
55 // When memory is freed, it's not owned, and call to GetAllocatedSize
58 EXPECT_FALSE(__sanitizer_get_ownership(array
));
59 EXPECT_DEATH(__sanitizer_get_allocated_size(array
),
60 kGetAllocatedSizeErrorMsg
);
63 void *zero_alloc
= Ident(malloc(0));
64 if (zero_alloc
!= 0) {
65 // If malloc(0) is not null, this pointer is owned and should have valid
67 EXPECT_TRUE(__sanitizer_get_ownership(zero_alloc
));
68 // Allocated size is 0 or 1 depending on the allocator used.
69 EXPECT_LT(__sanitizer_get_allocated_size(zero_alloc
), 2U);
74 TEST(AddressSanitizerInterface
, GetCurrentAllocatedBytesTest
) {
75 size_t before_malloc
, after_malloc
, after_free
;
77 const size_t kMallocSize
= 100;
78 before_malloc
= __sanitizer_get_current_allocated_bytes();
80 array
= Ident((char*)malloc(kMallocSize
));
81 after_malloc
= __sanitizer_get_current_allocated_bytes();
82 EXPECT_EQ(before_malloc
+ kMallocSize
, after_malloc
);
85 after_free
= __sanitizer_get_current_allocated_bytes();
86 EXPECT_EQ(before_malloc
, after_free
);
89 TEST(AddressSanitizerInterface
, GetHeapSizeTest
) {
90 // ASan allocator does not keep huge chunks in free list, but unmaps them.
91 // The chunk should be greater than the quarantine size,
92 // otherwise it will be stuck in quarantine instead of being unmaped.
93 static const size_t kLargeMallocSize
= (1 << 28) + 1; // 256M
94 free(Ident(malloc(kLargeMallocSize
))); // Drain quarantine.
95 size_t old_heap_size
= __sanitizer_get_heap_size();
96 for (int i
= 0; i
< 3; i
++) {
97 // fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
98 free(Ident(malloc(kLargeMallocSize
)));
99 EXPECT_EQ(old_heap_size
, __sanitizer_get_heap_size());
103 static const size_t kManyThreadsMallocSizes
[] = {5, 1UL<<10, 1UL<<14, 357};
104 static const size_t kManyThreadsIterations
= 250;
105 static const size_t kManyThreadsNumThreads
=
106 (SANITIZER_WORDSIZE
== 32) ? 40 : 200;
108 static void *ManyThreadsWithStatsWorker(void *arg
) {
110 for (size_t iter
= 0; iter
< kManyThreadsIterations
; iter
++) {
111 for (size_t size_index
= 0; size_index
< 4; size_index
++) {
112 free(Ident(malloc(kManyThreadsMallocSizes
[size_index
])));
115 // Just one large allocation.
116 free(Ident(malloc(1 << 20)));
120 TEST(AddressSanitizerInterface
, ManyThreadsWithStatsStressTest
) {
121 size_t before_test
, after_test
, i
;
122 pthread_t threads
[kManyThreadsNumThreads
];
123 before_test
= __sanitizer_get_current_allocated_bytes();
124 for (i
= 0; i
< kManyThreadsNumThreads
; i
++) {
125 PTHREAD_CREATE(&threads
[i
], 0,
126 (void* (*)(void *x
))ManyThreadsWithStatsWorker
, (void*)i
);
128 for (i
= 0; i
< kManyThreadsNumThreads
; i
++) {
129 PTHREAD_JOIN(threads
[i
], 0);
131 after_test
= __sanitizer_get_current_allocated_bytes();
132 // ASan stats also reflect memory usage of internal ASan RTL structs,
133 // so we can't check for equality here.
134 EXPECT_LT(after_test
, before_test
+ (1UL<<20));
137 static void DoDoubleFree() {
138 int *x
= Ident(new int);
143 static void MyDeathCallback() {
144 fprintf(stderr
, "MyDeathCallback\n");
145 fflush(0); // On Windows, stderr doesn't flush on crash.
148 TEST(AddressSanitizerInterface
, DeathCallbackTest
) {
149 __asan_set_death_callback(MyDeathCallback
);
150 EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback");
151 __asan_set_death_callback(NULL
);
154 static const char* kUseAfterPoisonErrorMessage
= "use-after-poison";
156 #define GOOD_ACCESS(ptr, offset) \
157 EXPECT_FALSE(__asan_address_is_poisoned(ptr + offset))
159 #define BAD_ACCESS(ptr, offset) \
160 EXPECT_TRUE(__asan_address_is_poisoned(ptr + offset))
162 TEST(AddressSanitizerInterface
, SimplePoisonMemoryRegionTest
) {
163 char *array
= Ident((char*)malloc(120));
164 // poison array[40..80)
165 __asan_poison_memory_region(array
+ 40, 40);
166 GOOD_ACCESS(array
, 39);
167 GOOD_ACCESS(array
, 80);
168 BAD_ACCESS(array
, 40);
169 BAD_ACCESS(array
, 60);
170 BAD_ACCESS(array
, 79);
172 EXPECT_DEATH(value
= Ident(array
[40]), kUseAfterPoisonErrorMessage
);
173 __asan_unpoison_memory_region(array
+ 40, 40);
174 // access previously poisoned memory.
175 GOOD_ACCESS(array
, 40);
176 GOOD_ACCESS(array
, 79);
180 TEST(AddressSanitizerInterface
, OverlappingPoisonMemoryRegionTest
) {
181 char *array
= Ident((char*)malloc(120));
182 // Poison [0..40) and [80..120)
183 __asan_poison_memory_region(array
, 40);
184 __asan_poison_memory_region(array
+ 80, 40);
185 BAD_ACCESS(array
, 20);
186 GOOD_ACCESS(array
, 60);
187 BAD_ACCESS(array
, 100);
188 // Poison whole array - [0..120)
189 __asan_poison_memory_region(array
, 120);
190 BAD_ACCESS(array
, 60);
192 __asan_unpoison_memory_region(array
+ 24, 72);
193 BAD_ACCESS(array
, 23);
194 GOOD_ACCESS(array
, 24);
195 GOOD_ACCESS(array
, 60);
196 GOOD_ACCESS(array
, 95);
197 BAD_ACCESS(array
, 96);
201 TEST(AddressSanitizerInterface
, PushAndPopWithPoisoningTest
) {
202 // Vector of capacity 20
203 char *vec
= Ident((char*)malloc(20));
204 __asan_poison_memory_region(vec
, 20);
205 for (size_t i
= 0; i
< 7; i
++) {
206 // Simulate push_back.
207 __asan_unpoison_memory_region(vec
+ i
, 1);
209 BAD_ACCESS(vec
, i
+ 1);
211 for (size_t i
= 7; i
> 0; i
--) {
212 // Simulate pop_back.
213 __asan_poison_memory_region(vec
+ i
- 1, 1);
214 BAD_ACCESS(vec
, i
- 1);
215 if (i
> 1) GOOD_ACCESS(vec
, i
- 2);
220 // Make sure that each aligned block of size "2^granularity" doesn't have
221 // "true" value before "false" value.
222 static void MakeShadowValid(bool *shadow
, int length
, int granularity
) {
223 bool can_be_poisoned
= true;
224 for (int i
= length
- 1; i
>= 0; i
--) {
226 can_be_poisoned
= false;
227 if (!can_be_poisoned
)
229 if (i
% (1 << granularity
) == 0) {
230 can_be_poisoned
= true;
235 TEST(AddressSanitizerInterface
, PoisoningStressTest
) {
236 const size_t kSize
= 24;
237 bool expected
[kSize
];
238 char *arr
= Ident((char*)malloc(kSize
));
239 for (size_t l1
= 0; l1
< kSize
; l1
++) {
240 for (size_t s1
= 1; l1
+ s1
<= kSize
; s1
++) {
241 for (size_t l2
= 0; l2
< kSize
; l2
++) {
242 for (size_t s2
= 1; l2
+ s2
<= kSize
; s2
++) {
243 // Poison [l1, l1+s1), [l2, l2+s2) and check result.
244 __asan_unpoison_memory_region(arr
, kSize
);
245 __asan_poison_memory_region(arr
+ l1
, s1
);
246 __asan_poison_memory_region(arr
+ l2
, s2
);
247 memset(expected
, false, kSize
);
248 memset(expected
+ l1
, true, s1
);
249 MakeShadowValid(expected
, kSize
, /*granularity*/ 3);
250 memset(expected
+ l2
, true, s2
);
251 MakeShadowValid(expected
, kSize
, /*granularity*/ 3);
252 for (size_t i
= 0; i
< kSize
; i
++) {
253 ASSERT_EQ(expected
[i
], __asan_address_is_poisoned(arr
+ i
));
255 // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result.
256 __asan_poison_memory_region(arr
, kSize
);
257 __asan_unpoison_memory_region(arr
+ l1
, s1
);
258 __asan_unpoison_memory_region(arr
+ l2
, s2
);
259 memset(expected
, true, kSize
);
260 memset(expected
+ l1
, false, s1
);
261 MakeShadowValid(expected
, kSize
, /*granularity*/ 3);
262 memset(expected
+ l2
, false, s2
);
263 MakeShadowValid(expected
, kSize
, /*granularity*/ 3);
264 for (size_t i
= 0; i
< kSize
; i
++) {
265 ASSERT_EQ(expected
[i
], __asan_address_is_poisoned(arr
+ i
));
274 TEST(AddressSanitizerInterface
, GlobalRedzones
) {
275 GOOD_ACCESS(glob1
, 1 - 1);
276 GOOD_ACCESS(glob2
, 2 - 1);
277 GOOD_ACCESS(glob3
, 3 - 1);
278 GOOD_ACCESS(glob4
, 4 - 1);
279 GOOD_ACCESS(glob5
, 5 - 1);
280 GOOD_ACCESS(glob6
, 6 - 1);
281 GOOD_ACCESS(glob7
, 7 - 1);
282 GOOD_ACCESS(glob8
, 8 - 1);
283 GOOD_ACCESS(glob9
, 9 - 1);
284 GOOD_ACCESS(glob10
, 10 - 1);
285 GOOD_ACCESS(glob11
, 11 - 1);
286 GOOD_ACCESS(glob12
, 12 - 1);
287 GOOD_ACCESS(glob13
, 13 - 1);
288 GOOD_ACCESS(glob14
, 14 - 1);
289 GOOD_ACCESS(glob15
, 15 - 1);
290 GOOD_ACCESS(glob16
, 16 - 1);
291 GOOD_ACCESS(glob17
, 17 - 1);
292 GOOD_ACCESS(glob1000
, 1000 - 1);
293 GOOD_ACCESS(glob10000
, 10000 - 1);
294 GOOD_ACCESS(glob100000
, 100000 - 1);
296 BAD_ACCESS(glob1
, 1);
297 BAD_ACCESS(glob2
, 2);
298 BAD_ACCESS(glob3
, 3);
299 BAD_ACCESS(glob4
, 4);
300 BAD_ACCESS(glob5
, 5);
301 BAD_ACCESS(glob6
, 6);
302 BAD_ACCESS(glob7
, 7);
303 BAD_ACCESS(glob8
, 8);
304 BAD_ACCESS(glob9
, 9);
305 BAD_ACCESS(glob10
, 10);
306 BAD_ACCESS(glob11
, 11);
307 BAD_ACCESS(glob12
, 12);
308 BAD_ACCESS(glob13
, 13);
309 BAD_ACCESS(glob14
, 14);
310 BAD_ACCESS(glob15
, 15);
311 BAD_ACCESS(glob16
, 16);
312 BAD_ACCESS(glob17
, 17);
313 BAD_ACCESS(glob1000
, 1000);
314 BAD_ACCESS(glob1000
, 1100); // Redzone is at least 101 bytes.
315 BAD_ACCESS(glob10000
, 10000);
316 BAD_ACCESS(glob10000
, 11000); // Redzone is at least 1001 bytes.
317 BAD_ACCESS(glob100000
, 100000);
318 BAD_ACCESS(glob100000
, 110000); // Redzone is at least 10001 bytes.
321 TEST(AddressSanitizerInterface
, PoisonedRegion
) {
323 for (size_t size
= 1; size
<= 64; size
++) {
324 char *p
= new char[size
];
325 for (size_t beg
= 0; beg
< size
+ rz
; beg
++) {
326 for (size_t end
= beg
; end
< size
+ rz
; end
++) {
327 void *first_poisoned
= __asan_region_is_poisoned(p
+ beg
, end
- beg
);
329 EXPECT_FALSE(first_poisoned
);
330 } else if (beg
< size
&& end
<= size
) {
331 EXPECT_FALSE(first_poisoned
);
332 } else if (beg
>= size
) {
333 EXPECT_EQ(p
+ beg
, first_poisoned
);
335 EXPECT_GT(end
, size
);
336 EXPECT_EQ(p
+ size
, first_poisoned
);
344 // This is a performance benchmark for manual runs.
345 // asan's memset interceptor calls mem_is_zero for the entire shadow region.
346 // the profile should look like this:
347 // 89.10% [.] __memset_sse2
348 // 10.50% [.] __sanitizer::mem_is_zero
349 // I.e. mem_is_zero should consume ~ SHADOW_GRANULARITY less CPU cycles
350 // than memset itself.
351 TEST(AddressSanitizerInterface
, DISABLED_StressLargeMemset
) {
352 size_t size
= 1 << 20;
353 char *x
= new char[size
];
354 for (int i
= 0; i
< 100000; i
++)
355 Ident(memset
)(x
, 0, size
);
359 // Same here, but we run memset with small sizes.
360 TEST(AddressSanitizerInterface
, DISABLED_StressSmallMemset
) {
362 char *x
= new char[size
];
363 for (int i
= 0; i
< 100000000; i
++)
364 Ident(memset
)(x
, 0, size
);
367 static const char *kInvalidPoisonMessage
= "invalid-poison-memory-range";
368 static const char *kInvalidUnpoisonMessage
= "invalid-unpoison-memory-range";
370 TEST(AddressSanitizerInterface
, DISABLED_InvalidPoisonAndUnpoisonCallsTest
) {
371 char *array
= Ident((char*)malloc(120));
372 __asan_unpoison_memory_region(array
, 120);
373 // Try to unpoison not owned memory
374 EXPECT_DEATH(__asan_unpoison_memory_region(array
, 121),
375 kInvalidUnpoisonMessage
);
376 EXPECT_DEATH(__asan_unpoison_memory_region(array
- 1, 120),
377 kInvalidUnpoisonMessage
);
379 __asan_poison_memory_region(array
, 120);
380 // Try to poison not owned memory.
381 EXPECT_DEATH(__asan_poison_memory_region(array
, 121), kInvalidPoisonMessage
);
382 EXPECT_DEATH(__asan_poison_memory_region(array
- 1, 120),
383 kInvalidPoisonMessage
);
387 #if !defined(_WIN32) // FIXME: This should really be a lit test.
388 static void ErrorReportCallbackOneToZ(const char *report
) {
389 int report_len
= strlen(report
);
390 ASSERT_EQ(6, write(2, "ABCDEF", 6));
391 ASSERT_EQ(report_len
, write(2, report
, report_len
));
392 ASSERT_EQ(6, write(2, "ABCDEF", 6));
396 TEST(AddressSanitizerInterface
, SetErrorReportCallbackTest
) {
397 __asan_set_error_report_callback(ErrorReportCallbackOneToZ
);
398 EXPECT_DEATH(__asan_report_error(0, 0, 0, 0, true, 1),
399 ASAN_PCRE_DOTALL
"ABCDEF.*AddressSanitizer.*WRITE.*ABCDEF");
400 __asan_set_error_report_callback(NULL
);
404 TEST(AddressSanitizerInterface
, GetOwnershipStressTest
) {
405 std::vector
<char *> pointers
;
406 std::vector
<size_t> sizes
;
407 const size_t kNumMallocs
= 1 << 9;
408 for (size_t i
= 0; i
< kNumMallocs
; i
++) {
409 size_t size
= i
* 100 + 1;
410 pointers
.push_back((char*)malloc(size
));
411 sizes
.push_back(size
);
413 for (size_t i
= 0; i
< 4000000; i
++) {
414 EXPECT_FALSE(__sanitizer_get_ownership(&pointers
));
415 EXPECT_FALSE(__sanitizer_get_ownership((void*)0x1234));
416 size_t idx
= i
% kNumMallocs
;
417 EXPECT_TRUE(__sanitizer_get_ownership(pointers
[idx
]));
418 EXPECT_EQ(sizes
[idx
], __sanitizer_get_allocated_size(pointers
[idx
]));
420 for (size_t i
= 0, n
= pointers
.size(); i
< n
; i
++)