Home | History | Annotate | Download | only in tests
      1 //===-- asan_test_mac.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 
     14 #include "asan_test_utils.h"
     15 
     16 #include "asan_mac_test.h"
     17 
     18 #include <malloc/malloc.h>
     19 #include <AvailabilityMacros.h>  // For MAC_OS_X_VERSION_*
     20 #include <CoreFoundation/CFString.h>
     21 
     22 TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree) {
     23   EXPECT_DEATH(
     24       CFAllocatorDefaultDoubleFree(NULL),
     25       "attempting double-free");
     26 }
     27 
     28 void CFAllocator_DoubleFreeOnPthread() {
     29   pthread_t child;
     30   PTHREAD_CREATE(&child, NULL, CFAllocatorDefaultDoubleFree, NULL);
     31   PTHREAD_JOIN(child, NULL);  // Shouldn't be reached.
     32 }
     33 
     34 TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree_ChildPhread) {
     35   EXPECT_DEATH(CFAllocator_DoubleFreeOnPthread(), "attempting double-free");
     36 }
     37 
     38 namespace {
     39 
     40 void *GLOB;
     41 
     42 void *CFAllocatorAllocateToGlob(void *unused) {
     43   GLOB = CFAllocatorAllocate(NULL, 100, /*hint*/0);
     44   return NULL;
     45 }
     46 
     47 void *CFAllocatorDeallocateFromGlob(void *unused) {
     48   char *p = (char*)GLOB;
     49   p[100] = 'A';  // ASan should report an error here.
     50   CFAllocatorDeallocate(NULL, GLOB);
     51   return NULL;
     52 }
     53 
     54 void CFAllocator_PassMemoryToAnotherThread() {
     55   pthread_t th1, th2;
     56   PTHREAD_CREATE(&th1, NULL, CFAllocatorAllocateToGlob, NULL);
     57   PTHREAD_JOIN(th1, NULL);
     58   PTHREAD_CREATE(&th2, NULL, CFAllocatorDeallocateFromGlob, NULL);
     59   PTHREAD_JOIN(th2, NULL);
     60 }
     61 
     62 TEST(AddressSanitizerMac, CFAllocator_PassMemoryToAnotherThread) {
     63   EXPECT_DEATH(CFAllocator_PassMemoryToAnotherThread(),
     64                "heap-buffer-overflow");
     65 }
     66 
     67 }  // namespace
     68 
     69 // TODO(glider): figure out whether we still need these tests. Is it correct
     70 // to intercept the non-default CFAllocators?
     71 TEST(AddressSanitizerMac, DISABLED_CFAllocatorSystemDefaultDoubleFree) {
     72   EXPECT_DEATH(
     73       CFAllocatorSystemDefaultDoubleFree(),
     74       "attempting double-free");
     75 }
     76 
     77 // We're intercepting malloc, so kCFAllocatorMalloc is routed to ASan.
     78 TEST(AddressSanitizerMac, CFAllocatorMallocDoubleFree) {
     79   EXPECT_DEATH(CFAllocatorMallocDoubleFree(), "attempting double-free");
     80 }
     81 
     82 TEST(AddressSanitizerMac, DISABLED_CFAllocatorMallocZoneDoubleFree) {
     83   EXPECT_DEATH(CFAllocatorMallocZoneDoubleFree(), "attempting double-free");
     84 }
     85 
     86 // For libdispatch tests below we check that ASan got to the shadow byte
     87 // legend, i.e. managed to print the thread stacks (this almost certainly
     88 // means that the libdispatch task creation has been intercepted correctly).
     89 TEST(AddressSanitizerMac, GCDDispatchAsync) {
     90   // Make sure the whole ASan report is printed, i.e. that we don't die
     91   // on a CHECK.
     92   EXPECT_DEATH(TestGCDDispatchAsync(), "Shadow byte legend");
     93 }
     94 
     95 TEST(AddressSanitizerMac, GCDDispatchSync) {
     96   // Make sure the whole ASan report is printed, i.e. that we don't die
     97   // on a CHECK.
     98   EXPECT_DEATH(TestGCDDispatchSync(), "Shadow byte legend");
     99 }
    100 
    101 
    102 TEST(AddressSanitizerMac, GCDReuseWqthreadsAsync) {
    103   // Make sure the whole ASan report is printed, i.e. that we don't die
    104   // on a CHECK.
    105   EXPECT_DEATH(TestGCDReuseWqthreadsAsync(), "Shadow byte legend");
    106 }
    107 
    108 TEST(AddressSanitizerMac, GCDReuseWqthreadsSync) {
    109   // Make sure the whole ASan report is printed, i.e. that we don't die
    110   // on a CHECK.
    111   EXPECT_DEATH(TestGCDReuseWqthreadsSync(), "Shadow byte legend");
    112 }
    113 
    114 TEST(AddressSanitizerMac, GCDDispatchAfter) {
    115   // Make sure the whole ASan report is printed, i.e. that we don't die
    116   // on a CHECK.
    117   EXPECT_DEATH(TestGCDDispatchAfter(), "Shadow byte legend");
    118 }
    119 
    120 TEST(AddressSanitizerMac, GCDSourceEvent) {
    121   // Make sure the whole ASan report is printed, i.e. that we don't die
    122   // on a CHECK.
    123   EXPECT_DEATH(TestGCDSourceEvent(), "Shadow byte legend");
    124 }
    125 
    126 TEST(AddressSanitizerMac, GCDSourceCancel) {
    127   // Make sure the whole ASan report is printed, i.e. that we don't die
    128   // on a CHECK.
    129   EXPECT_DEATH(TestGCDSourceCancel(), "Shadow byte legend");
    130 }
    131 
    132 TEST(AddressSanitizerMac, GCDGroupAsync) {
    133   // Make sure the whole ASan report is printed, i.e. that we don't die
    134   // on a CHECK.
    135   EXPECT_DEATH(TestGCDGroupAsync(), "Shadow byte legend");
    136 }
    137 
    138 void *MallocIntrospectionLockWorker(void *_) {
    139   const int kNumPointers = 100;
    140   int i;
    141   void *pointers[kNumPointers];
    142   for (i = 0; i < kNumPointers; i++) {
    143     pointers[i] = malloc(i + 1);
    144   }
    145   for (i = 0; i < kNumPointers; i++) {
    146     free(pointers[i]);
    147   }
    148 
    149   return NULL;
    150 }
    151 
    152 void *MallocIntrospectionLockForker(void *_) {
    153   pid_t result = fork();
    154   if (result == -1) {
    155     perror("fork");
    156   }
    157   assert(result != -1);
    158   if (result == 0) {
    159     // Call malloc in the child process to make sure we won't deadlock.
    160     void *ptr = malloc(42);
    161     free(ptr);
    162     exit(0);
    163   } else {
    164     // Return in the parent process.
    165     return NULL;
    166   }
    167 }
    168 
    169 TEST(AddressSanitizerMac, MallocIntrospectionLock) {
    170   // Incorrect implementation of force_lock and force_unlock in our malloc zone
    171   // will cause forked processes to deadlock.
    172   // TODO(glider): need to detect that none of the child processes deadlocked.
    173   const int kNumWorkers = 5, kNumIterations = 100;
    174   int i, iter;
    175   for (iter = 0; iter < kNumIterations; iter++) {
    176     pthread_t workers[kNumWorkers], forker;
    177     for (i = 0; i < kNumWorkers; i++) {
    178       PTHREAD_CREATE(&workers[i], 0, MallocIntrospectionLockWorker, 0);
    179     }
    180     PTHREAD_CREATE(&forker, 0, MallocIntrospectionLockForker, 0);
    181     for (i = 0; i < kNumWorkers; i++) {
    182       PTHREAD_JOIN(workers[i], 0);
    183     }
    184     PTHREAD_JOIN(forker, 0);
    185   }
    186 }
    187 
    188 void *TSDAllocWorker(void *test_key) {
    189   if (test_key) {
    190     void *mem = malloc(10);
    191     pthread_setspecific(*(pthread_key_t*)test_key, mem);
    192   }
    193   return NULL;
    194 }
    195 
    196 TEST(AddressSanitizerMac, DISABLED_TSDWorkqueueTest) {
    197   pthread_t th;
    198   pthread_key_t test_key;
    199   pthread_key_create(&test_key, CallFreeOnWorkqueue);
    200   PTHREAD_CREATE(&th, NULL, TSDAllocWorker, &test_key);
    201   PTHREAD_JOIN(th, NULL);
    202   pthread_key_delete(test_key);
    203 }
    204 
    205 // Test that CFStringCreateCopy does not copy constant strings.
    206 TEST(AddressSanitizerMac, CFStringCreateCopy) {
    207   CFStringRef str = CFSTR("Hello world!\n");
    208   CFStringRef str2 = CFStringCreateCopy(0, str);
    209   EXPECT_EQ(str, str2);
    210 }
    211 
    212 TEST(AddressSanitizerMac, NSObjectOOB) {
    213   // Make sure that our allocators are used for NSObjects.
    214   EXPECT_DEATH(TestOOBNSObjects(), "heap-buffer-overflow");
    215 }
    216 
    217 // Make sure that correct pointer is passed to free() when deallocating a
    218 // NSURL object.
    219 // See https://github.com/google/sanitizers/issues/70.
    220 TEST(AddressSanitizerMac, NSURLDeallocation) {
    221   TestNSURLDeallocation();
    222 }
    223 
    224 // See https://github.com/google/sanitizers/issues/109.
    225 TEST(AddressSanitizerMac, Mstats) {
    226   malloc_statistics_t stats1, stats2;
    227   malloc_zone_statistics(/*all zones*/NULL, &stats1);
    228   const size_t kMallocSize = 100000;
    229   void *alloc = Ident(malloc(kMallocSize));
    230   malloc_zone_statistics(/*all zones*/NULL, &stats2);
    231   EXPECT_GT(stats2.blocks_in_use, stats1.blocks_in_use);
    232   EXPECT_GE(stats2.size_in_use - stats1.size_in_use, kMallocSize);
    233   free(alloc);
    234   // Even the default OSX allocator may not change the stats after free().
    235 }
    236 
    237