Skip to content

Commit b7692bc

Browse files
committed
[UBSan] Fix isDerivedFromAtOffset on iOS ARM64
Summary: iOS on ARM64 doesn't unique RTTI. Ref: clang's iOS64CXXABI::shouldRTTIBeUnique() Due to this, pointer-equality will not necessarily work in this architecture, across dylib boundaries. dynamic_cast<>() will (as expected) still work, since Apple ships with one prepared for this, but we can't rely on the type names being pointer-equal. I've limited the expensive strcmp check to the specific architecture which needs it. Example which triggers this bug: lib.h: struct X { virtual ~X() {} }; X *libCall(); lib.mm: X *libCall() { return new X; } prog.mm: int main() { X *px = libCall(); delete px; } Expected output: Nothing Actual output: <unknown>: runtime error: member call on address 0x00017001ef50 which does not point to an object of type 'X' 0x00017001ef50: note: object is of type 'X' 00 00 00 00 60 00 0f 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ vptr for ‘X’ Reviewers: kubabrecka, samsonov, eugenis, rsmith Subscribers: aemerson, llvm-commits, rengolin Differential Revision: http://reviews.llvm.org/D11502 llvm-svn: 262147
1 parent d3a7467 commit b7692bc

File tree

6 files changed

+31
-1
lines changed

6 files changed

+31
-1
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_platform.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,10 @@
162162
# define MSC_PREREQ(version) 0
163163
#endif
164164

165+
#if defined(__arm64__) && SANITIZER_IOS
166+
# define SANITIZER_NON_UNIQUE_TYPEINFO 1
167+
#else
168+
# define SANITIZER_NON_UNIQUE_TYPEINFO 0
169+
#endif
170+
165171
#endif // SANITIZER_PLATFORM_H

compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ static __ubsan::HashValue *getTypeCacheHashTableBucket(__ubsan::HashValue V) {
115115
static bool isDerivedFromAtOffset(const abi::__class_type_info *Derived,
116116
const abi::__class_type_info *Base,
117117
sptr Offset) {
118-
if (Derived->__type_name == Base->__type_name)
118+
if (Derived->__type_name == Base->__type_name ||
119+
(SANITIZER_NON_UNIQUE_TYPEINFO &&
120+
!internal_strcmp(Derived->__type_name, Base->__type_name)))
119121
return Offset == 0;
120122

121123
if (const abi::__si_class_type_info *SI =
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Sources in this directory are helper files for tests which test functionality
2+
# involving multiple translation units.
3+
config.suffixes = []
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "vptr-non-unique-typeinfo-lib.h"
2+
3+
X *libCall() {
4+
return new X;
5+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
struct X {
2+
virtual ~X() {}
3+
};
4+
X *libCall();
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -I%p/Helpers %p/Helpers/vptr-non-unique-typeinfo-lib.cpp -fPIC -shared -o %t-lib.so
2+
// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -I%p/Helpers -g %s -O3 -o %t %t-lib.so
3+
// RUN: %run %t
4+
5+
#include "vptr-non-unique-typeinfo-lib.h"
6+
7+
int main() {
8+
X *px = libCall();
9+
delete px;
10+
}

0 commit comments

Comments
 (0)