Because CFAllocatorCreate() should also be called after __CFInitialize() on Lion,
do so by factoring the CFAllocator logic into ReplaceCFAllocator(), which is called from
either the __CFInitialize wrapper or __asan_init(), depending on which of them is called later.


git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@159822 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_malloc_mac.cc b/lib/asan/asan_malloc_mac.cc
index 34591eb..16e9201 100644
--- a/lib/asan/asan_malloc_mac.cc
+++ b/lib/asan/asan_malloc_mac.cc
@@ -35,6 +35,7 @@
 // TODO(glider): do we need both zones?
 static malloc_zone_t *system_malloc_zone = 0;
 static malloc_zone_t *system_purgeable_zone = 0;
+static malloc_zone_t asan_zone;
 CFAllocatorRef cf_asan = 0;
 
 // The free() implementation provided by OS X calls malloc_zone_from_ptr()
@@ -80,6 +81,10 @@
   }
 }
 
+namespace __asan {
+  void ReplaceCFAllocator();
+}
+
 // We can't always replace the default CFAllocator with cf_asan right in
 // ReplaceSystemMalloc(), because it is sometimes called before
 // __CFInitialize(), when the default allocator is invalid and replacing it may
@@ -91,11 +96,13 @@
 // and http://opensource.apple.com/source/CF/CF-550.43/CFRuntime.c
 INTERCEPTOR(void, __CFInitialize) {
   CHECK(FLAG_replace_cfallocator);
+  CHECK(asan_inited);
   REAL(__CFInitialize)();
-  if (cf_asan) CFAllocatorSetDefault(cf_asan);
+  ReplaceCFAllocator();
 }
 
 namespace {
+
 // TODO(glider): the mz_* functions should be united with the Linux wrappers,
 // as they are basically copied from there.
 size_t mz_size(malloc_zone_t* zone, const void* ptr) {
@@ -320,6 +327,19 @@
 extern int __CFRuntimeClassTableSize;
 
 namespace __asan {
+void ReplaceCFAllocator() {
+  static CFAllocatorContext asan_context = {
+        /*version*/ 0, /*info*/ &asan_zone,
+        /*retain*/ 0, /*release*/ 0,
+        /*copyDescription*/0,
+        /*allocate*/ &cf_malloc,
+        /*reallocate*/ &cf_realloc,
+        /*deallocate*/ &cf_free,
+        /*preferredSize*/ 0 };
+  cf_asan = CFAllocatorCreate(kCFAllocatorUseContext, &asan_context);
+  CFAllocatorSetDefault(cf_asan);
+}
+
 void ReplaceSystemMalloc() {
   static malloc_introspection_t asan_introspection;
   // Ok to use internal_memset, these places are not performance-critical.
@@ -333,7 +353,6 @@
   asan_introspection.force_lock = &mi_force_lock;
   asan_introspection.force_unlock = &mi_force_unlock;
 
-  static malloc_zone_t asan_zone;
   internal_memset(&asan_zone, 0, sizeof(malloc_zone_t));
 
   // Start with a version 4 zone which is used for OS X 10.4 and 10.5.
@@ -385,23 +404,14 @@
   CHECK(malloc_default_zone() == &asan_zone);
 
   if (FLAG_replace_cfallocator) {
-    static CFAllocatorContext asan_context =
-        { /*version*/ 0, /*info*/ &asan_zone,
-          /*retain*/ 0, /*release*/ 0,
-          /*copyDescription*/0,
-          /*allocate*/ &cf_malloc,
-          /*reallocate*/ &cf_realloc,
-          /*deallocate*/ &cf_free,
-          /*preferredSize*/ 0 };
-    cf_asan = CFAllocatorCreate(kCFAllocatorUseContext, &asan_context);
-    // If __CFInitialize() hasn't been called yet, cf_asan will be installed
-    // as the default allocator after __CFInitialize() finishes (see the
-    // interceptor for __CFInitialize() above). Otherwise install cf_asan right
-    // now. On both Snow Leopard and Lion __CFInitialize() calls
+    // If __CFInitialize() hasn't been called yet, cf_asan will be created and
+    // installed as the default allocator after __CFInitialize() finishes (see
+    // the interceptor for __CFInitialize() above). Otherwise install cf_asan
+    // right now. On both Snow Leopard and Lion __CFInitialize() calls
     // __CFAllocatorInitialize(), which initializes the _base._cfisa field of
     // the default allocators we check here.
     if (((CFRuntimeBase*)kCFAllocatorSystemDefault)->_cfisa) {
-      CFAllocatorSetDefault(cf_asan);
+      ReplaceCFAllocator();
     }
   }
 }