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