re PR sanitizer/64632 (runtime error: member call on address 0x0000004318a8 which...
authorJakub Jelinek <jakub@redhat.com>
Tue, 20 Jan 2015 20:39:52 +0000 (21:39 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 20 Jan 2015 20:39:52 +0000 (21:39 +0100)
PR sanitizer/64632
* ubsan/ubsan_type_hash.cc: Cherry pick upstream r224972.

* g++.dg/ubsan/pr64632.C: New test.

From-SVN: r219912

gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ubsan/pr64632.C [new file with mode: 0644]
libsanitizer/ChangeLog
libsanitizer/ubsan/ubsan_type_hash.cc

index 598843154b655ef4cc5da66cf56cccb2946bb26a..ee46288d3736eaec9424b750dbfaf812b1c6e1a6 100644 (file)
@@ -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 (file)
index 0000000..0d2a7aa
--- /dev/null
@@ -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 ();
+}
index 3de7396f854b9256ac637419b871d93a919ea0c8..cb0f98c7e834d0819fff255a03793a2ef9ad7e35 100644 (file)
@@ -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
index 8758f6c84c5c09d8bb13b680492c28344648a750..d01009426db0632e6427ac24dbcd96bd7bdfa851 100644 (file)
@@ -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>");
 }