[llvm-commits] [compiler-rt] r173048 - in /compiler-rt/trunk/lib/asan/tests: CMakeLists.txt asan_mac_test.cc asan_mac_test.mm asan_mac_test_helpers.mm asan_test.cc

Alexander Potapenko glider at google.com
Mon Jan 21 06:49:56 PST 2013


Author: glider
Date: Mon Jan 21 08:49:55 2013
New Revision: 173048

URL: http://llvm.org/viewvc/llvm-project?rev=173048&view=rev
Log:
[ASan] Move Mac-specific tests to asan_mac_test.cc


Added:
    compiler-rt/trunk/lib/asan/tests/asan_mac_test.cc
    compiler-rt/trunk/lib/asan/tests/asan_mac_test_helpers.mm
      - copied unchanged from r173030, compiler-rt/trunk/lib/asan/tests/asan_mac_test.mm
Removed:
    compiler-rt/trunk/lib/asan/tests/asan_mac_test.mm
Modified:
    compiler-rt/trunk/lib/asan/tests/CMakeLists.txt
    compiler-rt/trunk/lib/asan/tests/asan_test.cc

Modified: compiler-rt/trunk/lib/asan/tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/CMakeLists.txt?rev=173048&r1=173047&r2=173048&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/asan/tests/CMakeLists.txt Mon Jan 21 08:49:55 2013
@@ -140,7 +140,9 @@
   asan_compile(ASAN_INST_TEST_OBJECTS asan_test.cc ${arch}
                ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
   if (APPLE)
-    asan_compile(ASAN_INST_TEST_OBJECTS asan_mac_test.mm ${arch}
+    asan_compile(ASAN_INST_TEST_OBJECTS asan_mac_test.cc ${arch}
+                 ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS})
+    asan_compile(ASAN_INST_TEST_OBJECTS asan_mac_test_helpers.mm ${arch}
                  ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} -ObjC)
   endif()
   # Uninstrumented tests.

Added: compiler-rt/trunk/lib/asan/tests/asan_mac_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_mac_test.cc?rev=173048&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_mac_test.cc (added)
+++ compiler-rt/trunk/lib/asan/tests/asan_mac_test.cc Mon Jan 21 08:49:55 2013
@@ -0,0 +1,236 @@
+//===-- asan_test_mac.cc --------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+//===----------------------------------------------------------------------===//
+
+#include "asan_test_utils.h"
+
+#include "asan_mac_test.h"
+
+#include <malloc/malloc.h>
+#include <AvailabilityMacros.h>  // For MAC_OS_X_VERSION_*
+#include <CoreFoundation/CFString.h>
+
+TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree) {
+  EXPECT_DEATH(
+      CFAllocatorDefaultDoubleFree(NULL),
+      "attempting double-free");
+}
+
+void CFAllocator_DoubleFreeOnPthread() {
+  pthread_t child;
+  PTHREAD_CREATE(&child, NULL, CFAllocatorDefaultDoubleFree, NULL);
+  PTHREAD_JOIN(child, NULL);  // Shouldn't be reached.
+}
+
+TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree_ChildPhread) {
+  EXPECT_DEATH(CFAllocator_DoubleFreeOnPthread(), "attempting double-free");
+}
+
+namespace {
+
+void *GLOB;
+
+void *CFAllocatorAllocateToGlob(void *unused) {
+  GLOB = CFAllocatorAllocate(NULL, 100, /*hint*/0);
+  return NULL;
+}
+
+void *CFAllocatorDeallocateFromGlob(void *unused) {
+  char *p = (char*)GLOB;
+  p[100] = 'A';  // ASan should report an error here.
+  CFAllocatorDeallocate(NULL, GLOB);
+  return NULL;
+}
+
+void CFAllocator_PassMemoryToAnotherThread() {
+  pthread_t th1, th2;
+  PTHREAD_CREATE(&th1, NULL, CFAllocatorAllocateToGlob, NULL);
+  PTHREAD_JOIN(th1, NULL);
+  PTHREAD_CREATE(&th2, NULL, CFAllocatorDeallocateFromGlob, NULL);
+  PTHREAD_JOIN(th2, NULL);
+}
+
+TEST(AddressSanitizerMac, CFAllocator_PassMemoryToAnotherThread) {
+  EXPECT_DEATH(CFAllocator_PassMemoryToAnotherThread(),
+               "heap-buffer-overflow");
+}
+
+}  // namespace
+
+// TODO(glider): figure out whether we still need these tests. Is it correct
+// to intercept the non-default CFAllocators?
+TEST(AddressSanitizerMac, DISABLED_CFAllocatorSystemDefaultDoubleFree) {
+  EXPECT_DEATH(
+      CFAllocatorSystemDefaultDoubleFree(),
+      "attempting double-free");
+}
+
+// We're intercepting malloc, so kCFAllocatorMalloc is routed to ASan.
+TEST(AddressSanitizerMac, CFAllocatorMallocDoubleFree) {
+  EXPECT_DEATH(CFAllocatorMallocDoubleFree(), "attempting double-free");
+}
+
+TEST(AddressSanitizerMac, DISABLED_CFAllocatorMallocZoneDoubleFree) {
+  EXPECT_DEATH(CFAllocatorMallocZoneDoubleFree(), "attempting double-free");
+}
+
+// For libdispatch tests below we check that ASan got to the shadow byte
+// legend, i.e. managed to print the thread stacks (this almost certainly
+// means that the libdispatch task creation has been intercepted correctly).
+TEST(AddressSanitizerMac, GCDDispatchAsync) {
+  // Make sure the whole ASan report is printed, i.e. that we don't die
+  // on a CHECK.
+  EXPECT_DEATH(TestGCDDispatchAsync(), "Shadow byte legend");
+}
+
+TEST(AddressSanitizerMac, GCDDispatchSync) {
+  // Make sure the whole ASan report is printed, i.e. that we don't die
+  // on a CHECK.
+  EXPECT_DEATH(TestGCDDispatchSync(), "Shadow byte legend");
+}
+
+
+TEST(AddressSanitizerMac, GCDReuseWqthreadsAsync) {
+  // Make sure the whole ASan report is printed, i.e. that we don't die
+  // on a CHECK.
+  EXPECT_DEATH(TestGCDReuseWqthreadsAsync(), "Shadow byte legend");
+}
+
+TEST(AddressSanitizerMac, GCDReuseWqthreadsSync) {
+  // Make sure the whole ASan report is printed, i.e. that we don't die
+  // on a CHECK.
+  EXPECT_DEATH(TestGCDReuseWqthreadsSync(), "Shadow byte legend");
+}
+
+TEST(AddressSanitizerMac, GCDDispatchAfter) {
+  // Make sure the whole ASan report is printed, i.e. that we don't die
+  // on a CHECK.
+  EXPECT_DEATH(TestGCDDispatchAfter(), "Shadow byte legend");
+}
+
+TEST(AddressSanitizerMac, GCDSourceEvent) {
+  // Make sure the whole ASan report is printed, i.e. that we don't die
+  // on a CHECK.
+  EXPECT_DEATH(TestGCDSourceEvent(), "Shadow byte legend");
+}
+
+TEST(AddressSanitizerMac, GCDSourceCancel) {
+  // Make sure the whole ASan report is printed, i.e. that we don't die
+  // on a CHECK.
+  EXPECT_DEATH(TestGCDSourceCancel(), "Shadow byte legend");
+}
+
+TEST(AddressSanitizerMac, GCDGroupAsync) {
+  // Make sure the whole ASan report is printed, i.e. that we don't die
+  // on a CHECK.
+  EXPECT_DEATH(TestGCDGroupAsync(), "Shadow byte legend");
+}
+
+void *MallocIntrospectionLockWorker(void *_) {
+  const int kNumPointers = 100;
+  int i;
+  void *pointers[kNumPointers];
+  for (i = 0; i < kNumPointers; i++) {
+    pointers[i] = malloc(i + 1);
+  }
+  for (i = 0; i < kNumPointers; i++) {
+    free(pointers[i]);
+  }
+
+  return NULL;
+}
+
+void *MallocIntrospectionLockForker(void *_) {
+  pid_t result = fork();
+  if (result == -1) {
+    perror("fork");
+  }
+  assert(result != -1);
+  if (result == 0) {
+    // Call malloc in the child process to make sure we won't deadlock.
+    void *ptr = malloc(42);
+    free(ptr);
+    exit(0);
+  } else {
+    // Return in the parent process.
+    return NULL;
+  }
+}
+
+TEST(AddressSanitizerMac, MallocIntrospectionLock) {
+  // Incorrect implementation of force_lock and force_unlock in our malloc zone
+  // will cause forked processes to deadlock.
+  // TODO(glider): need to detect that none of the child processes deadlocked.
+  const int kNumWorkers = 5, kNumIterations = 100;
+  int i, iter;
+  for (iter = 0; iter < kNumIterations; iter++) {
+    pthread_t workers[kNumWorkers], forker;
+    for (i = 0; i < kNumWorkers; i++) {
+      PTHREAD_CREATE(&workers[i], 0, MallocIntrospectionLockWorker, 0);
+    }
+    PTHREAD_CREATE(&forker, 0, MallocIntrospectionLockForker, 0);
+    for (i = 0; i < kNumWorkers; i++) {
+      PTHREAD_JOIN(workers[i], 0);
+    }
+    PTHREAD_JOIN(forker, 0);
+  }
+}
+
+void *TSDAllocWorker(void *test_key) {
+  if (test_key) {
+    void *mem = malloc(10);
+    pthread_setspecific(*(pthread_key_t*)test_key, mem);
+  }
+  return NULL;
+}
+
+TEST(AddressSanitizerMac, DISABLED_TSDWorkqueueTest) {
+  pthread_t th;
+  pthread_key_t test_key;
+  pthread_key_create(&test_key, CallFreeOnWorkqueue);
+  PTHREAD_CREATE(&th, NULL, TSDAllocWorker, &test_key);
+  PTHREAD_JOIN(th, NULL);
+  pthread_key_delete(test_key);
+}
+
+// Test that CFStringCreateCopy does not copy constant strings.
+TEST(AddressSanitizerMac, CFStringCreateCopy) {
+  CFStringRef str = CFSTR("Hello world!\n");
+  CFStringRef str2 = CFStringCreateCopy(0, str);
+  EXPECT_EQ(str, str2);
+}
+
+TEST(AddressSanitizerMac, NSObjectOOB) {
+  // Make sure that our allocators are used for NSObjects.
+  EXPECT_DEATH(TestOOBNSObjects(), "heap-buffer-overflow");
+}
+
+// Make sure that correct pointer is passed to free() when deallocating a
+// NSURL object.
+// See http://code.google.com/p/address-sanitizer/issues/detail?id=70.
+TEST(AddressSanitizerMac, NSURLDeallocation) {
+  TestNSURLDeallocation();
+}
+
+// See http://code.google.com/p/address-sanitizer/issues/detail?id=109.
+TEST(AddressSanitizerMac, Mstats) {
+  malloc_statistics_t stats1, stats2;
+  malloc_zone_statistics(/*all zones*/NULL, &stats1);
+  const size_t kMallocSize = 100000;
+  void *alloc = Ident(malloc(kMallocSize));
+  malloc_zone_statistics(/*all zones*/NULL, &stats2);
+  EXPECT_GT(stats2.blocks_in_use, stats1.blocks_in_use);
+  EXPECT_GE(stats2.size_in_use - stats1.size_in_use, kMallocSize);
+  free(alloc);
+  // Even the default OSX allocator may not change the stats after free().
+}
+

Removed: compiler-rt/trunk/lib/asan/tests/asan_mac_test.mm
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_mac_test.mm?rev=173047&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_mac_test.mm (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_mac_test.mm (removed)
@@ -1,237 +0,0 @@
-// Mac OS X 10.6 or higher only.
-#include <dispatch/dispatch.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#import <CoreFoundation/CFBase.h>
-#import <Foundation/NSObject.h>
-#import <Foundation/NSURL.h>
-
-// This is a (void*)(void*) function so it can be passed to pthread_create.
-void *CFAllocatorDefaultDoubleFree(void *unused) {
-  void *mem =  CFAllocatorAllocate(kCFAllocatorDefault, 5, 0);
-  CFAllocatorDeallocate(kCFAllocatorDefault, mem);
-  CFAllocatorDeallocate(kCFAllocatorDefault, mem);
-  return 0;
-}
-
-void CFAllocatorSystemDefaultDoubleFree() {
-  void *mem =  CFAllocatorAllocate(kCFAllocatorSystemDefault, 5, 0);
-  CFAllocatorDeallocate(kCFAllocatorSystemDefault, mem);
-  CFAllocatorDeallocate(kCFAllocatorSystemDefault, mem);
-}
-
-void CFAllocatorMallocDoubleFree() {
-  void *mem =  CFAllocatorAllocate(kCFAllocatorMalloc, 5, 0);
-  CFAllocatorDeallocate(kCFAllocatorMalloc, mem);
-  CFAllocatorDeallocate(kCFAllocatorMalloc, mem);
-}
-
-void CFAllocatorMallocZoneDoubleFree() {
-  void *mem =  CFAllocatorAllocate(kCFAllocatorMallocZone, 5, 0);
-  CFAllocatorDeallocate(kCFAllocatorMallocZone, mem);
-  CFAllocatorDeallocate(kCFAllocatorMallocZone, mem);
-}
-
-__attribute__((noinline))
-void access_memory(char *a) {
-  *a = 0;
-}
-
-// Test the +load instrumentation.
-// Because the +load methods are invoked before anything else is initialized,
-// it makes little sense to wrap the code below into a gTest test case.
-// If AddressSanitizer doesn't instrument the +load method below correctly,
-// everything will just crash.
-
-char kStartupStr[] =
-    "If your test didn't crash, AddressSanitizer is instrumenting "
-    "the +load methods correctly.";
-
- at interface LoadSomething : NSObject {
-}
- at end
-
- at implementation LoadSomething
-
-+(void) load {
-  for (size_t i = 0; i < strlen(kStartupStr); i++) {
-    access_memory(&kStartupStr[i]);  // make sure no optimizations occur.
-  }
-  // Don't print anything here not to interfere with the death tests.
-}
-
- at end
-
-void worker_do_alloc(int size) {
-  char * volatile mem = (char * volatile)malloc(size);
-  mem[0] = 0; // Ok
-  free(mem);
-}
-
-void worker_do_crash(int size) {
-  char * volatile mem = (char * volatile)malloc(size);
-  access_memory(&mem[size]);  // BOOM
-  free(mem);
-}
-
-// Tests for the Grand Central Dispatch. See
-// http://developer.apple.com/library/mac/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html
-// for the reference.
-
-void TestGCDDispatchAsync() {
-  dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
-  dispatch_block_t block = ^{ worker_do_crash(1024); };
-  // dispatch_async() runs the task on a worker thread that does not go through
-  // pthread_create(). We need to verify that AddressSanitizer notices that the
-  // thread has started.
-  dispatch_async(queue, block);
-  // TODO(glider): this is hacky. Need to wait for the worker instead.
-  sleep(1);
-}
-
-void TestGCDDispatchSync() {
-  dispatch_queue_t queue = dispatch_get_global_queue(2, 0);
-  dispatch_block_t block = ^{ worker_do_crash(1024); };
-  // dispatch_sync() runs the task on a worker thread that does not go through
-  // pthread_create(). We need to verify that AddressSanitizer notices that the
-  // thread has started.
-  dispatch_sync(queue, block);
-  // TODO(glider): this is hacky. Need to wait for the worker instead.
-  sleep(1);
-}
-
-// libdispatch spawns a rather small number of threads and reuses them. We need
-// to make sure AddressSanitizer handles the reusing correctly.
-void TestGCDReuseWqthreadsAsync() {
-  dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
-  dispatch_block_t block_alloc = ^{ worker_do_alloc(1024); };
-  dispatch_block_t block_crash = ^{ worker_do_crash(1024); };
-  for (int i = 0; i < 100; i++) {
-    dispatch_async(queue, block_alloc);
-  }
-  dispatch_async(queue, block_crash);
-  // TODO(glider): this is hacky. Need to wait for the workers instead.
-  sleep(1);
-}
-
-// Try to trigger abnormal behaviour of dispatch_sync() being unhandled by us.
-void TestGCDReuseWqthreadsSync() {
-  dispatch_queue_t queue[4];
-  queue[0] = dispatch_get_global_queue(2, 0);
-  queue[1] = dispatch_get_global_queue(0, 0);
-  queue[2] = dispatch_get_global_queue(-2, 0);
-  queue[3] = dispatch_queue_create("my_queue", NULL);
-  dispatch_block_t block_alloc = ^{ worker_do_alloc(1024); };
-  dispatch_block_t block_crash = ^{ worker_do_crash(1024); };
-  for (int i = 0; i < 1000; i++) {
-    dispatch_sync(queue[i % 4], block_alloc);
-  }
-  dispatch_sync(queue[3], block_crash);
-  // TODO(glider): this is hacky. Need to wait for the workers instead.
-  sleep(1);
-}
-
-void TestGCDDispatchAfter() {
-  dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
-  dispatch_block_t block_crash = ^{ worker_do_crash(1024); };
-  // Schedule the event one second from the current time.
-  dispatch_time_t milestone =
-      dispatch_time(DISPATCH_TIME_NOW, 1LL * NSEC_PER_SEC);
-  dispatch_after(milestone, queue, block_crash);
-  // Let's wait for a bit longer now.
-  // TODO(glider): this is still hacky.
-  sleep(2);
-}
-
-void worker_do_deallocate(void *ptr) {
-  free(ptr);
-}
-
-void CallFreeOnWorkqueue(void *tsd) {
-  dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
-  dispatch_block_t block_dealloc = ^{ worker_do_deallocate(tsd); };
-  dispatch_async(queue, block_dealloc);
-  // Do not wait for the worker to free the memory -- nobody is going to touch
-  // it.
-}
-
-void TestGCDSourceEvent() {
-  dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
-  dispatch_source_t timer =
-      dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
-  // Schedule the timer one second from the current time.
-  dispatch_time_t milestone =
-      dispatch_time(DISPATCH_TIME_NOW, 1LL * NSEC_PER_SEC);
-
-  dispatch_source_set_timer(timer, milestone, DISPATCH_TIME_FOREVER, 0);
-  char * volatile mem = (char * volatile)malloc(10);
-  dispatch_source_set_event_handler(timer, ^{
-    access_memory(&mem[10]);
-  });
-  dispatch_resume(timer);
-  sleep(2);
-}
-
-void TestGCDSourceCancel() {
-  dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
-  dispatch_source_t timer =
-      dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
-  // Schedule the timer one second from the current time.
-  dispatch_time_t milestone =
-      dispatch_time(DISPATCH_TIME_NOW, 1LL * NSEC_PER_SEC);
-
-  dispatch_source_set_timer(timer, milestone, DISPATCH_TIME_FOREVER, 0);
-  char * volatile mem = (char * volatile)malloc(10);
-  // Both dispatch_source_set_cancel_handler() and
-  // dispatch_source_set_event_handler() use dispatch_barrier_async_f().
-  // It's tricky to test dispatch_source_set_cancel_handler() separately,
-  // so we test both here.
-  dispatch_source_set_event_handler(timer, ^{
-    dispatch_source_cancel(timer);
-  });
-  dispatch_source_set_cancel_handler(timer, ^{
-    access_memory(&mem[10]);
-  });
-  dispatch_resume(timer);
-  sleep(2);
-}
-
-void TestGCDGroupAsync() {
-  dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
-  dispatch_group_t group = dispatch_group_create(); 
-  char * volatile mem = (char * volatile)malloc(10);
-  dispatch_group_async(group, queue, ^{
-    access_memory(&mem[10]);
-  });
-  dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
-}
-
- at interface FixedArray : NSObject {
-  int items[10];
-}
- at end
-
- at implementation FixedArray
--(int) access: (int)index {
-  return items[index];
-}
- at end
-
-void TestOOBNSObjects() {
-  id anObject = [FixedArray new];
-  [anObject access:1];
-  [anObject access:11];
-  [anObject release];
-}
-
-void TestNSURLDeallocation() {
-  NSURL *base =
-      [[NSURL alloc] initWithString:@"file://localhost/Users/glider/Library/"];
-  volatile NSURL *u =
-      [[NSURL alloc] initWithString:@"Saved Application State"
-                     relativeToURL:base];
-  [u release];
-}

Modified: compiler-rt/trunk/lib/asan/tests/asan_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/tests/asan_test.cc?rev=173048&r1=173047&r2=173048&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Mon Jan 21 08:49:55 2013
@@ -37,11 +37,7 @@
 
 #ifndef __APPLE__
 #include <malloc.h>
-#else
-#include <malloc/malloc.h>
-#include <AvailabilityMacros.h>  // For MAC_OS_X_VERSION_*
-#include <CoreFoundation/CFString.h>
-#endif  // __APPLE__
+#endif
 
 #if ASAN_HAS_EXCEPTIONS
 # define ASAN_THROW(x) throw (x)
@@ -1097,15 +1093,6 @@
   free(heap_string);
 }
 
-static inline char* MallocAndMemsetString(size_t size, char ch) {
-  char *s = Ident((char*)malloc(size));
-  memset(s, ch, size);
-  return s;
-}
-static inline char* MallocAndMemsetString(size_t size) {
-  return MallocAndMemsetString(size, 'z');
-}
-
 #ifndef __APPLE__
 TEST(AddressSanitizer, StrNLenOOBTest) {
   size_t size = Ident(123);
@@ -1126,6 +1113,15 @@
 }
 #endif
 
+static inline char* MallocAndMemsetString(size_t size, char ch) {
+  char *s = Ident((char*)malloc(size));
+  memset(s, ch, size);
+  return s;
+}
+static inline char* MallocAndMemsetString(size_t size) {
+  return MallocAndMemsetString(size, 'z');
+}
+
 TEST(AddressSanitizer, StrDupOOBTest) {
   size_t size = Ident(42);
   char *str = MallocAndMemsetString(size);
@@ -2160,223 +2156,6 @@
   delete [] Ident(x);
 }
 
-#ifdef __APPLE__
-#include "asan_mac_test.h"
-TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree) {
-  EXPECT_DEATH(
-      CFAllocatorDefaultDoubleFree(NULL),
-      "attempting double-free");
-}
-
-void CFAllocator_DoubleFreeOnPthread() {
-  pthread_t child;
-  PTHREAD_CREATE(&child, NULL, CFAllocatorDefaultDoubleFree, NULL);
-  PTHREAD_JOIN(child, NULL);  // Shouldn't be reached.
-}
-
-TEST(AddressSanitizerMac, CFAllocatorDefaultDoubleFree_ChildPhread) {
-  EXPECT_DEATH(CFAllocator_DoubleFreeOnPthread(), "attempting double-free");
-}
-
-namespace {
-
-void *GLOB;
-
-void *CFAllocatorAllocateToGlob(void *unused) {
-  GLOB = CFAllocatorAllocate(NULL, 100, /*hint*/0);
-  return NULL;
-}
-
-void *CFAllocatorDeallocateFromGlob(void *unused) {
-  char *p = (char*)GLOB;
-  p[100] = 'A';  // ASan should report an error here.
-  CFAllocatorDeallocate(NULL, GLOB);
-  return NULL;
-}
-
-void CFAllocator_PassMemoryToAnotherThread() {
-  pthread_t th1, th2;
-  PTHREAD_CREATE(&th1, NULL, CFAllocatorAllocateToGlob, NULL);
-  PTHREAD_JOIN(th1, NULL);
-  PTHREAD_CREATE(&th2, NULL, CFAllocatorDeallocateFromGlob, NULL);
-  PTHREAD_JOIN(th2, NULL);
-}
-
-TEST(AddressSanitizerMac, CFAllocator_PassMemoryToAnotherThread) {
-  EXPECT_DEATH(CFAllocator_PassMemoryToAnotherThread(),
-               "heap-buffer-overflow");
-}
-
-}  // namespace
-
-// TODO(glider): figure out whether we still need these tests. Is it correct
-// to intercept the non-default CFAllocators?
-TEST(AddressSanitizerMac, DISABLED_CFAllocatorSystemDefaultDoubleFree) {
-  EXPECT_DEATH(
-      CFAllocatorSystemDefaultDoubleFree(),
-      "attempting double-free");
-}
-
-// We're intercepting malloc, so kCFAllocatorMalloc is routed to ASan.
-TEST(AddressSanitizerMac, CFAllocatorMallocDoubleFree) {
-  EXPECT_DEATH(CFAllocatorMallocDoubleFree(), "attempting double-free");
-}
-
-TEST(AddressSanitizerMac, DISABLED_CFAllocatorMallocZoneDoubleFree) {
-  EXPECT_DEATH(CFAllocatorMallocZoneDoubleFree(), "attempting double-free");
-}
-
-// For libdispatch tests below we check that ASan got to the shadow byte
-// legend, i.e. managed to print the thread stacks (this almost certainly
-// means that the libdispatch task creation has been intercepted correctly).
-TEST(AddressSanitizerMac, GCDDispatchAsync) {
-  // Make sure the whole ASan report is printed, i.e. that we don't die
-  // on a CHECK.
-  EXPECT_DEATH(TestGCDDispatchAsync(), "Shadow byte legend");
-}
-
-TEST(AddressSanitizerMac, GCDDispatchSync) {
-  // Make sure the whole ASan report is printed, i.e. that we don't die
-  // on a CHECK.
-  EXPECT_DEATH(TestGCDDispatchSync(), "Shadow byte legend");
-}
-
-
-TEST(AddressSanitizerMac, GCDReuseWqthreadsAsync) {
-  // Make sure the whole ASan report is printed, i.e. that we don't die
-  // on a CHECK.
-  EXPECT_DEATH(TestGCDReuseWqthreadsAsync(), "Shadow byte legend");
-}
-
-TEST(AddressSanitizerMac, GCDReuseWqthreadsSync) {
-  // Make sure the whole ASan report is printed, i.e. that we don't die
-  // on a CHECK.
-  EXPECT_DEATH(TestGCDReuseWqthreadsSync(), "Shadow byte legend");
-}
-
-TEST(AddressSanitizerMac, GCDDispatchAfter) {
-  // Make sure the whole ASan report is printed, i.e. that we don't die
-  // on a CHECK.
-  EXPECT_DEATH(TestGCDDispatchAfter(), "Shadow byte legend");
-}
-
-TEST(AddressSanitizerMac, GCDSourceEvent) {
-  // Make sure the whole ASan report is printed, i.e. that we don't die
-  // on a CHECK.
-  EXPECT_DEATH(TestGCDSourceEvent(), "Shadow byte legend");
-}
-
-TEST(AddressSanitizerMac, GCDSourceCancel) {
-  // Make sure the whole ASan report is printed, i.e. that we don't die
-  // on a CHECK.
-  EXPECT_DEATH(TestGCDSourceCancel(), "Shadow byte legend");
-}
-
-TEST(AddressSanitizerMac, GCDGroupAsync) {
-  // Make sure the whole ASan report is printed, i.e. that we don't die
-  // on a CHECK.
-  EXPECT_DEATH(TestGCDGroupAsync(), "Shadow byte legend");
-}
-
-void *MallocIntrospectionLockWorker(void *_) {
-  const int kNumPointers = 100;
-  int i;
-  void *pointers[kNumPointers];
-  for (i = 0; i < kNumPointers; i++) {
-    pointers[i] = malloc(i + 1);
-  }
-  for (i = 0; i < kNumPointers; i++) {
-    free(pointers[i]);
-  }
-
-  return NULL;
-}
-
-void *MallocIntrospectionLockForker(void *_) {
-  pid_t result = fork();
-  if (result == -1) {
-    perror("fork");
-  }
-  assert(result != -1);
-  if (result == 0) {
-    // Call malloc in the child process to make sure we won't deadlock.
-    void *ptr = malloc(42);
-    free(ptr);
-    exit(0);
-  } else {
-    // Return in the parent process.
-    return NULL;
-  }
-}
-
-TEST(AddressSanitizerMac, MallocIntrospectionLock) {
-  // Incorrect implementation of force_lock and force_unlock in our malloc zone
-  // will cause forked processes to deadlock.
-  // TODO(glider): need to detect that none of the child processes deadlocked.
-  const int kNumWorkers = 5, kNumIterations = 100;
-  int i, iter;
-  for (iter = 0; iter < kNumIterations; iter++) {
-    pthread_t workers[kNumWorkers], forker;
-    for (i = 0; i < kNumWorkers; i++) {
-      PTHREAD_CREATE(&workers[i], 0, MallocIntrospectionLockWorker, 0);
-    }
-    PTHREAD_CREATE(&forker, 0, MallocIntrospectionLockForker, 0);
-    for (i = 0; i < kNumWorkers; i++) {
-      PTHREAD_JOIN(workers[i], 0);
-    }
-    PTHREAD_JOIN(forker, 0);
-  }
-}
-
-void *TSDAllocWorker(void *test_key) {
-  if (test_key) {
-    void *mem = malloc(10);
-    pthread_setspecific(*(pthread_key_t*)test_key, mem);
-  }
-  return NULL;
-}
-
-TEST(AddressSanitizerMac, DISABLED_TSDWorkqueueTest) {
-  pthread_t th;
-  pthread_key_t test_key;
-  pthread_key_create(&test_key, CallFreeOnWorkqueue);
-  PTHREAD_CREATE(&th, NULL, TSDAllocWorker, &test_key);
-  PTHREAD_JOIN(th, NULL);
-  pthread_key_delete(test_key);
-}
-
-// Test that CFStringCreateCopy does not copy constant strings.
-TEST(AddressSanitizerMac, CFStringCreateCopy) {
-  CFStringRef str = CFSTR("Hello world!\n");
-  CFStringRef str2 = CFStringCreateCopy(0, str);
-  EXPECT_EQ(str, str2);
-}
-
-TEST(AddressSanitizerMac, NSObjectOOB) {
-  // Make sure that our allocators are used for NSObjects.
-  EXPECT_DEATH(TestOOBNSObjects(), "heap-buffer-overflow");
-}
-
-// Make sure that correct pointer is passed to free() when deallocating a
-// NSURL object.
-// See http://code.google.com/p/address-sanitizer/issues/detail?id=70.
-TEST(AddressSanitizerMac, NSURLDeallocation) {
-  TestNSURLDeallocation();
-}
-
-// See http://code.google.com/p/address-sanitizer/issues/detail?id=109.
-TEST(AddressSanitizerMac, Mstats) {
-  malloc_statistics_t stats1, stats2;
-  malloc_zone_statistics(/*all zones*/NULL, &stats1);
-  const size_t kMallocSize = 100000;
-  void *alloc = Ident(malloc(kMallocSize));
-  malloc_zone_statistics(/*all zones*/NULL, &stats2);
-  EXPECT_GT(stats2.blocks_in_use, stats1.blocks_in_use);
-  EXPECT_GE(stats2.size_in_use - stats1.size_in_use, kMallocSize);
-  free(alloc);
-  // Even the default OSX allocator may not change the stats after free().
-}
-#endif  // __APPLE__
 
 // Test that instrumentation of stack allocations takes into account
 // AllocSize of a type, and not its StoreSize (16 vs 10 bytes for long double).





More information about the llvm-commits mailing list