diff options
author | Kuba Mracek <mracek@apple.com> | 2018-07-24 16:19:06 +0000 |
---|---|---|
committer | Kuba Mracek <mracek@apple.com> | 2018-07-24 16:19:06 +0000 |
commit | 3ac94fe6137e5d5123b064b03084ea7a0bd0f5ff (patch) | |
tree | 928d2f9702196b4131370ed35a57925ebdfdd23e /lib | |
parent | 37bd9aa510166186a9bba5cf13d717d6b097c95e (diff) |
[tsan] Fix crash in objc_sync_enter/objc_sync_exit when using an Obj-C tagged pointer
Objective-C tagged pointers (either bottom-most or top-most bit is 1) are valid Obj-C objects but are not valid pointers. Make sure we don't crash on them when used in objc_sync_enter/objc_sync_exit. Instead, let's synchronize on a global object.
Differential Revision: https://reviews.llvm.org/D49707
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@337837 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/tsan/rtl/tsan_interceptors_mac.cc | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/lib/tsan/rtl/tsan_interceptors_mac.cc b/lib/tsan/rtl/tsan_interceptors_mac.cc index 1c4aa02a0..b58e6b707 100644 --- a/lib/tsan/rtl/tsan_interceptors_mac.cc +++ b/lib/tsan/rtl/tsan_interceptors_mac.cc @@ -294,16 +294,40 @@ TSAN_INTERCEPTOR(void, xpc_connection_cancel, xpc_connection_t connection) { #endif // #if defined(__has_include) && __has_include(<xpc/xpc.h>) +// Is the Obj-C object a tagged pointer (i.e. isn't really a valid pointer and +// contains data in the pointers bits instead)? +static bool IsTaggedObjCPointer(void *obj) { + const uptr kPossibleTaggedBits = 0x8000000000000001ull; + return ((uptr)obj & kPossibleTaggedBits) != 0; +} + +// Return an address on which we can synchronize (Acquire and Release) for a +// Obj-C tagged pointer (which is not a valid pointer). Ideally should be a +// derived address from 'obj', but for now just return the same global address. +// TODO(kubamracek): Return different address for different pointers. +static uptr SyncAddressForTaggedPointer(void *obj) { + (void)obj; + static u64 addr; + return (uptr)&addr; +} + +// Address on which we can synchronize for an Objective-C object. Supports +// tagged pointers. +static uptr SyncAddressForObjCObject(void *obj) { + if (IsTaggedObjCPointer(obj)) return SyncAddressForTaggedPointer(obj); + return (uptr)obj; +} + TSAN_INTERCEPTOR(int, objc_sync_enter, void *obj) { SCOPED_TSAN_INTERCEPTOR(objc_sync_enter, obj); int result = REAL(objc_sync_enter)(obj); - if (obj) Acquire(thr, pc, (uptr)obj); + if (obj) Acquire(thr, pc, SyncAddressForObjCObject(obj)); return result; } TSAN_INTERCEPTOR(int, objc_sync_exit, void *obj) { SCOPED_TSAN_INTERCEPTOR(objc_sync_enter, obj); - if (obj) Release(thr, pc, (uptr)obj); + if (obj) Release(thr, pc, SyncAddressForObjCObject(obj)); return REAL(objc_sync_exit)(obj); } |