diff options
-rw-r--r-- | compiler-rt/lib/asan/asan_interceptors.cc | 9 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_mac.cc | 42 | ||||
-rw-r--r-- | compiler-rt/lib/asan/asan_mac.h | 5 | ||||
-rw-r--r-- | compiler-rt/lib/asan/tests/asan_test.cc | 2 |
4 files changed, 56 insertions, 2 deletions
diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index e32d113811a..746b1a000b5 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -94,6 +94,7 @@ dispatch_after_f_f real_dispatch_after_f; dispatch_barrier_async_f_f real_dispatch_barrier_async_f; dispatch_group_async_f_f real_dispatch_group_async_f; pthread_workqueue_additem_np_f real_pthread_workqueue_additem_np; +CFStringCreateCopy_f real_CFStringCreateCopy; #endif sigaction_f real_sigaction; @@ -648,6 +649,14 @@ void InitializeAsanInterceptors() { if (FLAG_v >= 2) { INTERCEPT_FUNCTION(pthread_workqueue_additem_np); } + // Normally CFStringCreateCopy should not copy constant CF strings. + // Replacing the default CFAllocator causes constant strings to be copied + // rather than just returned, which leads to bugs in big applications like + // Chromium and WebKit, see + // http://code.google.com/p/address-sanitizer/issues/detail?id=10 + // Until this problem is fixed we need to check that the string is + // non-constant before calling CFStringCreateCopy. + INTERCEPT_FUNCTION(CFStringCreateCopy); #else // On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it // there. diff --git a/compiler-rt/lib/asan/asan_mac.cc b/compiler-rt/lib/asan/asan_mac.cc index af65c8f58db..a008f2d328a 100644 --- a/compiler-rt/lib/asan/asan_mac.cc +++ b/compiler-rt/lib/asan/asan_mac.cc @@ -42,6 +42,7 @@ extern dispatch_after_f_f real_dispatch_after_f; extern dispatch_barrier_async_f_f real_dispatch_barrier_async_f; extern dispatch_group_async_f_f real_dispatch_group_async_f; extern pthread_workqueue_additem_np_f real_pthread_workqueue_additem_np; +extern CFStringCreateCopy_f real_CFStringCreateCopy; void GetPcSpBp(void *context, uintptr_t *pc, uintptr_t *sp, uintptr_t *bp) { ucontext_t *ucontext = (ucontext_t*)context; @@ -514,4 +515,45 @@ int WRAP(pthread_workqueue_additem_np)(pthread_workqueue_t workq, itemhandlep, gencountp); } +// CF_RC_BITS, the layout of CFRuntimeBase and __CFStrIsConstant are internal +// and subject to change in further CoreFoundation versions. Apple does not +// guarantee any binary compatibility from release to release. + +// See http://opensource.apple.com/source/CF/CF-635.15/CFInternal.h +#if defined(__BIG_ENDIAN__) +#define CF_RC_BITS 0 +#endif + +#if defined(__LITTLE_ENDIAN__) +#define CF_RC_BITS 3 +#endif + +// See http://opensource.apple.com/source/CF/CF-635.15/CFRuntime.h +typedef struct __CFRuntimeBase { + uintptr_t _cfisa; + uint8_t _cfinfo[4]; +#if __LP64__ + uint32_t _rc; +#endif +} CFRuntimeBase; + +// See http://opensource.apple.com/source/CF/CF-635.15/CFString.c +int __CFStrIsConstant(CFStringRef str) { + CFRuntimeBase *base = (CFRuntimeBase*)str; +#if __LP64__ + return base->_rc == 0; +#else + return (base->_cfinfo[CF_RC_BITS]) == 0; +#endif +} + +extern "C" +CFStringRef WRAP(CFStringCreateCopy)(CFAllocatorRef alloc, CFStringRef str) { + if (__CFStrIsConstant(str)) { + return str; + } else { + return real_CFStringCreateCopy(alloc, str); + } +} + #endif // __APPLE__ diff --git a/compiler-rt/lib/asan/asan_mac.h b/compiler-rt/lib/asan/asan_mac.h index c8a9c08e54a..bb39f8206b4 100644 --- a/compiler-rt/lib/asan/asan_mac.h +++ b/compiler-rt/lib/asan/asan_mac.h @@ -22,6 +22,7 @@ #include <dispatch/dispatch.h> #include <mach/mach_error.h> #include <setjmp.h> +#include <CoreFoundation/CFString.h> typedef void* pthread_workqueue_t; typedef void* pthread_workitem_handle_t; @@ -44,7 +45,8 @@ typedef void (*dispatch_group_async_f_f)(dispatch_group_t group, typedef int (*pthread_workqueue_additem_np_f)(pthread_workqueue_t workq, void *(*workitem_func)(void *), void * workitem_arg, pthread_workitem_handle_t * itemhandlep, unsigned int *gencountp); - +typedef CFStringRef (*CFStringCreateCopy_f)(CFAllocatorRef alloc, + CFStringRef str); // A wrapper for the ObjC blocks used to support libdispatch. typedef struct { @@ -90,6 +92,7 @@ void WRAP(dispatch_group_async_f)(dispatch_group_t group, int WRAP(pthread_workqueue_additem_np)(pthread_workqueue_t workq, void *(*workitem_func)(void *), void * workitem_arg, pthread_workitem_handle_t * itemhandlep, unsigned int *gencountp); +CFStringRef WRAP(CFStringCreateCopy)(CFAllocatorRef alloc, CFStringRef str); } #endif // ASAN_MAC_H diff --git a/compiler-rt/lib/asan/tests/asan_test.cc b/compiler-rt/lib/asan/tests/asan_test.cc index d8657bf0cf3..82128f2e2dc 100644 --- a/compiler-rt/lib/asan/tests/asan_test.cc +++ b/compiler-rt/lib/asan/tests/asan_test.cc @@ -1898,7 +1898,7 @@ TEST(AddressSanitizerMac, DISABLED_TSDWorkqueueTest) { } // Test that CFStringCreateCopy does not copy constant strings. -TEST(AddressSanitizerMac, DISABLED_CFStringCreateCopy) { +TEST(AddressSanitizerMac, CFStringCreateCopy) { CFStringRef str = CFSTR("Hello world!\n"); CFStringRef str2 = CFStringCreateCopy(0, str); EXPECT_EQ(str, str2); |