asan_noinst_test.cc revision b43d6a8ca10b9af8a903e8726003ae7767f9e823
1//===-- asan_noinst_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// This test file should be compiled w/o asan instrumentation.
13//===----------------------------------------------------------------------===//
14
15#include "asan_allocator.h"
16#include "asan_internal.h"
17#include "asan_mapping.h"
18#include "asan_stack.h"
19#include "asan_test_utils.h"
20#include "asan_test_config.h"
21#include "sanitizer/asan_interface.h"
22
23#include <assert.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>  // for memset()
27#include <algorithm>
28#include <vector>
29#include "gtest/gtest.h"
30
31// Simple stand-alone pseudorandom number generator.
32// Current algorithm is ANSI C linear congruential PRNG.
33static inline u32 my_rand(u32* state) {
34  return (*state = *state * 1103515245 + 12345) >> 16;
35}
36
37static u32 global_seed = 0;
38
39
40TEST(AddressSanitizer, InternalSimpleDeathTest) {
41  EXPECT_DEATH(exit(1), "");
42}
43
44static void MallocStress(size_t n) {
45  u32 seed = my_rand(&global_seed);
46  __asan::StackTrace stack1;
47  stack1.trace[0] = 0xa123;
48  stack1.trace[1] = 0xa456;
49  stack1.size = 2;
50
51  __asan::StackTrace stack2;
52  stack2.trace[0] = 0xb123;
53  stack2.trace[1] = 0xb456;
54  stack2.size = 2;
55
56  __asan::StackTrace stack3;
57  stack3.trace[0] = 0xc123;
58  stack3.trace[1] = 0xc456;
59  stack3.size = 2;
60
61  std::vector<void *> vec;
62  for (size_t i = 0; i < n; i++) {
63    if ((i % 3) == 0) {
64      if (vec.empty()) continue;
65      size_t idx = my_rand(&seed) % vec.size();
66      void *ptr = vec[idx];
67      vec[idx] = vec.back();
68      vec.pop_back();
69      __asan::asan_free(ptr, &stack1);
70    } else {
71      size_t size = my_rand(&seed) % 1000 + 1;
72      switch ((my_rand(&seed) % 128)) {
73        case 0: size += 1024; break;
74        case 1: size += 2048; break;
75        case 2: size += 4096; break;
76      }
77      size_t alignment = 1 << (my_rand(&seed) % 10 + 1);
78      char *ptr = (char*)__asan::asan_memalign(alignment, size, &stack2);
79      vec.push_back(ptr);
80      ptr[0] = 0;
81      ptr[size-1] = 0;
82      ptr[size/2] = 0;
83    }
84  }
85  for (size_t i = 0; i < vec.size(); i++)
86    __asan::asan_free(vec[i], &stack3);
87}
88
89
90TEST(AddressSanitizer, NoInstMallocTest) {
91#ifdef __arm__
92  MallocStress(300000);
93#else
94  MallocStress(1000000);
95#endif
96}
97
98static void PrintShadow(const char *tag, uptr ptr, size_t size) {
99  fprintf(stderr, "%s shadow: %lx size % 3ld: ", tag, (long)ptr, (long)size);
100  uptr prev_shadow = 0;
101  for (sptr i = -32; i < (sptr)size + 32; i++) {
102    uptr shadow = __asan::MemToShadow(ptr + i);
103    if (i == 0 || i == (sptr)size)
104      fprintf(stderr, ".");
105    if (shadow != prev_shadow) {
106      prev_shadow = shadow;
107      fprintf(stderr, "%02x", (int)*(u8*)shadow);
108    }
109  }
110  fprintf(stderr, "\n");
111}
112
113TEST(AddressSanitizer, DISABLED_InternalPrintShadow) {
114  for (size_t size = 1; size <= 513; size++) {
115    char *ptr = new char[size];
116    PrintShadow("m", (uptr)ptr, size);
117    delete [] ptr;
118    PrintShadow("f", (uptr)ptr, size);
119  }
120}
121
122static uptr pc_array[] = {
123#if __WORDSIZE == 64
124  0x7effbf756068ULL,
125  0x7effbf75e5abULL,
126  0x7effc0625b7cULL,
127  0x7effc05b8997ULL,
128  0x7effbf990577ULL,
129  0x7effbf990c56ULL,
130  0x7effbf992f3cULL,
131  0x7effbf950c22ULL,
132  0x7effc036dba0ULL,
133  0x7effc03638a3ULL,
134  0x7effc035be4aULL,
135  0x7effc0539c45ULL,
136  0x7effc0539a65ULL,
137  0x7effc03db9b3ULL,
138  0x7effc03db100ULL,
139  0x7effc037c7b8ULL,
140  0x7effc037bfffULL,
141  0x7effc038b777ULL,
142  0x7effc038021cULL,
143  0x7effc037c7d1ULL,
144  0x7effc037bfffULL,
145  0x7effc038b777ULL,
146  0x7effc038021cULL,
147  0x7effc037c7d1ULL,
148  0x7effc037bfffULL,
149  0x7effc038b777ULL,
150  0x7effc038021cULL,
151  0x7effc037c7d1ULL,
152  0x7effc037bfffULL,
153  0x7effc0520d26ULL,
154  0x7effc009ddffULL,
155  0x7effbf90bb50ULL,
156  0x7effbdddfa69ULL,
157  0x7effbdde1fe2ULL,
158  0x7effbdde2424ULL,
159  0x7effbdde27b3ULL,
160  0x7effbddee53bULL,
161  0x7effbdde1988ULL,
162  0x7effbdde0904ULL,
163  0x7effc106ce0dULL,
164  0x7effbcc3fa04ULL,
165  0x7effbcc3f6a4ULL,
166  0x7effbcc3e726ULL,
167  0x7effbcc40852ULL,
168  0x7effb681ec4dULL,
169#endif  // __WORDSIZE
170  0xB0B5E768,
171  0x7B682EC1,
172  0x367F9918,
173  0xAE34E13,
174  0xBA0C6C6,
175  0x13250F46,
176  0xA0D6A8AB,
177  0x2B07C1A8,
178  0x6C844F4A,
179  0x2321B53,
180  0x1F3D4F8F,
181  0x3FE2924B,
182  0xB7A2F568,
183  0xBD23950A,
184  0x61020930,
185  0x33E7970C,
186  0x405998A1,
187  0x59F3551D,
188  0x350E3028,
189  0xBC55A28D,
190  0x361F3AED,
191  0xBEAD0F73,
192  0xAEF28479,
193  0x757E971F,
194  0xAEBA450,
195  0x43AD22F5,
196  0x8C2C50C4,
197  0x7AD8A2E1,
198  0x69EE4EE8,
199  0xC08DFF,
200  0x4BA6538,
201  0x3708AB2,
202  0xC24B6475,
203  0x7C8890D7,
204  0x6662495F,
205  0x9B641689,
206  0xD3596B,
207  0xA1049569,
208  0x44CBC16,
209  0x4D39C39F
210};
211
212void CompressStackTraceTest(size_t n_iter) {
213  u32 seed = my_rand(&global_seed);
214  const size_t kNumPcs = ARRAY_SIZE(pc_array);
215  u32 compressed[2 * kNumPcs];
216
217  for (size_t iter = 0; iter < n_iter; iter++) {
218    std::random_shuffle(pc_array, pc_array + kNumPcs);
219    __asan::StackTrace stack0, stack1;
220    stack0.CopyFrom(pc_array, kNumPcs);
221    stack0.size = std::max((size_t)1, (size_t)(my_rand(&seed) % stack0.size));
222    size_t compress_size =
223      std::max((size_t)2, (size_t)my_rand(&seed) % (2 * kNumPcs));
224    size_t n_frames =
225      __asan::StackTrace::CompressStack(&stack0, compressed, compress_size);
226    Ident(n_frames);
227    assert(n_frames <= stack0.size);
228    __asan::StackTrace::UncompressStack(&stack1, compressed, compress_size);
229    assert(stack1.size == n_frames);
230    for (size_t i = 0; i < stack1.size; i++) {
231      assert(stack0.trace[i] == stack1.trace[i]);
232    }
233  }
234}
235
236TEST(AddressSanitizer, CompressStackTraceTest) {
237  CompressStackTraceTest(10000);
238}
239
240void CompressStackTraceBenchmark(size_t n_iter) {
241  const size_t kNumPcs = ARRAY_SIZE(pc_array);
242  u32 compressed[2 * kNumPcs];
243  std::random_shuffle(pc_array, pc_array + kNumPcs);
244
245  __asan::StackTrace stack0;
246  stack0.CopyFrom(pc_array, kNumPcs);
247  stack0.size = kNumPcs;
248  for (size_t iter = 0; iter < n_iter; iter++) {
249    size_t compress_size = kNumPcs;
250    size_t n_frames =
251      __asan::StackTrace::CompressStack(&stack0, compressed, compress_size);
252    Ident(n_frames);
253  }
254}
255
256TEST(AddressSanitizer, CompressStackTraceBenchmark) {
257  CompressStackTraceBenchmark(1 << 24);
258}
259
260TEST(AddressSanitizer, QuarantineTest) {
261  __asan::StackTrace stack;
262  stack.trace[0] = 0x890;
263  stack.size = 1;
264
265  const int size = 32;
266  void *p = __asan::asan_malloc(size, &stack);
267  __asan::asan_free(p, &stack);
268  size_t i;
269  size_t max_i = 1 << 30;
270  for (i = 0; i < max_i; i++) {
271    void *p1 = __asan::asan_malloc(size, &stack);
272    __asan::asan_free(p1, &stack);
273    if (p1 == p) break;
274  }
275  // fprintf(stderr, "i=%ld\n", i);
276  EXPECT_GE(i, 100000U);
277  EXPECT_LT(i, max_i);
278}
279
280void *ThreadedQuarantineTestWorker(void *unused) {
281  (void)unused;
282  u32 seed = my_rand(&global_seed);
283  __asan::StackTrace stack;
284  stack.trace[0] = 0x890;
285  stack.size = 1;
286
287  for (size_t i = 0; i < 1000; i++) {
288    void *p = __asan::asan_malloc(1 + (my_rand(&seed) % 4000), &stack);
289    __asan::asan_free(p, &stack);
290  }
291  return NULL;
292}
293
294// Check that the thread local allocators are flushed when threads are
295// destroyed.
296TEST(AddressSanitizer, ThreadedQuarantineTest) {
297  const int n_threads = 3000;
298  size_t mmaped1 = __asan_get_heap_size();
299  for (int i = 0; i < n_threads; i++) {
300    pthread_t t;
301    pthread_create(&t, NULL, ThreadedQuarantineTestWorker, 0);
302    pthread_join(t, 0);
303    size_t mmaped2 = __asan_get_heap_size();
304    EXPECT_LT(mmaped2 - mmaped1, 320U * (1 << 20));
305  }
306}
307
308void *ThreadedOneSizeMallocStress(void *unused) {
309  (void)unused;
310  __asan::StackTrace stack;
311  stack.trace[0] = 0x890;
312  stack.size = 1;
313  const size_t kNumMallocs = 1000;
314  for (int iter = 0; iter < 1000; iter++) {
315    void *p[kNumMallocs];
316    for (size_t i = 0; i < kNumMallocs; i++) {
317      p[i] = __asan::asan_malloc(32, &stack);
318    }
319    for (size_t i = 0; i < kNumMallocs; i++) {
320      __asan::asan_free(p[i], &stack);
321    }
322  }
323  return NULL;
324}
325
326TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) {
327  const int kNumThreads = 4;
328  pthread_t t[kNumThreads];
329  for (int i = 0; i < kNumThreads; i++) {
330    pthread_create(&t[i], 0, ThreadedOneSizeMallocStress, 0);
331  }
332  for (int i = 0; i < kNumThreads; i++) {
333    pthread_join(t[i], 0);
334  }
335}
336
337TEST(AddressSanitizer, MemsetWildAddressTest) {
338  typedef void*(*memset_p)(void*, int, size_t);
339  // Prevent inlining of memset().
340  volatile memset_p libc_memset = (memset_p)memset;
341  EXPECT_DEATH(libc_memset((void*)(kLowShadowBeg + kPageSize), 0, 100),
342               "unknown-crash.*low shadow");
343  EXPECT_DEATH(libc_memset((void*)(kShadowGapBeg + kPageSize), 0, 100),
344               "unknown-crash.*shadow gap");
345  EXPECT_DEATH(libc_memset((void*)(kHighShadowBeg + kPageSize), 0, 100),
346               "unknown-crash.*high shadow");
347}
348
349TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) {
350  EXPECT_EQ(1U, __asan_get_estimated_allocated_size(0));
351  const size_t sizes[] = { 1, 30, 1<<30 };
352  for (size_t i = 0; i < 3; i++) {
353    EXPECT_EQ(sizes[i], __asan_get_estimated_allocated_size(sizes[i]));
354  }
355}
356
357static const char* kGetAllocatedSizeErrorMsg =
358  "attempting to call __asan_get_allocated_size()";
359
360TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
361  const size_t kArraySize = 100;
362  char *array = Ident((char*)malloc(kArraySize));
363  int *int_ptr = Ident(new int);
364
365  // Allocated memory is owned by allocator. Allocated size should be
366  // equal to requested size.
367  EXPECT_EQ(true, __asan_get_ownership(array));
368  EXPECT_EQ(kArraySize, __asan_get_allocated_size(array));
369  EXPECT_EQ(true, __asan_get_ownership(int_ptr));
370  EXPECT_EQ(sizeof(int), __asan_get_allocated_size(int_ptr));
371
372  // We cannot call GetAllocatedSize from the memory we didn't map,
373  // and from the interior pointers (not returned by previous malloc).
374  void *wild_addr = (void*)0x1;
375  EXPECT_EQ(false, __asan_get_ownership(wild_addr));
376  EXPECT_DEATH(__asan_get_allocated_size(wild_addr), kGetAllocatedSizeErrorMsg);
377  EXPECT_EQ(false, __asan_get_ownership(array + kArraySize / 2));
378  EXPECT_DEATH(__asan_get_allocated_size(array + kArraySize / 2),
379               kGetAllocatedSizeErrorMsg);
380
381  // NULL is not owned, but is a valid argument for __asan_get_allocated_size().
382  EXPECT_EQ(false, __asan_get_ownership(NULL));
383  EXPECT_EQ(0U, __asan_get_allocated_size(NULL));
384
385  // When memory is freed, it's not owned, and call to GetAllocatedSize
386  // is forbidden.
387  free(array);
388  EXPECT_EQ(false, __asan_get_ownership(array));
389  EXPECT_DEATH(__asan_get_allocated_size(array), kGetAllocatedSizeErrorMsg);
390
391  delete int_ptr;
392}
393
394TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) {
395  size_t before_malloc, after_malloc, after_free;
396  char *array;
397  const size_t kMallocSize = 100;
398  before_malloc = __asan_get_current_allocated_bytes();
399
400  array = Ident((char*)malloc(kMallocSize));
401  after_malloc = __asan_get_current_allocated_bytes();
402  EXPECT_EQ(before_malloc + kMallocSize, after_malloc);
403
404  free(array);
405  after_free = __asan_get_current_allocated_bytes();
406  EXPECT_EQ(before_malloc, after_free);
407}
408
409static void DoDoubleFree() {
410  int *x = Ident(new int);
411  delete Ident(x);
412  delete Ident(x);
413}
414
415// This test is run in a separate process, so that large malloced
416// chunk won't remain in the free lists after the test.
417// Note: use ASSERT_* instead of EXPECT_* here.
418static void RunGetHeapSizeTestAndDie() {
419  size_t old_heap_size, new_heap_size, heap_growth;
420  // We unlikely have have chunk of this size in free list.
421  static const size_t kLargeMallocSize = 1 << 29;  // 512M
422  old_heap_size = __asan_get_heap_size();
423  fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
424  free(Ident(malloc(kLargeMallocSize)));
425  new_heap_size = __asan_get_heap_size();
426  heap_growth = new_heap_size - old_heap_size;
427  fprintf(stderr, "heap growth after first malloc: %zu\n", heap_growth);
428  ASSERT_GE(heap_growth, kLargeMallocSize);
429  ASSERT_LE(heap_growth, 2 * kLargeMallocSize);
430
431  // Now large chunk should fall into free list, and can be
432  // allocated without increasing heap size.
433  old_heap_size = new_heap_size;
434  free(Ident(malloc(kLargeMallocSize)));
435  heap_growth = __asan_get_heap_size() - old_heap_size;
436  fprintf(stderr, "heap growth after second malloc: %zu\n", heap_growth);
437  ASSERT_LT(heap_growth, kLargeMallocSize);
438
439  // Test passed. Now die with expected double-free.
440  DoDoubleFree();
441}
442
443TEST(AddressSanitizerInterface, GetHeapSizeTest) {
444  EXPECT_DEATH(RunGetHeapSizeTestAndDie(), "double-free");
445}
446
447// Note: use ASSERT_* instead of EXPECT_* here.
448static void DoLargeMallocForGetFreeBytesTestAndDie() {
449  size_t old_free_bytes, new_free_bytes;
450  static const size_t kLargeMallocSize = 1 << 29;  // 512M
451  // If we malloc and free a large memory chunk, it will not fall
452  // into quarantine and will be available for future requests.
453  old_free_bytes = __asan_get_free_bytes();
454  fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
455  fprintf(stderr, "free bytes before malloc: %zu\n", old_free_bytes);
456  free(Ident(malloc(kLargeMallocSize)));
457  new_free_bytes = __asan_get_free_bytes();
458  fprintf(stderr, "free bytes after malloc and free: %zu\n", new_free_bytes);
459  ASSERT_GE(new_free_bytes, old_free_bytes + kLargeMallocSize);
460  // Test passed.
461  DoDoubleFree();
462}
463
464TEST(AddressSanitizerInterface, GetFreeBytesTest) {
465  static const size_t kNumOfChunks = 100;
466  static const size_t kChunkSize = 100;
467  char *chunks[kNumOfChunks];
468  size_t i;
469  size_t old_free_bytes, new_free_bytes;
470  // Allocate a small chunk. Now allocator probably has a lot of these
471  // chunks to fulfill future requests. So, future requests will decrease
472  // the number of free bytes.
473  chunks[0] = Ident((char*)malloc(kChunkSize));
474  old_free_bytes = __asan_get_free_bytes();
475  for (i = 1; i < kNumOfChunks; i++) {
476    chunks[i] = Ident((char*)malloc(kChunkSize));
477    new_free_bytes = __asan_get_free_bytes();
478    EXPECT_LT(new_free_bytes, old_free_bytes);
479    old_free_bytes = new_free_bytes;
480  }
481  EXPECT_DEATH(DoLargeMallocForGetFreeBytesTestAndDie(), "double-free");
482}
483
484static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<20, 357};
485static const size_t kManyThreadsIterations = 250;
486static const size_t kManyThreadsNumThreads = (__WORDSIZE == 32) ? 40 : 200;
487
488void *ManyThreadsWithStatsWorker(void *arg) {
489  (void)arg;
490  for (size_t iter = 0; iter < kManyThreadsIterations; iter++) {
491    for (size_t size_index = 0; size_index < 4; size_index++) {
492      free(Ident(malloc(kManyThreadsMallocSizes[size_index])));
493    }
494  }
495  return 0;
496}
497
498TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
499  size_t before_test, after_test, i;
500  pthread_t threads[kManyThreadsNumThreads];
501  before_test = __asan_get_current_allocated_bytes();
502  for (i = 0; i < kManyThreadsNumThreads; i++) {
503    pthread_create(&threads[i], 0,
504                   (void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i);
505  }
506  for (i = 0; i < kManyThreadsNumThreads; i++) {
507    pthread_join(threads[i], 0);
508  }
509  after_test = __asan_get_current_allocated_bytes();
510  // ASan stats also reflect memory usage of internal ASan RTL structs,
511  // so we can't check for equality here.
512  EXPECT_LT(after_test, before_test + (1UL<<20));
513}
514
515TEST(AddressSanitizerInterface, ExitCode) {
516  int original_exit_code = __asan_set_error_exit_code(7);
517  EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(7), "");
518  EXPECT_EQ(7, __asan_set_error_exit_code(8));
519  EXPECT_EXIT(DoDoubleFree(), ::testing::ExitedWithCode(8), "");
520  EXPECT_EQ(8, __asan_set_error_exit_code(original_exit_code));
521  EXPECT_EXIT(DoDoubleFree(),
522              ::testing::ExitedWithCode(original_exit_code), "");
523}
524
525static void MyDeathCallback() {
526  fprintf(stderr, "MyDeathCallback\n");
527}
528
529TEST(AddressSanitizerInterface, DeathCallbackTest) {
530  __asan_set_death_callback(MyDeathCallback);
531  EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback");
532  __asan_set_death_callback(NULL);
533}
534
535TEST(AddressSanitizerInterface, OnErrorCallbackTest) {
536  __asan_set_on_error_callback(MyDeathCallback);
537  EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback.*double-free");
538  __asan_set_on_error_callback(NULL);
539}
540
541static const char* kUseAfterPoisonErrorMessage = "use-after-poison";
542
543#define GOOD_ACCESS(ptr, offset)  \
544    EXPECT_FALSE(__asan::AddressIsPoisoned((uptr)(ptr + offset)))
545
546#define BAD_ACCESS(ptr, offset) \
547    EXPECT_TRUE(__asan::AddressIsPoisoned((uptr)(ptr + offset)))
548
549TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) {
550  char *array = Ident((char*)malloc(120));
551  // poison array[40..80)
552  __asan_poison_memory_region(array + 40, 40);
553  GOOD_ACCESS(array, 39);
554  GOOD_ACCESS(array, 80);
555  BAD_ACCESS(array, 40);
556  BAD_ACCESS(array, 60);
557  BAD_ACCESS(array, 79);
558  EXPECT_DEATH(__asan_report_error(0, 0, 0, (uptr)(array + 40), true, 1),
559               kUseAfterPoisonErrorMessage);
560  __asan_unpoison_memory_region(array + 40, 40);
561  // access previously poisoned memory.
562  GOOD_ACCESS(array, 40);
563  GOOD_ACCESS(array, 79);
564  free(array);
565}
566
567TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) {
568  char *array = Ident((char*)malloc(120));
569  // Poison [0..40) and [80..120)
570  __asan_poison_memory_region(array, 40);
571  __asan_poison_memory_region(array + 80, 40);
572  BAD_ACCESS(array, 20);
573  GOOD_ACCESS(array, 60);
574  BAD_ACCESS(array, 100);
575  // Poison whole array - [0..120)
576  __asan_poison_memory_region(array, 120);
577  BAD_ACCESS(array, 60);
578  // Unpoison [24..96)
579  __asan_unpoison_memory_region(array + 24, 72);
580  BAD_ACCESS(array, 23);
581  GOOD_ACCESS(array, 24);
582  GOOD_ACCESS(array, 60);
583  GOOD_ACCESS(array, 95);
584  BAD_ACCESS(array, 96);
585  free(array);
586}
587
588TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) {
589  // Vector of capacity 20
590  char *vec = Ident((char*)malloc(20));
591  __asan_poison_memory_region(vec, 20);
592  for (size_t i = 0; i < 7; i++) {
593    // Simulate push_back.
594    __asan_unpoison_memory_region(vec + i, 1);
595    GOOD_ACCESS(vec, i);
596    BAD_ACCESS(vec, i + 1);
597  }
598  for (size_t i = 7; i > 0; i--) {
599    // Simulate pop_back.
600    __asan_poison_memory_region(vec + i - 1, 1);
601    BAD_ACCESS(vec, i - 1);
602    if (i > 1) GOOD_ACCESS(vec, i - 2);
603  }
604  free(vec);
605}
606
607// Make sure that each aligned block of size "2^granularity" doesn't have
608// "true" value before "false" value.
609static void MakeShadowValid(bool *shadow, int length, int granularity) {
610  bool can_be_poisoned = true;
611  for (int i = length - 1; i >= 0; i--) {
612    if (!shadow[i])
613      can_be_poisoned = false;
614    if (!can_be_poisoned)
615      shadow[i] = false;
616    if (i % (1 << granularity) == 0) {
617      can_be_poisoned = true;
618    }
619  }
620}
621
622TEST(AddressSanitizerInterface, PoisoningStressTest) {
623  const size_t kSize = 24;
624  bool expected[kSize];
625  char *arr = Ident((char*)malloc(kSize));
626  for (size_t l1 = 0; l1 < kSize; l1++) {
627    for (size_t s1 = 1; l1 + s1 <= kSize; s1++) {
628      for (size_t l2 = 0; l2 < kSize; l2++) {
629        for (size_t s2 = 1; l2 + s2 <= kSize; s2++) {
630          // Poison [l1, l1+s1), [l2, l2+s2) and check result.
631          __asan_unpoison_memory_region(arr, kSize);
632          __asan_poison_memory_region(arr + l1, s1);
633          __asan_poison_memory_region(arr + l2, s2);
634          memset(expected, false, kSize);
635          memset(expected + l1, true, s1);
636          MakeShadowValid(expected, kSize, /*granularity*/ 3);
637          memset(expected + l2, true, s2);
638          MakeShadowValid(expected, kSize, /*granularity*/ 3);
639          for (size_t i = 0; i < kSize; i++) {
640            ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
641          }
642          // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result.
643          __asan_poison_memory_region(arr, kSize);
644          __asan_unpoison_memory_region(arr + l1, s1);
645          __asan_unpoison_memory_region(arr + l2, s2);
646          memset(expected, true, kSize);
647          memset(expected + l1, false, s1);
648          MakeShadowValid(expected, kSize, /*granularity*/ 3);
649          memset(expected + l2, false, s2);
650          MakeShadowValid(expected, kSize, /*granularity*/ 3);
651          for (size_t i = 0; i < kSize; i++) {
652            ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
653          }
654        }
655      }
656    }
657  }
658}
659
660static const char *kInvalidPoisonMessage = "invalid-poison-memory-range";
661static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range";
662
663TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) {
664  char *array = Ident((char*)malloc(120));
665  __asan_unpoison_memory_region(array, 120);
666  // Try to unpoison not owned memory
667  EXPECT_DEATH(__asan_unpoison_memory_region(array, 121),
668               kInvalidUnpoisonMessage);
669  EXPECT_DEATH(__asan_unpoison_memory_region(array - 1, 120),
670               kInvalidUnpoisonMessage);
671
672  __asan_poison_memory_region(array, 120);
673  // Try to poison not owned memory.
674  EXPECT_DEATH(__asan_poison_memory_region(array, 121), kInvalidPoisonMessage);
675  EXPECT_DEATH(__asan_poison_memory_region(array - 1, 120),
676               kInvalidPoisonMessage);
677  free(array);
678}
679
680static void ErrorReportCallbackOneToZ(const char *report) {
681  int report_len = strlen(report);
682  ASSERT_EQ(6, write(2, "ABCDEF", 6));
683  ASSERT_EQ(report_len, write(2, report, report_len));
684  ASSERT_EQ(6, write(2, "ABCDEF", 6));
685  _exit(1);
686}
687
688TEST(AddressSanitizerInterface, SetErrorReportCallbackTest) {
689  __asan_set_error_report_callback(ErrorReportCallbackOneToZ);
690  EXPECT_DEATH(__asan_report_error(0, 0, 0, 0, true, 1),
691               ASAN_PCRE_DOTALL "ABCDEF.*AddressSanitizer.*WRITE.*ABCDEF");
692  __asan_set_error_report_callback(NULL);
693}
694
695TEST(AddressSanitizerInterface, GetOwnershipStressTest) {
696  std::vector<char *> pointers;
697  std::vector<size_t> sizes;
698  const size_t kNumMallocs =
699      (__WORDSIZE <= 32 || ASAN_LOW_MEMORY) ? 1 << 10 : 1 << 14;
700  for (size_t i = 0; i < kNumMallocs; i++) {
701    size_t size = i * 100 + 1;
702    pointers.push_back((char*)malloc(size));
703    sizes.push_back(size);
704  }
705  for (size_t i = 0; i < 4000000; i++) {
706    EXPECT_FALSE(__asan_get_ownership(&pointers));
707    EXPECT_FALSE(__asan_get_ownership((void*)0x1234));
708    size_t idx = i % kNumMallocs;
709    EXPECT_TRUE(__asan_get_ownership(pointers[idx]));
710    EXPECT_EQ(sizes[idx], __asan_get_allocated_size(pointers[idx]));
711  }
712  for (size_t i = 0, n = pointers.size(); i < n; i++)
713    free(pointers[i]);
714}
715