Wrap CFStringCreateCopy to prevent copying constant CF strings.
This should fix http://code.google.com/p/address-sanitizer/issues/detail?id=10 llvm-svn: 148696
This commit is contained in:
parent
f9392011c8
commit
046ecc06be
|
|
@ -94,6 +94,7 @@ dispatch_after_f_f real_dispatch_after_f;
|
||||||
dispatch_barrier_async_f_f real_dispatch_barrier_async_f;
|
dispatch_barrier_async_f_f real_dispatch_barrier_async_f;
|
||||||
dispatch_group_async_f_f real_dispatch_group_async_f;
|
dispatch_group_async_f_f real_dispatch_group_async_f;
|
||||||
pthread_workqueue_additem_np_f real_pthread_workqueue_additem_np;
|
pthread_workqueue_additem_np_f real_pthread_workqueue_additem_np;
|
||||||
|
CFStringCreateCopy_f real_CFStringCreateCopy;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sigaction_f real_sigaction;
|
sigaction_f real_sigaction;
|
||||||
|
|
@ -648,6 +649,14 @@ void InitializeAsanInterceptors() {
|
||||||
if (FLAG_v >= 2) {
|
if (FLAG_v >= 2) {
|
||||||
INTERCEPT_FUNCTION(pthread_workqueue_additem_np);
|
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
|
#else
|
||||||
// On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
|
// On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
|
||||||
// there.
|
// there.
|
||||||
|
|
|
||||||
|
|
@ -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_barrier_async_f_f real_dispatch_barrier_async_f;
|
||||||
extern dispatch_group_async_f_f real_dispatch_group_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 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) {
|
void GetPcSpBp(void *context, uintptr_t *pc, uintptr_t *sp, uintptr_t *bp) {
|
||||||
ucontext_t *ucontext = (ucontext_t*)context;
|
ucontext_t *ucontext = (ucontext_t*)context;
|
||||||
|
|
@ -514,4 +515,45 @@ int WRAP(pthread_workqueue_additem_np)(pthread_workqueue_t workq,
|
||||||
itemhandlep, gencountp);
|
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__
|
#endif // __APPLE__
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include <dispatch/dispatch.h>
|
#include <dispatch/dispatch.h>
|
||||||
#include <mach/mach_error.h>
|
#include <mach/mach_error.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
#include <CoreFoundation/CFString.h>
|
||||||
|
|
||||||
typedef void* pthread_workqueue_t;
|
typedef void* pthread_workqueue_t;
|
||||||
typedef void* pthread_workitem_handle_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,
|
typedef int (*pthread_workqueue_additem_np_f)(pthread_workqueue_t workq,
|
||||||
void *(*workitem_func)(void *), void * workitem_arg,
|
void *(*workitem_func)(void *), void * workitem_arg,
|
||||||
pthread_workitem_handle_t * itemhandlep, unsigned int *gencountp);
|
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.
|
// A wrapper for the ObjC blocks used to support libdispatch.
|
||||||
typedef struct {
|
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,
|
int WRAP(pthread_workqueue_additem_np)(pthread_workqueue_t workq,
|
||||||
void *(*workitem_func)(void *), void * workitem_arg,
|
void *(*workitem_func)(void *), void * workitem_arg,
|
||||||
pthread_workitem_handle_t * itemhandlep, unsigned int *gencountp);
|
pthread_workitem_handle_t * itemhandlep, unsigned int *gencountp);
|
||||||
|
CFStringRef WRAP(CFStringCreateCopy)(CFAllocatorRef alloc, CFStringRef str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ASAN_MAC_H
|
#endif // ASAN_MAC_H
|
||||||
|
|
|
||||||
|
|
@ -1898,7 +1898,7 @@ TEST(AddressSanitizerMac, DISABLED_TSDWorkqueueTest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that CFStringCreateCopy does not copy constant strings.
|
// Test that CFStringCreateCopy does not copy constant strings.
|
||||||
TEST(AddressSanitizerMac, DISABLED_CFStringCreateCopy) {
|
TEST(AddressSanitizerMac, CFStringCreateCopy) {
|
||||||
CFStringRef str = CFSTR("Hello world!\n");
|
CFStringRef str = CFSTR("Hello world!\n");
|
||||||
CFStringRef str2 = CFStringCreateCopy(0, str);
|
CFStringRef str2 = CFStringCreateCopy(0, str);
|
||||||
EXPECT_EQ(str, str2);
|
EXPECT_EQ(str, str2);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue