Home | History | Annotate | Download | only in tests
      1 //===-- asan_noinst_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 // This test file should be compiled w/o asan instrumentation.
     13 //===----------------------------------------------------------------------===//
     14 #include "asan_allocator.h"
     15 #include "asan_interface.h"
     16 #include "asan_internal.h"
     17 #include "asan_mapping.h"
     18 #include "asan_stack.h"
     19 #include "asan_test_utils.h"
     20 
     21 #include <assert.h>
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 #include <vector>
     25 #include <algorithm>
     26 #include "gtest/gtest.h"
     27 
     28 // Simple stand-alone pseudorandom number generator.
     29 // Current algorithm is ANSI C linear congruential PRNG.
     30 static inline uint32_t my_rand(uint32_t* state) {
     31   return (*state = *state * 1103515245 + 12345) >> 16;
     32 }
     33 
     34 static uint32_t global_seed = 0;
     35 
     36 
     37 TEST(AddressSanitizer, InternalSimpleDeathTest) {
     38   EXPECT_DEATH(exit(1), "");
     39 }
     40 
     41 static void MallocStress(size_t n) {
     42   uint32_t seed = my_rand(&global_seed);
     43   __asan::AsanStackTrace stack1;
     44   stack1.trace[0] = 0xa123;
     45   stack1.trace[1] = 0xa456;
     46   stack1.size = 2;
     47 
     48   __asan::AsanStackTrace stack2;
     49   stack2.trace[0] = 0xb123;
     50   stack2.trace[1] = 0xb456;
     51   stack2.size = 2;
     52 
     53   __asan::AsanStackTrace stack3;
     54   stack3.trace[0] = 0xc123;
     55   stack3.trace[1] = 0xc456;
     56   stack3.size = 2;
     57 
     58   std::vector<void *> vec;
     59   for (size_t i = 0; i < n; i++) {
     60     if ((i % 3) == 0) {
     61       if (vec.empty()) continue;
     62       size_t idx = my_rand(&seed) % vec.size();
     63       void *ptr = vec[idx];
     64       vec[idx] = vec.back();
     65       vec.pop_back();
     66       __asan::asan_free(ptr, &stack1);
     67     } else {
     68       size_t size = my_rand(&seed) % 1000 + 1;
     69       switch ((my_rand(&seed) % 128)) {
     70         case 0: size += 1024; break;
     71         case 1: size += 2048; break;
     72         case 2: size += 4096; break;
     73       }
     74       size_t alignment = 1 << (my_rand(&seed) % 10 + 1);
     75       char *ptr = (char*)__asan::asan_memalign(alignment, size, &stack2);
     76       vec.push_back(ptr);
     77       ptr[0] = 0;
     78       ptr[size-1] = 0;
     79       ptr[size/2] = 0;
     80     }
     81   }
     82   for (size_t i = 0; i < vec.size(); i++)
     83     __asan::asan_free(vec[i], &stack3);
     84 }
     85 
     86 
     87 TEST(AddressSanitizer, NoInstMallocTest) {
     88 #ifdef __arm__
     89   MallocStress(300000);
     90 #else
     91   MallocStress(1000000);
     92 #endif
     93 }
     94 
     95 static void PrintShadow(const char *tag, uintptr_t ptr, size_t size) {
     96   fprintf(stderr, "%s shadow: %lx size % 3ld: ", tag, (long)ptr, (long)size);
     97   uintptr_t prev_shadow = 0;
     98   for (intptr_t i = -32; i < (intptr_t)size + 32; i++) {
     99     uintptr_t shadow = __asan::MemToShadow(ptr + i);
    100     if (i == 0 || i == (intptr_t)size)
    101       fprintf(stderr, ".");
    102     if (shadow != prev_shadow) {
    103       prev_shadow = shadow;
    104       fprintf(stderr, "%02x", (int)*(uint8_t*)shadow);
    105     }
    106   }
    107   fprintf(stderr, "\n");
    108 }
    109 
    110 TEST(AddressSanitizer, DISABLED_InternalPrintShadow) {
    111   for (size_t size = 1; size <= 513; size++) {
    112     char *ptr = new char[size];
    113     PrintShadow("m", (uintptr_t)ptr, size);
    114     delete [] ptr;
    115     PrintShadow("f", (uintptr_t)ptr, size);
    116   }
    117 }
    118 
    119 static uintptr_t pc_array[] = {
    120 #if __WORDSIZE == 64
    121   0x7effbf756068ULL,
    122   0x7effbf75e5abULL,
    123   0x7effc0625b7cULL,
    124   0x7effc05b8997ULL,
    125   0x7effbf990577ULL,
    126   0x7effbf990c56ULL,
    127   0x7effbf992f3cULL,
    128   0x7effbf950c22ULL,
    129   0x7effc036dba0ULL,
    130   0x7effc03638a3ULL,
    131   0x7effc035be4aULL,
    132   0x7effc0539c45ULL,
    133   0x7effc0539a65ULL,
    134   0x7effc03db9b3ULL,
    135   0x7effc03db100ULL,
    136   0x7effc037c7b8ULL,
    137   0x7effc037bfffULL,
    138   0x7effc038b777ULL,
    139   0x7effc038021cULL,
    140   0x7effc037c7d1ULL,
    141   0x7effc037bfffULL,
    142   0x7effc038b777ULL,
    143   0x7effc038021cULL,
    144   0x7effc037c7d1ULL,
    145   0x7effc037bfffULL,
    146   0x7effc038b777ULL,
    147   0x7effc038021cULL,
    148   0x7effc037c7d1ULL,
    149   0x7effc037bfffULL,
    150   0x7effc0520d26ULL,
    151   0x7effc009ddffULL,
    152   0x7effbf90bb50ULL,
    153   0x7effbdddfa69ULL,
    154   0x7effbdde1fe2ULL,
    155   0x7effbdde2424ULL,
    156   0x7effbdde27b3ULL,
    157   0x7effbddee53bULL,
    158   0x7effbdde1988ULL,
    159   0x7effbdde0904ULL,
    160   0x7effc106ce0dULL,
    161   0x7effbcc3fa04ULL,
    162   0x7effbcc3f6a4ULL,
    163   0x7effbcc3e726ULL,
    164   0x7effbcc40852ULL,
    165   0x7effb681ec4dULL,
    166 #endif  // __WORDSIZE
    167   0xB0B5E768,
    168   0x7B682EC1,
    169   0x367F9918,
    170   0xAE34E13,
    171   0xBA0C6C6,
    172   0x13250F46,
    173   0xA0D6A8AB,
    174   0x2B07C1A8,
    175   0x6C844F4A,
    176   0x2321B53,
    177   0x1F3D4F8F,
    178   0x3FE2924B,
    179   0xB7A2F568,
    180   0xBD23950A,
    181   0x61020930,
    182   0x33E7970C,
    183   0x405998A1,
    184   0x59F3551D,
    185   0x350E3028,
    186   0xBC55A28D,
    187   0x361F3AED,
    188   0xBEAD0F73,
    189   0xAEF28479,
    190   0x757E971F,
    191   0xAEBA450,
    192   0x43AD22F5,
    193   0x8C2C50C4,
    194   0x7AD8A2E1,
    195   0x69EE4EE8,
    196   0xC08DFF,
    197   0x4BA6538,
    198   0x3708AB2,
    199   0xC24B6475,
    200   0x7C8890D7,
    201   0x6662495F,
    202   0x9B641689,
    203   0xD3596B,
    204   0xA1049569,
    205   0x44CBC16,
    206   0x4D39C39F
    207 };
    208 
    209 void CompressStackTraceTest(size_t n_iter) {
    210   uint32_t seed = my_rand(&global_seed);
    211   const size_t kNumPcs = ASAN_ARRAY_SIZE(pc_array);
    212   uint32_t compressed[2 * kNumPcs];
    213 
    214   for (size_t iter = 0; iter < n_iter; iter++) {
    215     std::random_shuffle(pc_array, pc_array + kNumPcs);
    216     __asan::AsanStackTrace stack0, stack1;
    217     stack0.CopyFrom(pc_array, kNumPcs);
    218     stack0.size = std::max((size_t)1, (size_t)my_rand(&seed) % stack0.size);
    219     size_t compress_size =
    220       std::max((size_t)2, (size_t)my_rand(&seed) % (2 * kNumPcs));
    221     size_t n_frames =
    222       __asan::AsanStackTrace::CompressStack(&stack0, compressed, compress_size);
    223     assert(n_frames <= stack0.size);
    224     __asan::AsanStackTrace::UncompressStack(&stack1, compressed, compress_size);
    225     assert(stack1.size == n_frames);
    226     for (size_t i = 0; i < stack1.size; i++) {
    227       assert(stack0.trace[i] == stack1.trace[i]);
    228     }
    229   }
    230 }
    231 
    232 TEST(AddressSanitizer, CompressStackTraceTest) {
    233   CompressStackTraceTest(10000);
    234 }
    235 
    236 void CompressStackTraceBenchmark(size_t n_iter) {
    237   const size_t kNumPcs = ASAN_ARRAY_SIZE(pc_array);
    238   uint32_t compressed[2 * kNumPcs];
    239   std::random_shuffle(pc_array, pc_array + kNumPcs);
    240 
    241   __asan::AsanStackTrace stack0;
    242   stack0.CopyFrom(pc_array, kNumPcs);
    243   stack0.size = kNumPcs;
    244   for (size_t iter = 0; iter < n_iter; iter++) {
    245     size_t compress_size = kNumPcs;
    246     size_t n_frames =
    247       __asan::AsanStackTrace::CompressStack(&stack0, compressed, compress_size);
    248     Ident(n_frames);
    249   }
    250 }
    251 
    252 TEST(AddressSanitizer, CompressStackTraceBenchmark) {
    253   CompressStackTraceBenchmark(1 << 24);
    254 }
    255 
    256 TEST(AddressSanitizer, QuarantineTest) {
    257   __asan::AsanStackTrace stack;
    258   stack.trace[0] = 0x890;
    259   stack.size = 1;
    260 
    261   const int size = 32;
    262   void *p = __asan::asan_malloc(size, &stack);
    263   __asan::asan_free(p, &stack);
    264   size_t i;
    265   size_t max_i = 1 << 30;
    266   for (i = 0; i < max_i; i++) {
    267     void *p1 = __asan::asan_malloc(size, &stack);
    268     __asan::asan_free(p1, &stack);
    269     if (p1 == p) break;
    270   }
    271   // fprintf(stderr, "i=%ld\n", i);
    272   EXPECT_GE(i, 100000U);
    273   EXPECT_LT(i, max_i);
    274 }
    275 
    276 void *ThreadedQuarantineTestWorker(void *unused) {
    277   uint32_t seed = my_rand(&global_seed);
    278   __asan::AsanStackTrace stack;
    279   stack.trace[0] = 0x890;
    280   stack.size = 1;
    281 
    282   for (size_t i = 0; i < 1000; i++) {
    283     void *p = __asan::asan_malloc(1 + (my_rand(&seed) % 4000), &stack);
    284     __asan::asan_free(p, &stack);
    285   }
    286   return NULL;
    287 }
    288 
    289 // Check that the thread local allocators are flushed when threads are
    290 // destroyed.
    291 TEST(AddressSanitizer, ThreadedQuarantineTest) {
    292   const int n_threads = 3000;
    293   size_t mmaped1 = __asan_get_heap_size();
    294   for (int i = 0; i < n_threads; i++) {
    295     pthread_t t;
    296     pthread_create(&t, NULL, ThreadedQuarantineTestWorker, 0);
    297     pthread_join(t, 0);
    298     size_t mmaped2 = __asan_get_heap_size();
    299     EXPECT_LT(mmaped2 - mmaped1, 320U * (1 << 20));
    300   }
    301 }
    302 
    303 void *ThreadedOneSizeMallocStress(void *unused) {
    304   __asan::AsanStackTrace stack;
    305   stack.trace[0] = 0x890;
    306   stack.size = 1;
    307   const size_t kNumMallocs = 1000;
    308   for (int iter = 0; iter < 1000; iter++) {
    309     void *p[kNumMallocs];
    310     for (size_t i = 0; i < kNumMallocs; i++) {
    311       p[i] = __asan::asan_malloc(32, &stack);
    312     }
    313     for (size_t i = 0; i < kNumMallocs; i++) {
    314       __asan::asan_free(p[i], &stack);
    315     }
    316   }
    317   return NULL;
    318 }
    319 
    320 TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) {
    321   const int kNumThreads = 4;
    322   pthread_t t[kNumThreads];
    323   for (int i = 0; i < kNumThreads; i++) {
    324     pthread_create(&t[i], 0, ThreadedOneSizeMallocStress, 0);
    325   }
    326   for (int i = 0; i < kNumThreads; i++) {
    327     pthread_join(t[i], 0);
    328   }
    329 }
    330