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