summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-20 20:39:52 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2015-01-20 20:39:52 +0000
commit0f9736fac5fd53b99c7e45c434607433ba8d80cd (patch)
tree62486ce633b46c7bf8945dc5e7352f4f545b2b55
parent69d99fc497f9f846a8b829525eae5e7d53763238 (diff)
downloadgcc-0f9736fac5fd53b99c7e45c434607433ba8d80cd.tar.gz
PR sanitizer/64632
* ubsan/ubsan_type_hash.cc: Cherry pick upstream r224972. * g++.dg/ubsan/pr64632.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219912 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/ubsan/pr64632.C23
-rw-r--r--libsanitizer/ChangeLog5
-rw-r--r--libsanitizer/ubsan/ubsan_type_hash.cc47
4 files changed, 52 insertions, 26 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 598843154b6..ee46288d373 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2015-01-20 Jakub Jelinek <jakub@redhat.com>
+ PR sanitizer/64632
+ * g++.dg/ubsan/pr64632.C: New test.
+
PR debug/64663
* gcc.dg/pr64663.c: New test.
diff --git a/gcc/testsuite/g++.dg/ubsan/pr64632.C b/gcc/testsuite/g++.dg/ubsan/pr64632.C
new file mode 100644
index 00000000000..0d2a7aa9aef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/pr64632.C
@@ -0,0 +1,23 @@
+// PR sanitizer/64632
+// { dg-do run }
+// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" }
+
+struct S
+{
+ S () : a(0) {}
+ int a;
+ int f () { return a; }
+ virtual int v () { return 0; }
+};
+
+struct X : virtual S
+{
+ int v () { return 2; }
+};
+
+int
+main ()
+{
+ X x;
+ return x.f ();
+}
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index 3de7396f854..cb0f98c7e83 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,8 @@
+2015-01-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/64632
+ * ubsan/ubsan_type_hash.cc: Cherry pick upstream r224972.
+
2015-01-19 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/64435
diff --git a/libsanitizer/ubsan/ubsan_type_hash.cc b/libsanitizer/ubsan/ubsan_type_hash.cc
index 8758f6c84c5..d01009426db 100644
--- a/libsanitizer/ubsan/ubsan_type_hash.cc
+++ b/libsanitizer/ubsan/ubsan_type_hash.cc
@@ -113,8 +113,7 @@ __ubsan::__ubsan_vptr_type_cache[__ubsan::VptrTypeCacheSize];
/// \brief Determine whether \p Derived has a \p Base base class subobject at
/// offset \p Offset.
-static bool isDerivedFromAtOffset(sptr Object,
- const abi::__class_type_info *Derived,
+static bool isDerivedFromAtOffset(const abi::__class_type_info *Derived,
const abi::__class_type_info *Base,
sptr Offset) {
if (Derived->__type_name == Base->__type_name)
@@ -122,7 +121,7 @@ static bool isDerivedFromAtOffset(sptr Object,
if (const abi::__si_class_type_info *SI =
dynamic_cast<const abi::__si_class_type_info*>(Derived))
- return isDerivedFromAtOffset(Object, SI->__base_type, Base, Offset);
+ return isDerivedFromAtOffset(SI->__base_type, Base, Offset);
const abi::__vmi_class_type_info *VTI =
dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
@@ -137,13 +136,13 @@ static bool isDerivedFromAtOffset(sptr Object,
sptr OffsetHere = VTI->base_info[base].__offset_flags >>
abi::__base_class_type_info::__offset_shift;
if (VTI->base_info[base].__offset_flags &
- abi::__base_class_type_info::__virtual_mask) {
- sptr VTable = *reinterpret_cast<const sptr *>(Object);
- OffsetHere = *reinterpret_cast<const sptr *>(VTable + OffsetHere);
- }
- if (isDerivedFromAtOffset(Object + OffsetHere,
- VTI->base_info[base].__base_type, Base,
- Offset - OffsetHere))
+ abi::__base_class_type_info::__virtual_mask)
+ // For now, just punt on virtual bases and say 'yes'.
+ // FIXME: OffsetHere is the offset in the vtable of the virtual base
+ // offset. Read the vbase offset out of the vtable and use it.
+ return true;
+ if (isDerivedFromAtOffset(VTI->base_info[base].__base_type,
+ Base, Offset - OffsetHere))
return true;
}
@@ -152,15 +151,14 @@ static bool isDerivedFromAtOffset(sptr Object,
/// \brief Find the derived-most dynamic base class of \p Derived at offset
/// \p Offset.
-static const abi::__class_type_info *
-findBaseAtOffset(sptr Object, const abi::__class_type_info *Derived,
- sptr Offset) {
+static const abi::__class_type_info *findBaseAtOffset(
+ const abi::__class_type_info *Derived, sptr Offset) {
if (!Offset)
return Derived;
if (const abi::__si_class_type_info *SI =
dynamic_cast<const abi::__si_class_type_info*>(Derived))
- return findBaseAtOffset(Object, SI->__base_type, Offset);
+ return findBaseAtOffset(SI->__base_type, Offset);
const abi::__vmi_class_type_info *VTI =
dynamic_cast<const abi::__vmi_class_type_info*>(Derived);
@@ -172,13 +170,12 @@ findBaseAtOffset(sptr Object, const abi::__class_type_info *Derived,
sptr OffsetHere = VTI->base_info[base].__offset_flags >>
abi::__base_class_type_info::__offset_shift;
if (VTI->base_info[base].__offset_flags &
- abi::__base_class_type_info::__virtual_mask) {
- sptr VTable = *reinterpret_cast<const sptr *>(Object);
- OffsetHere = *reinterpret_cast<const sptr *>(VTable + OffsetHere);
- }
- if (const abi::__class_type_info *Base = findBaseAtOffset(
- Object + OffsetHere, VTI->base_info[base].__base_type,
- Offset - OffsetHere))
+ abi::__base_class_type_info::__virtual_mask)
+ // FIXME: Can't handle virtual bases yet.
+ continue;
+ if (const abi::__class_type_info *Base =
+ findBaseAtOffset(VTI->base_info[base].__base_type,
+ Offset - OffsetHere))
return Base;
}
@@ -230,8 +227,7 @@ bool __ubsan::checkDynamicType(void *Object, void *Type, HashValue Hash) {
return false;
abi::__class_type_info *Base = (abi::__class_type_info*)Type;
- if (!isDerivedFromAtOffset(reinterpret_cast<sptr>(Object), Derived, Base,
- -Vtable->Offset))
+ if (!isDerivedFromAtOffset(Derived, Base, -Vtable->Offset))
return false;
// Success. Cache this result.
@@ -245,9 +241,8 @@ __ubsan::DynamicTypeInfo __ubsan::getDynamicTypeInfo(void *Object) {
if (!Vtable)
return DynamicTypeInfo(0, 0, 0);
const abi::__class_type_info *ObjectType = findBaseAtOffset(
- reinterpret_cast<sptr>(Object),
- static_cast<const abi::__class_type_info *>(Vtable->TypeInfo),
- -Vtable->Offset);
+ static_cast<const abi::__class_type_info*>(Vtable->TypeInfo),
+ -Vtable->Offset);
return DynamicTypeInfo(Vtable->TypeInfo->__type_name, -Vtable->Offset,
ObjectType ? ObjectType->__type_name : "<unknown>");
}