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 22TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree) { 23 EXPECT_DEATH( 24 CFAllocatorDefaultDoubleFree(NULL), 25 "attempting double-free"); 26} 27 28void CFAllocator_DoubleFreeOnPthread() { 29 pthread_t child; 30 PTHREAD_CREATE(&child, NULL, CFAllocatorDefaultDoubleFree, NULL); 31 PTHREAD_JOIN(child, NULL); // Shouldn't be reached. 32} 33 34TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree_ChildPhread) { 35 EXPECT_DEATH(CFAllocator_DoubleFreeOnPthread(), "attempting double-free"); 36} 37 38namespace { 39 40void *GLOB; 41 42void *CFAllocatorAllocateToGlob(void *unused) { 43 GLOB = CFAllocatorAllocate(NULL, 100, /*hint*/0); 44 return NULL; 45} 46 47void *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 54void 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 62TEST(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? 71TEST(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. 78TEST(AddressSanitizerMac, CFAllocatorMallocDoubleFree) { 79 EXPECT_DEATH(CFAllocatorMallocDoubleFree(), "attempting double-free"); 80} 81 82TEST(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). 89TEST(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 95TEST(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 102TEST(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 108TEST(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 114TEST(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 120TEST(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 126TEST(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 132TEST(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 138void *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 152void *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 169TEST(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 188void *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 196TEST(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. 206TEST(AddressSanitizerMac, CFStringCreateCopy) { 207 CFStringRef str = CFSTR("Hello world!\n"); 208 CFStringRef str2 = CFStringCreateCopy(0, str); 209 EXPECT_EQ(str, str2); 210} 211 212TEST(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. 220TEST(AddressSanitizerMac, NSURLDeallocation) { 221 TestNSURLDeallocation(); 222} 223 224// See https://github.com/google/sanitizers/issues/109. 225TEST(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