[llvm-commits] [compiler-rt] r158863 - in /compiler-rt/trunk/lib/asan: asan_mac.cc asan_malloc_mac.cc tests/asan_test.cc

Alexander Potapenko glider at google.com
Wed Jun 20 15:29:09 PDT 2012


Author: glider
Date: Wed Jun 20 17:29:09 2012
New Revision: 158863

URL: http://llvm.org/viewvc/llvm-project?rev=158863&view=rev
Log:
Actually intercept free() to ensure that the deallocations caused by other functions directly calling it are routed to our allocator.
For the allocations that do not belong to any malloc zone check whether they're padded with a pointer to ASan's CFAllocator. If so, free the original (unpadded) pointer.
This should fix AddressSanitizerMac.NSURLDeallocation and issue 70.

Modified:
    compiler-rt/trunk/lib/asan/asan_mac.cc
    compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
    compiler-rt/trunk/lib/asan/tests/asan_test.cc

Modified: compiler-rt/trunk/lib/asan/asan_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_mac.cc?rev=158863&r1=158862&r2=158863&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_mac.cc Wed Jun 20 17:29:09 2012
@@ -29,8 +29,9 @@
 #include <sys/resource.h>
 #include <sys/sysctl.h>
 #include <sys/ucontext.h>
-#include <pthread.h>
 #include <fcntl.h>
+#include <pthread.h>
+#include <stdlib.h>  // for free()
 #include <unistd.h>
 #include <libkern/OSAtomic.h>
 #include <CoreFoundation/CFString.h>
@@ -294,6 +295,8 @@
                                 asan_dispatch_call_block_and_release);
 }
 
+DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr);
+
 INTERCEPTOR(void, dispatch_sync_f, dispatch_queue_t dq, void *ctxt,
                                    dispatch_function_t func) {
   GET_STACK_TRACE_HERE(kStackTraceMax);
@@ -447,6 +450,9 @@
   // Until this problem is fixed we need to check that the string is
   // non-constant before calling CFStringCreateCopy.
   CHECK(INTERCEPT_FUNCTION(CFStringCreateCopy));
+  // Some of the library functions call free() directly, so we have to
+  // intercept it.
+  CHECK(INTERCEPT_FUNCTION(free));
 }
 
 }  // namespace __asan

Modified: compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_mac.cc?rev=158863&r1=158862&r2=158863&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_mac.cc Wed Jun 20 17:29:09 2012
@@ -30,12 +30,25 @@
 // ---------------------- Replacement functions ---------------- {{{1
 using namespace __asan;  // NOLINT
 
+// TODO(glider): do we need both zones?
+static malloc_zone_t *system_malloc_zone = 0;
+static malloc_zone_t *system_purgeable_zone = 0;
+CFAllocatorRef cf_asan = 0;
+
 // The free() implementation provided by OS X calls malloc_zone_from_ptr()
 // to find the owner of |ptr|. If the result is 0, an invalid free() is
 // reported. Our implementation falls back to asan_free() in this case
 // in order to print an ASan-style report.
-extern "C"
-void free(void *ptr) {
+//
+// For the objects created by _CFRuntimeCreateInstance a CFAllocatorRef is
+// placed at the beginning of the allocated chunk and the pointer returned by
+// our allocator is off by sizeof(CFAllocatorRef). This pointer can be then
+// passed directly to free(), which will lead to errors.
+// To overcome this we're checking whether |ptr-sizeof(CFAllocatorRef)|
+// contains a pointer to our CFAllocator (assuming no other allocator is used).
+// See http://code.google.com/p/address-sanitizer/issues/detail?id=70 for more
+// info.
+INTERCEPTOR(void, free, void *ptr) {
   malloc_zone_t *zone = malloc_zone_from_ptr(ptr);
   if (zone) {
 #if defined(MAC_OS_X_VERSION_10_6) && \
@@ -49,16 +62,22 @@
     malloc_zone_free(zone, ptr);
 #endif
   } else {
+    if (FLAG_replace_cfallocator) {
+      // Make sure we're not hitting the previous page. This may be incorrect
+      // if ASan's malloc returns an address ending with 0xFF8, which will be
+      // then padded to a page boundary with a CFAllocatorRef.
+      uptr arith_ptr = (uptr)ptr;
+      if ((arith_ptr & 0xFFF) > sizeof(CFAllocatorRef)) {
+        CFAllocatorRef *saved =
+            (CFAllocatorRef*)(arith_ptr - sizeof(CFAllocatorRef));
+        if ((*saved == cf_asan) && asan_mz_size(saved)) ptr = (void*)saved;
+      }
+    }
     GET_STACK_TRACE_HERE_FOR_FREE(ptr);
     asan_free(ptr, &stack);
   }
 }
 
-// TODO(glider): do we need both zones?
-static malloc_zone_t *system_malloc_zone = 0;
-static malloc_zone_t *system_purgeable_zone = 0;
-
-// We need to provide wrappers around all the libc functions.
 namespace {
 // TODO(glider): the mz_* functions should be united with the Linux wrappers,
 // as they are basically copied from there.
@@ -388,8 +407,7 @@
           /*reallocate*/ &cf_realloc,
           /*deallocate*/ &cf_free,
           /*preferredSize*/ 0 };
-    CFAllocatorRef cf_asan =
-        CFAllocatorCreate(kCFAllocatorUseContext, &asan_context);
+    cf_asan = CFAllocatorCreate(kCFAllocatorUseContext, &asan_context);
     CFAllocatorSetDefault(cf_asan);
   }
 }

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=158863&r1=158862&r2=158863&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/tests/asan_test.cc (original)
+++ compiler-rt/trunk/lib/asan/tests/asan_test.cc Wed Jun 20 17:29:09 2012
@@ -2053,7 +2053,7 @@
 // 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, DISABLED_NSURLDeallocation) {
+TEST(AddressSanitizerMac, NSURLDeallocation) {
   TestNSURLDeallocation();
 }
 #endif  // __APPLE__





More information about the llvm-commits mailing list