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