Fix http://code.google.com/p/address-sanitizer/issues/detail?id=87 by making sure we replace the default CFAllocator only after __CFInitialize has been called.

llvm-svn: 159749
This commit is contained in:
Alexander Potapenko 2012-07-05 14:46:56 +00:00
parent 38b1ec4317
commit 25b567dd0d
2 changed files with 30 additions and 4 deletions

View File

@ -295,8 +295,6 @@ INTERCEPTOR(void, dispatch_async_f, dispatch_queue_t dq, void *ctxt,
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);
@ -428,6 +426,12 @@ INTERCEPTOR(CFStringRef, CFStringCreateCopy, CFAllocatorRef alloc,
}
}
DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
extern "C"
void __CFInitialize();
DECLARE_REAL_AND_INTERCEPTOR(void, __CFInitialize)
namespace __asan {
void InitializeMacInterceptors() {
@ -453,6 +457,9 @@ void InitializeMacInterceptors() {
// Some of the library functions call free() directly, so we have to
// intercept it.
CHECK(INTERCEPT_FUNCTION(free));
if (FLAG_replace_cfallocator) {
CHECK(INTERCEPT_FUNCTION(__CFInitialize));
}
}
} // namespace __asan

View File

@ -78,6 +78,21 @@ INTERCEPTOR(void, free, void *ptr) {
}
}
// 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
// crash the program. Instead we wait for the allocator to initialize and jump
// in just after __CFInitialize(). Nobody is going to allocate memory using
// CFAllocators before that, so we won't miss anything.
//
// See http://code.google.com/p/address-sanitizer/issues/detail?id=87
// and http://opensource.apple.com/source/CF/CF-550.43/CFRuntime.c
INTERCEPTOR(void, __CFInitialize) {
CHECK(FLAG_replace_cfallocator);
REAL(__CFInitialize)();
if (cf_asan) CFAllocatorSetDefault(cf_asan);
}
namespace {
// TODO(glider): the mz_* functions should be united with the Linux wrappers,
// as they are basically copied from there.
@ -300,7 +315,7 @@ boolean_t mi_zone_locked(malloc_zone_t *zone) {
} // unnamed namespace
extern bool kCFUseCollectableAllocator; // is GC on?
extern int __CFRuntimeClassTableSize;
namespace __asan {
void ReplaceSystemMalloc() {
@ -377,7 +392,11 @@ void ReplaceSystemMalloc() {
/*deallocate*/ &cf_free,
/*preferredSize*/ 0 };
cf_asan = CFAllocatorCreate(kCFAllocatorUseContext, &asan_context);
CFAllocatorSetDefault(cf_asan);
// 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 (if
// __CFRuntimeClassTableSize is initialized) install cf_asan right now.
if (__CFRuntimeClassTableSize) CFAllocatorSetDefault(cf_asan);
}
}
} // namespace __asan