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
17TEST(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
25static const char* kGetAllocatedSizeErrorMsg =
26  "attempting to call __sanitizer_get_allocated_size";
27
28TEST(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
74TEST(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
89TEST(AddressSanitizerInterface, GetHeapSizeTest) {
90  // asan_allocator2 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
103static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<14, 357};
104static const size_t kManyThreadsIterations = 250;
105static const size_t kManyThreadsNumThreads =
106  (SANITIZER_WORDSIZE == 32) ? 40 : 200;
107
108static 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
120TEST(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
137static void DoDoubleFree() {
138  int *x = Ident(new int);
139  delete Ident(x);
140  delete Ident(x);
141}
142
143TEST(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
153static void MyDeathCallback() {
154  fprintf(stderr, "MyDeathCallback\n");
155  fflush(0);  // On Windows, stderr doesn't flush on crash.
156}
157
158TEST(AddressSanitizerInterface, DeathCallbackTest) {
159  __asan_set_death_callback(MyDeathCallback);
160  EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback");
161  __asan_set_death_callback(NULL);
162}
163
164static 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
172TEST(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
190TEST(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
211TEST(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.
232static 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
245TEST(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
284TEST(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
331TEST(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.
361TEST(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.
370TEST(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}
377static const char *kInvalidPoisonMessage = "invalid-poison-memory-range";
378static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range";
379
380TEST(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.
398static 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
406TEST(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
414TEST(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