[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