asan_interface_test.cc revision 3fe913558354f76707e2c5584559521399854b79
1//===-- asan_interface_test.cc ------------*- C++ -*-===//
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 <pthread.h>
14#include <stdio.h>
15#include <string.h>
16
17#include "asan_test_config.h"
18#include "asan_test_utils.h"
19#include "asan_interface.h"
20
21TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) {
22  EXPECT_EQ(1, __asan_get_estimated_allocated_size(0));
23  const size_t sizes[] = { 1, 30, 1<<30 };
24  for (size_t i = 0; i < 3; i++) {
25    EXPECT_EQ(sizes[i], __asan_get_estimated_allocated_size(sizes[i]));
26  }
27}
28
29static const char* kGetAllocatedSizeErrorMsg =
30  "attempting to call __asan_get_allocated_size()";
31
32TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
33  const size_t kArraySize = 100;
34  char *array = Ident((char*)malloc(kArraySize));
35  int *int_ptr = Ident(new int);
36
37  // Allocated memory is owned by allocator. Allocated size should be
38  // equal to requested size.
39  EXPECT_EQ(true, __asan_get_ownership(array));
40  EXPECT_EQ(kArraySize, __asan_get_allocated_size(array));
41  EXPECT_EQ(true, __asan_get_ownership(int_ptr));
42  EXPECT_EQ(sizeof(int), __asan_get_allocated_size(int_ptr));
43
44  // We cannot call GetAllocatedSize from the memory we didn't map,
45  // and from the interior pointers (not returned by previous malloc).
46  void *wild_addr = (void*)0x1;
47  EXPECT_EQ(false, __asan_get_ownership(wild_addr));
48  EXPECT_DEATH(__asan_get_allocated_size(wild_addr), kGetAllocatedSizeErrorMsg);
49  EXPECT_EQ(false, __asan_get_ownership(array + kArraySize / 2));
50  EXPECT_DEATH(__asan_get_allocated_size(array + kArraySize / 2),
51               kGetAllocatedSizeErrorMsg);
52
53  // NULL is not owned, but is a valid argument for __asan_get_allocated_size().
54  EXPECT_EQ(false, __asan_get_ownership(NULL));
55  EXPECT_EQ(0, __asan_get_allocated_size(NULL));
56
57  // When memory is freed, it's not owned, and call to GetAllocatedSize
58  // is forbidden.
59  free(array);
60  EXPECT_EQ(false, __asan_get_ownership(array));
61  EXPECT_DEATH(__asan_get_allocated_size(array), kGetAllocatedSizeErrorMsg);
62
63  delete int_ptr;
64}
65
66TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) {
67  size_t before_malloc, after_malloc, after_free;
68  char *array;
69  const size_t kMallocSize = 100;
70  before_malloc = __asan_get_current_allocated_bytes();
71
72  array = Ident((char*)malloc(kMallocSize));
73  after_malloc = __asan_get_current_allocated_bytes();
74  EXPECT_EQ(before_malloc + kMallocSize, after_malloc);
75
76  free(array);
77  after_free = __asan_get_current_allocated_bytes();
78  EXPECT_EQ(before_malloc, after_free);
79}
80
81static void DoDoubleFree() {
82  int *x = Ident(new int);
83  delete Ident(x);
84  delete Ident(x);
85}
86
87// This test is run in a separate process, so that large malloced
88// chunk won't remain in the free lists after the test.
89// Note: use ASSERT_* instead of EXPECT_* here.
90static void RunGetHeapSizeTestAndDie() {
91  size_t old_heap_size, new_heap_size, heap_growth;
92  // We unlikely have have chunk of this size in free list.
93  static const size_t kLargeMallocSize = 1 << 29;  // 512M
94  old_heap_size = __asan_get_heap_size();
95  fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
96  free(Ident(malloc(kLargeMallocSize)));
97  new_heap_size = __asan_get_heap_size();
98  heap_growth = new_heap_size - old_heap_size;
99  fprintf(stderr, "heap growth after first malloc: %zu\n", heap_growth);
100  ASSERT_GE(heap_growth, kLargeMallocSize);
101  ASSERT_LE(heap_growth, 2 * kLargeMallocSize);
102
103  // Now large chunk should fall into free list, and can be
104  // allocated without increasing heap size.
105  old_heap_size = new_heap_size;
106  free(Ident(malloc(kLargeMallocSize)));
107  heap_growth = __asan_get_heap_size() - old_heap_size;
108  fprintf(stderr, "heap growth after second malloc: %zu\n", heap_growth);
109  ASSERT_LT(heap_growth, kLargeMallocSize);
110
111  // Test passed. Now die with expected double-free.
112  DoDoubleFree();
113}
114
115TEST(AddressSanitizerInterface, GetHeapSizeTest) {
116  EXPECT_DEATH(RunGetHeapSizeTestAndDie(), "double-free");
117}
118
119// Note: use ASSERT_* instead of EXPECT_* here.
120static void DoLargeMallocForGetFreeBytesTestAndDie() {
121  size_t old_free_bytes, new_free_bytes;
122  static const size_t kLargeMallocSize = 1 << 29;  // 512M
123  // If we malloc and free a large memory chunk, it will not fall
124  // into quarantine and will be available for future requests.
125  old_free_bytes = __asan_get_free_bytes();
126  fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
127  fprintf(stderr, "free bytes before malloc: %zu\n", old_free_bytes);
128  free(Ident(malloc(kLargeMallocSize)));
129  new_free_bytes = __asan_get_free_bytes();
130  fprintf(stderr, "free bytes after malloc and free: %zu\n", new_free_bytes);
131  ASSERT_GE(new_free_bytes, old_free_bytes + kLargeMallocSize);
132  // Test passed.
133  DoDoubleFree();
134}
135
136TEST(AddressSanitizerInterface, GetFreeBytesTest) {
137  static const size_t kNumOfChunks = 100;
138  static const size_t kChunkSize = 100;
139  char *chunks[kNumOfChunks];
140  size_t i;
141  size_t old_free_bytes, new_free_bytes;
142  // Allocate a small chunk. Now allocator probably has a lot of these
143  // chunks to fulfill future requests. So, future requests will decrease
144  // the number of free bytes.
145  chunks[0] = Ident((char*)malloc(kChunkSize));
146  old_free_bytes = __asan_get_free_bytes();
147  for (i = 1; i < kNumOfChunks; i++) {
148    chunks[i] = Ident((char*)malloc(kChunkSize));
149    new_free_bytes = __asan_get_free_bytes();
150    EXPECT_LT(new_free_bytes, old_free_bytes);
151    old_free_bytes = new_free_bytes;
152  }
153  // Deleting these chunks will move them to quarantine, number of free
154  // bytes won't increase.
155  for (i = 0; i < kNumOfChunks; i++) {
156    free(chunks[i]);
157    EXPECT_EQ(old_free_bytes, __asan_get_free_bytes());
158  }
159  EXPECT_DEATH(DoLargeMallocForGetFreeBytesTestAndDie(), "double-free");
160}
161
162static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<20, 357};
163static const size_t kManyThreadsIterations = 250;
164static const size_t kManyThreadsNumThreads = 200;
165
166void *ManyThreadsWithStatsWorker(void *arg) {
167  for (size_t iter = 0; iter < kManyThreadsIterations; iter++) {
168    for (size_t size_index = 0; size_index < 4; size_index++) {
169      free(Ident(malloc(kManyThreadsMallocSizes[size_index])));
170    }
171  }
172  return 0;
173}
174
175TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
176  size_t before_test, after_test, i;
177  pthread_t threads[kManyThreadsNumThreads];
178  before_test = __asan_get_current_allocated_bytes();
179  for (i = 0; i < kManyThreadsNumThreads; i++) {
180    pthread_create(&threads[i], 0,
181                   (void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i);
182  }
183  for (i = 0; i < kManyThreadsNumThreads; i++) {
184    pthread_join(threads[i], 0);
185  }
186  after_test = __asan_get_current_allocated_bytes();
187  // ASan stats also reflect memory usage of internal ASan RTL structs,
188  // so we can't check for equality here.
189  EXPECT_LT(after_test, before_test + (1UL<<20));
190}
191
192TEST(AddressSanitizerInterface, ExitCode) {
193  int original_exit_code = __asan_set_error_exit_code(7);
194  EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(7), "");
195  EXPECT_EQ(7, __asan_set_error_exit_code(8));
196  EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(8), "");
197  EXPECT_EQ(8, __asan_set_error_exit_code(original_exit_code));
198  EXPECT_EXIT(DoDoubleFree(),
199              ::testing::ExitedWithCode(original_exit_code), "");
200}
201
202static void MyDeathCallback() {
203  fprintf(stderr, "MyDeathCallback\n");
204}
205
206TEST(AddressSanitizerInterface, DeathCallbackTest) {
207  __asan_set_death_callback(MyDeathCallback);
208  EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback");
209  __asan_set_death_callback(NULL);
210}
211
212static const char* kUseAfterPoisonErrorMessage = "use-after-poison";
213
214#define ACCESS(ptr, offset) Ident(*(ptr + offset))
215
216#define DIE_ON_ACCESS(ptr, offset) \
217    EXPECT_DEATH(Ident(*(ptr + offset)), kUseAfterPoisonErrorMessage)
218
219TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) {
220  char *array = Ident((char*)malloc(120));
221  // poison array[40..80)
222  ASAN_POISON_MEMORY_REGION(array + 40, 40);
223  ACCESS(array, 39);
224  ACCESS(array, 80);
225  DIE_ON_ACCESS(array, 40);
226  DIE_ON_ACCESS(array, 60);
227  DIE_ON_ACCESS(array, 79);
228  ASAN_UNPOISON_MEMORY_REGION(array + 40, 40);
229  // access previously poisoned memory.
230  ACCESS(array, 40);
231  ACCESS(array, 79);
232  free(array);
233}
234
235TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) {
236  char *array = Ident((char*)malloc(120));
237  // Poison [0..40) and [80..120)
238  ASAN_POISON_MEMORY_REGION(array, 40);
239  ASAN_POISON_MEMORY_REGION(array + 80, 40);
240  DIE_ON_ACCESS(array, 20);
241  ACCESS(array, 60);
242  DIE_ON_ACCESS(array, 100);
243  // Poison whole array - [0..120)
244  ASAN_POISON_MEMORY_REGION(array, 120);
245  DIE_ON_ACCESS(array, 60);
246  // Unpoison [24..96)
247  ASAN_UNPOISON_MEMORY_REGION(array + 24, 72);
248  DIE_ON_ACCESS(array, 23);
249  ACCESS(array, 24);
250  ACCESS(array, 60);
251  ACCESS(array, 95);
252  DIE_ON_ACCESS(array, 96);
253  free(array);
254}
255
256TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) {
257  // Vector of capacity 20
258  char *vec = Ident((char*)malloc(20));
259  ASAN_POISON_MEMORY_REGION(vec, 20);
260  for (size_t i = 0; i < 7; i++) {
261    // Simulate push_back.
262    ASAN_UNPOISON_MEMORY_REGION(vec + i, 1);
263    ACCESS(vec, i);
264    DIE_ON_ACCESS(vec, i + 1);
265  }
266  for (size_t i = 7; i > 0; i--) {
267    // Simulate pop_back.
268    ASAN_POISON_MEMORY_REGION(vec + i - 1, 1);
269    DIE_ON_ACCESS(vec, i - 1);
270    if (i > 1) ACCESS(vec, i - 2);
271  }
272  free(vec);
273}
274
275// Make sure that each aligned block of size "2^granularity" doesn't have
276// "true" value before "false" value.
277static void MakeShadowValid(bool *shadow, int length, int granularity) {
278  bool can_be_poisoned = true;
279  for (int i = length - 1; i >= 0; i--) {
280    can_be_poisoned &= shadow[i];
281    shadow[i] &= can_be_poisoned;
282    if (i % (1 << granularity) == 0) {
283      can_be_poisoned = true;
284    }
285  }
286}
287
288TEST(AddressSanitizerInterface, PoisoningStressTest) {
289  const size_t kSize = 24;
290  bool expected[kSize];
291  char *arr = Ident((char*)malloc(kSize));
292  for (size_t l1 = 0; l1 < kSize; l1++) {
293    for (size_t s1 = 1; l1 + s1 <= kSize; s1++) {
294      for (size_t l2 = 0; l2 < kSize; l2++) {
295        for (size_t s2 = 1; l2 + s2 <= kSize; s2++) {
296          // Poison [l1, l1+s1), [l2, l2+s2) and check result.
297          ASAN_UNPOISON_MEMORY_REGION(arr, kSize);
298          ASAN_POISON_MEMORY_REGION(arr + l1, s1);
299          ASAN_POISON_MEMORY_REGION(arr + l2, s2);
300          memset(expected, false, kSize);
301          memset(expected + l1, true, s1);
302          MakeShadowValid(expected, 24, /*granularity*/ 3);
303          memset(expected + l2, true, s2);
304          MakeShadowValid(expected, 24, /*granularity*/ 3);
305          for (size_t i = 0; i < kSize; i++) {
306            ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
307          }
308          // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result.
309          ASAN_POISON_MEMORY_REGION(arr, kSize);
310          ASAN_UNPOISON_MEMORY_REGION(arr + l1, s1);
311          ASAN_UNPOISON_MEMORY_REGION(arr + l2, s2);
312          memset(expected, true, kSize);
313          memset(expected + l1, false, s1);
314          MakeShadowValid(expected, 24, /*granularity*/ 3);
315          memset(expected + l2, false, s2);
316          MakeShadowValid(expected, 24, /*granularity*/ 3);
317          for (size_t i = 0; i < kSize; i++) {
318            ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
319          }
320        }
321      }
322    }
323  }
324}
325
326static const char *kInvalidPoisonMessage = "invalid-poison-memory-range";
327static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range";
328
329TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) {
330  char *array = Ident((char*)malloc(120));
331  ASAN_UNPOISON_MEMORY_REGION(array, 120);
332  // Try to unpoison not owned memory
333  EXPECT_DEATH(ASAN_UNPOISON_MEMORY_REGION(array, 121),
334               kInvalidUnpoisonMessage);
335  EXPECT_DEATH(ASAN_UNPOISON_MEMORY_REGION(array - 1, 120),
336               kInvalidUnpoisonMessage);
337
338  ASAN_POISON_MEMORY_REGION(array, 120);
339  // Try to poison not owned memory.
340  EXPECT_DEATH(ASAN_POISON_MEMORY_REGION(array, 121), kInvalidPoisonMessage);
341  EXPECT_DEATH(ASAN_POISON_MEMORY_REGION(array - 1, 120),
342               kInvalidPoisonMessage);
343  free(array);
344}
345
346static void ErrorReportCallbackOneToZ(const char *report) {
347  int len = strlen(report);
348  char *dup = (char*)malloc(len);
349  strcpy(dup, report);
350  for (int i = 0; i < len; i++) {
351    if (dup[i] == '1') dup[i] = 'Z';
352  }
353  write(2, dup, len);
354  free(dup);
355}
356
357TEST(AddressSanitizerInterface, SetErrorReportCallbackTest) {
358  __asan_set_error_report_callback(ErrorReportCallbackOneToZ);
359  char *array = Ident((char*)malloc(120));
360  EXPECT_DEATH(ACCESS(array, 120), "size Z");
361  __asan_set_error_report_callback(NULL);
362}
363