This is an archive of the discontinued LLVM Phabricator instance.

[tsan] Fix crash in objc_sync_enter/objc_sync_exit when using an Obj-C tagged pointer
ClosedPublic

Authored by kubamracek on Jul 23 2018, 4:48 PM.

Details

Summary

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.

Diff Detail

Repository
rL LLVM

Event Timeline

kubamracek created this revision.Jul 23 2018, 4:48 PM
Herald added subscribers: Restricted Project, jfb. · View Herald TranscriptJul 23 2018, 4:48 PM
lib/tsan/rtl/tsan_interceptors_mac.cc
297 ↗(On Diff #156925)

can we have a short docstring for both functions? Also, isTaggedObjCPointer?

299 ↗(On Diff #156925)

return ((uptr)obj & kPossibleTaggedBits) != 0 ?

303 ↗(On Diff #156925)

what's the point of taking in the argument then?

312 ↗(On Diff #156925)

can we extract this line into a function with a name explaining it's semantics?

kubamracek added inline comments.Jul 23 2018, 5:08 PM
lib/tsan/rtl/tsan_interceptors_mac.cc
303 ↗(On Diff #156925)

The point is that, ideally, the function would return a different sync address for different pointers. But for now, the implementation trivially returns the same address for all, which can cause false negatives.

kubamracek added inline comments.
lib/tsan/rtl/tsan_interceptors_mac.cc
297 ↗(On Diff #156925)

Also, isTaggedObjCPointer?

In (almost) all of TSan, private functions starts with an uppercase letter. Let's not try to change style with this patch.

lib/tsan/rtl/tsan_interceptors_mac.cc
299 ↗(On Diff #156932)

also all the helper functions should be static

george.karpenkov accepted this revision.Jul 23 2018, 5:20 PM
This revision is now accepted and ready to land.Jul 23 2018, 5:20 PM
dvyukov accepted this revision.Jul 24 2018, 12:49 AM
delcypher accepted this revision.Jul 24 2018, 8:26 AM

Other than minor suggestions the basic idea seems okay for now.

lib/tsan/rtl/tsan_interceptors_mac.cc
299 ↗(On Diff #156937)

Perhaps the name should be IsTaggedObjCPointer?

308 ↗(On Diff #156937)

There probably should be a TODO(kubamracek) or FIXME in here.

Do we even want to do Acquire() and Release() for tagged pointers? Even if we had a perfect implementation of SyncAddressForTaggedPointer() that still seems wrong because we could have two independent instances of a tagged pointer
(e.g. create two separate NSString with same value) and those shouldn't really be considered as the same object, but they would
be considered the same because their tagged pointer value is the same.

kubamracek added inline comments.Jul 24 2018, 9:00 AM
lib/tsan/rtl/tsan_interceptors_mac.cc
308 ↗(On Diff #156937)

Yes, the entire idea of using value types (strings, integeres, timestamps) as synchronization objects is weird and most likely not what you intended anyway. Therefore this patch is really just to avoid crashing and to mirror what libobjc is actually doing when using @synchronize on a tagged pointer (it does actually establish synchronization if the pointer bits are exactly the same).

This revision was automatically updated to reflect the committed changes.
This revision was automatically updated to reflect the committed changes.

Thanks for the fast review!