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