summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/asan/asan_interceptors.cc9
-rw-r--r--compiler-rt/lib/asan/asan_mac.cc42
-rw-r--r--compiler-rt/lib/asan/asan_mac.h5
-rw-r--r--compiler-rt/lib/asan/tests/asan_test.cc2
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);
OpenPOWER on IntegriCloud