1 //===-- asan_interface_test.cc --------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "asan_test_utils.h"
14 #include <sanitizer/allocator_interface.h>
15 #include <sanitizer/asan_interface.h>
16
TEST(AddressSanitizerInterface,GetEstimatedAllocatedSize)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]));
22 }
23 }
24
25 static const char* kGetAllocatedSizeErrorMsg =
26 "attempting to call __sanitizer_get_allocated_size";
27
TEST(AddressSanitizerInterface,GetAllocatedSizeAndOwnershipTest)28 TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
29 const size_t kArraySize = 100;
30 char *array = Ident((char*)malloc(kArraySize));
31 int *int_ptr = Ident(new int);
32
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));
39
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);
49
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));
54
55 // When memory is freed, it's not owned, and call to GetAllocatedSize
56 // is forbidden.
57 free(array);
58 EXPECT_FALSE(__sanitizer_get_ownership(array));
59 EXPECT_DEATH(__sanitizer_get_allocated_size(array),
60 kGetAllocatedSizeErrorMsg);
61 delete int_ptr;
62
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
66 // allocated size.
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);
70 }
71 free(zero_alloc);
72 }
73
TEST(AddressSanitizerInterface,GetCurrentAllocatedBytesTest)74 TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) {
75 size_t before_malloc, after_malloc, after_free;
76 char *array;
77 const size_t kMallocSize = 100;
78 before_malloc = __sanitizer_get_current_allocated_bytes();
79
80 array = Ident((char*)malloc(kMallocSize));
81 after_malloc = __sanitizer_get_current_allocated_bytes();
82 EXPECT_EQ(before_malloc + kMallocSize, after_malloc);
83
84 free(array);
85 after_free = __sanitizer_get_current_allocated_bytes();
86 EXPECT_EQ(before_malloc, after_free);
87 }
88
TEST(AddressSanitizerInterface,GetHeapSizeTest)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());
100 }
101 }
102
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;
107
ManyThreadsWithStatsWorker(void * arg)108 static void *ManyThreadsWithStatsWorker(void *arg) {
109 (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])));
113 }
114 }
115 // Just one large allocation.
116 free(Ident(malloc(1 << 20)));
117 return 0;
118 }
119
TEST(AddressSanitizerInterface,ManyThreadsWithStatsStressTest)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);
127 }
128 for (i = 0; i < kManyThreadsNumThreads; i++) {
129 PTHREAD_JOIN(threads[i], 0);
130 }
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));
135 }
136
DoDoubleFree()137 static void DoDoubleFree() {
138 int *x = Ident(new int);
139 delete Ident(x);
140 delete Ident(x);
141 }
142
TEST(AddressSanitizerInterface,ExitCode)143 TEST(AddressSanitizerInterface, ExitCode) {
144 int original_exit_code = __asan_set_error_exit_code(7);
145 EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(7), "");
146 EXPECT_EQ(7, __asan_set_error_exit_code(8));
147 EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(8), "");
148 EXPECT_EQ(8, __asan_set_error_exit_code(original_exit_code));
149 EXPECT_EXIT(DoDoubleFree(),
150 ::testing::ExitedWithCode(original_exit_code), "");
151 }
152
MyDeathCallback()153 static void MyDeathCallback() {
154 fprintf(stderr, "MyDeathCallback\n");
155 fflush(0); // On Windows, stderr doesn't flush on crash.
156 }
157
TEST(AddressSanitizerInterface,DeathCallbackTest)158 TEST(AddressSanitizerInterface, DeathCallbackTest) {
159 __asan_set_death_callback(MyDeathCallback);
160 EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback");
161 __asan_set_death_callback(NULL);
162 }
163
164 static const char* kUseAfterPoisonErrorMessage = "use-after-poison";
165
166 #define GOOD_ACCESS(ptr, offset) \
167 EXPECT_FALSE(__asan_address_is_poisoned(ptr + offset))
168
169 #define BAD_ACCESS(ptr, offset) \
170 EXPECT_TRUE(__asan_address_is_poisoned(ptr + offset))
171
TEST(AddressSanitizerInterface,SimplePoisonMemoryRegionTest)172 TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) {
173 char *array = Ident((char*)malloc(120));
174 // poison array[40..80)
175 __asan_poison_memory_region(array + 40, 40);
176 GOOD_ACCESS(array, 39);
177 GOOD_ACCESS(array, 80);
178 BAD_ACCESS(array, 40);
179 BAD_ACCESS(array, 60);
180 BAD_ACCESS(array, 79);
181 char value;
182 EXPECT_DEATH(value = Ident(array[40]), kUseAfterPoisonErrorMessage);
183 __asan_unpoison_memory_region(array + 40, 40);
184 // access previously poisoned memory.
185 GOOD_ACCESS(array, 40);
186 GOOD_ACCESS(array, 79);
187 free(array);
188 }
189
TEST(AddressSanitizerInterface,OverlappingPoisonMemoryRegionTest)190 TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) {
191 char *array = Ident((char*)malloc(120));
192 // Poison [0..40) and [80..120)
193 __asan_poison_memory_region(array, 40);
194 __asan_poison_memory_region(array + 80, 40);
195 BAD_ACCESS(array, 20);
196 GOOD_ACCESS(array, 60);
197 BAD_ACCESS(array, 100);
198 // Poison whole array - [0..120)
199 __asan_poison_memory_region(array, 120);
200 BAD_ACCESS(array, 60);
201 // Unpoison [24..96)
202 __asan_unpoison_memory_region(array + 24, 72);
203 BAD_ACCESS(array, 23);
204 GOOD_ACCESS(array, 24);
205 GOOD_ACCESS(array, 60);
206 GOOD_ACCESS(array, 95);
207 BAD_ACCESS(array, 96);
208 free(array);
209 }
210
TEST(AddressSanitizerInterface,PushAndPopWithPoisoningTest)211 TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) {
212 // Vector of capacity 20
213 char *vec = Ident((char*)malloc(20));
214 __asan_poison_memory_region(vec, 20);
215 for (size_t i = 0; i < 7; i++) {
216 // Simulate push_back.
217 __asan_unpoison_memory_region(vec + i, 1);
218 GOOD_ACCESS(vec, i);
219 BAD_ACCESS(vec, i + 1);
220 }
221 for (size_t i = 7; i > 0; i--) {
222 // Simulate pop_back.
223 __asan_poison_memory_region(vec + i - 1, 1);
224 BAD_ACCESS(vec, i - 1);
225 if (i > 1) GOOD_ACCESS(vec, i - 2);
226 }
227 free(vec);
228 }
229
230 // Make sure that each aligned block of size "2^granularity" doesn't have
231 // "true" value before "false" value.
MakeShadowValid(bool * shadow,int length,int granularity)232 static void MakeShadowValid(bool *shadow, int length, int granularity) {
233 bool can_be_poisoned = true;
234 for (int i = length - 1; i >= 0; i--) {
235 if (!shadow[i])
236 can_be_poisoned = false;
237 if (!can_be_poisoned)
238 shadow[i] = false;
239 if (i % (1 << granularity) == 0) {
240 can_be_poisoned = true;
241 }
242 }
243 }
244
TEST(AddressSanitizerInterface,PoisoningStressTest)245 TEST(AddressSanitizerInterface, PoisoningStressTest) {
246 const size_t kSize = 24;
247 bool expected[kSize];
248 char *arr = Ident((char*)malloc(kSize));
249 for (size_t l1 = 0; l1 < kSize; l1++) {
250 for (size_t s1 = 1; l1 + s1 <= kSize; s1++) {
251 for (size_t l2 = 0; l2 < kSize; l2++) {
252 for (size_t s2 = 1; l2 + s2 <= kSize; s2++) {
253 // Poison [l1, l1+s1), [l2, l2+s2) and check result.
254 __asan_unpoison_memory_region(arr, kSize);
255 __asan_poison_memory_region(arr + l1, s1);
256 __asan_poison_memory_region(arr + l2, s2);
257 memset(expected, false, kSize);
258 memset(expected + l1, true, s1);
259 MakeShadowValid(expected, kSize, /*granularity*/ 3);
260 memset(expected + l2, true, s2);
261 MakeShadowValid(expected, kSize, /*granularity*/ 3);
262 for (size_t i = 0; i < kSize; i++) {
263 ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
264 }
265 // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result.
266 __asan_poison_memory_region(arr, kSize);
267 __asan_unpoison_memory_region(arr + l1, s1);
268 __asan_unpoison_memory_region(arr + l2, s2);
269 memset(expected, true, kSize);
270 memset(expected + l1, false, s1);
271 MakeShadowValid(expected, kSize, /*granularity*/ 3);
272 memset(expected + l2, false, s2);
273 MakeShadowValid(expected, kSize, /*granularity*/ 3);
274 for (size_t i = 0; i < kSize; i++) {
275 ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
276 }
277 }
278 }
279 }
280 }
281 free(arr);
282 }
283
TEST(AddressSanitizerInterface,GlobalRedzones)284 TEST(AddressSanitizerInterface, GlobalRedzones) {
285 GOOD_ACCESS(glob1, 1 - 1);
286 GOOD_ACCESS(glob2, 2 - 1);
287 GOOD_ACCESS(glob3, 3 - 1);
288 GOOD_ACCESS(glob4, 4 - 1);
289 GOOD_ACCESS(glob5, 5 - 1);
290 GOOD_ACCESS(glob6, 6 - 1);
291 GOOD_ACCESS(glob7, 7 - 1);
292 GOOD_ACCESS(glob8, 8 - 1);
293 GOOD_ACCESS(glob9, 9 - 1);
294 GOOD_ACCESS(glob10, 10 - 1);
295 GOOD_ACCESS(glob11, 11 - 1);
296 GOOD_ACCESS(glob12, 12 - 1);
297 GOOD_ACCESS(glob13, 13 - 1);
298 GOOD_ACCESS(glob14, 14 - 1);
299 GOOD_ACCESS(glob15, 15 - 1);
300 GOOD_ACCESS(glob16, 16 - 1);
301 GOOD_ACCESS(glob17, 17 - 1);
302 GOOD_ACCESS(glob1000, 1000 - 1);
303 GOOD_ACCESS(glob10000, 10000 - 1);
304 GOOD_ACCESS(glob100000, 100000 - 1);
305
306 BAD_ACCESS(glob1, 1);
307 BAD_ACCESS(glob2, 2);
308 BAD_ACCESS(glob3, 3);
309 BAD_ACCESS(glob4, 4);
310 BAD_ACCESS(glob5, 5);
311 BAD_ACCESS(glob6, 6);
312 BAD_ACCESS(glob7, 7);
313 BAD_ACCESS(glob8, 8);
314 BAD_ACCESS(glob9, 9);
315 BAD_ACCESS(glob10, 10);
316 BAD_ACCESS(glob11, 11);
317 BAD_ACCESS(glob12, 12);
318 BAD_ACCESS(glob13, 13);
319 BAD_ACCESS(glob14, 14);
320 BAD_ACCESS(glob15, 15);
321 BAD_ACCESS(glob16, 16);
322 BAD_ACCESS(glob17, 17);
323 BAD_ACCESS(glob1000, 1000);
324 BAD_ACCESS(glob1000, 1100); // Redzone is at least 101 bytes.
325 BAD_ACCESS(glob10000, 10000);
326 BAD_ACCESS(glob10000, 11000); // Redzone is at least 1001 bytes.
327 BAD_ACCESS(glob100000, 100000);
328 BAD_ACCESS(glob100000, 110000); // Redzone is at least 10001 bytes.
329 }
330
TEST(AddressSanitizerInterface,PoisonedRegion)331 TEST(AddressSanitizerInterface, PoisonedRegion) {
332 size_t rz = 16;
333 for (size_t size = 1; size <= 64; size++) {
334 char *p = new char[size];
335 for (size_t beg = 0; beg < size + rz; beg++) {
336 for (size_t end = beg; end < size + rz; end++) {
337 void *first_poisoned = __asan_region_is_poisoned(p + beg, end - beg);
338 if (beg == end) {
339 EXPECT_FALSE(first_poisoned);
340 } else if (beg < size && end <= size) {
341 EXPECT_FALSE(first_poisoned);
342 } else if (beg >= size) {
343 EXPECT_EQ(p + beg, first_poisoned);
344 } else {
345 EXPECT_GT(end, size);
346 EXPECT_EQ(p + size, first_poisoned);
347 }
348 }
349 }
350 delete [] p;
351 }
352 }
353
354 // This is a performance benchmark for manual runs.
355 // asan's memset interceptor calls mem_is_zero for the entire shadow region.
356 // the profile should look like this:
357 // 89.10% [.] __memset_sse2
358 // 10.50% [.] __sanitizer::mem_is_zero
359 // I.e. mem_is_zero should consume ~ SHADOW_GRANULARITY less CPU cycles
360 // than memset itself.
TEST(AddressSanitizerInterface,DISABLED_StressLargeMemset)361 TEST(AddressSanitizerInterface, DISABLED_StressLargeMemset) {
362 size_t size = 1 << 20;
363 char *x = new char[size];
364 for (int i = 0; i < 100000; i++)
365 Ident(memset)(x, 0, size);
366 delete [] x;
367 }
368
369 // Same here, but we run memset with small sizes.
TEST(AddressSanitizerInterface,DISABLED_StressSmallMemset)370 TEST(AddressSanitizerInterface, DISABLED_StressSmallMemset) {
371 size_t size = 32;
372 char *x = new char[size];
373 for (int i = 0; i < 100000000; i++)
374 Ident(memset)(x, 0, size);
375 delete [] x;
376 }
377 static const char *kInvalidPoisonMessage = "invalid-poison-memory-range";
378 static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range";
379
TEST(AddressSanitizerInterface,DISABLED_InvalidPoisonAndUnpoisonCallsTest)380 TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) {
381 char *array = Ident((char*)malloc(120));
382 __asan_unpoison_memory_region(array, 120);
383 // Try to unpoison not owned memory
384 EXPECT_DEATH(__asan_unpoison_memory_region(array, 121),
385 kInvalidUnpoisonMessage);
386 EXPECT_DEATH(__asan_unpoison_memory_region(array - 1, 120),
387 kInvalidUnpoisonMessage);
388
389 __asan_poison_memory_region(array, 120);
390 // Try to poison not owned memory.
391 EXPECT_DEATH(__asan_poison_memory_region(array, 121), kInvalidPoisonMessage);
392 EXPECT_DEATH(__asan_poison_memory_region(array - 1, 120),
393 kInvalidPoisonMessage);
394 free(array);
395 }
396
397 #if !defined(_WIN32) // FIXME: This should really be a lit test.
ErrorReportCallbackOneToZ(const char * report)398 static void ErrorReportCallbackOneToZ(const char *report) {
399 int report_len = strlen(report);
400 ASSERT_EQ(6, write(2, "ABCDEF", 6));
401 ASSERT_EQ(report_len, write(2, report, report_len));
402 ASSERT_EQ(6, write(2, "ABCDEF", 6));
403 _exit(1);
404 }
405
TEST(AddressSanitizerInterface,SetErrorReportCallbackTest)406 TEST(AddressSanitizerInterface, SetErrorReportCallbackTest) {
407 __asan_set_error_report_callback(ErrorReportCallbackOneToZ);
408 EXPECT_DEATH(__asan_report_error(0, 0, 0, 0, true, 1),
409 ASAN_PCRE_DOTALL "ABCDEF.*AddressSanitizer.*WRITE.*ABCDEF");
410 __asan_set_error_report_callback(NULL);
411 }
412 #endif
413
TEST(AddressSanitizerInterface,GetOwnershipStressTest)414 TEST(AddressSanitizerInterface, GetOwnershipStressTest) {
415 std::vector<char *> pointers;
416 std::vector<size_t> sizes;
417 const size_t kNumMallocs = 1 << 9;
418 for (size_t i = 0; i < kNumMallocs; i++) {
419 size_t size = i * 100 + 1;
420 pointers.push_back((char*)malloc(size));
421 sizes.push_back(size);
422 }
423 for (size_t i = 0; i < 4000000; i++) {
424 EXPECT_FALSE(__sanitizer_get_ownership(&pointers));
425 EXPECT_FALSE(__sanitizer_get_ownership((void*)0x1234));
426 size_t idx = i % kNumMallocs;
427 EXPECT_TRUE(__sanitizer_get_ownership(pointers[idx]));
428 EXPECT_EQ(sizes[idx], __sanitizer_get_allocated_size(pointers[idx]));
429 }
430 for (size_t i = 0, n = pointers.size(); i < n; i++)
431 free(pointers[i]);
432 }
433
434