ubsan: Add checking for invalid downcasts. Per [expr.static.cast]p2 and p11,
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 13 Feb 2013 21:18:23 +0000 (21:18 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 13 Feb 2013 21:18:23 +0000 (21:18 +0000)
base-to-derived casts have undefined behavior if the object is not actually an
instance of the derived type. Runtime library part.

llvm-svn: 175079

compiler-rt/lib/ubsan/lit_tests/TypeCheck/vptr.cpp
compiler-rt/lib/ubsan/ubsan_handlers.cc
compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc

index 574a7be..109e7a8 100644 (file)
@@ -1,11 +1,13 @@
 // RUN: %clang -ccc-cxx -fsanitize=vptr %s -O3 -o %t
-// RUN: %t rT && %t mT && %t fT
-// RUN: %t rU && %t mU && %t fU
+// RUN: %t rT && %t mT && %t fT && %t cT
+// RUN: %t rU && %t mU && %t fU && %t cU
 // RUN: %t rS && %t rV && %t oV
 // RUN: %t mS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --strict-whitespace
 // RUN: %t fS 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace
+// RUN: %t cS 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --strict-whitespace
 // RUN: %t mV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMBER --strict-whitespace
 // RUN: %t fV 2>&1 | FileCheck %s --check-prefix=CHECK-MEMFUN --strict-whitespace
+// RUN: %t cV 2>&1 | FileCheck %s --check-prefix=CHECK-DOWNCAST --strict-whitespace
 // RUN: %t oU 2>&1 | FileCheck %s --check-prefix=CHECK-OFFSET --strict-whitespace
 // RUN: %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --strict-whitespace
 
@@ -102,5 +104,14 @@ int main(int, char **argv) {
     // CHECK-OFFSET-NEXT: {{^              \^                        (                         ~~~~~~~~~~~~)~~~~~~~~~~~ *$}}
     // CHECK-OFFSET-NEXT: {{^                                       (                         )?vptr for}} 'T' base class of [[DYN_TYPE]]
     return reinterpret_cast<U*>(p)->v() - 2;
+
+  case 'c':
+    // CHECK-DOWNCAST: vptr.cpp:[[@LINE+5]]:5: runtime error: downcast of address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
+    // CHECK-DOWNCAST-NEXT: [[PTR]]: note: object is of type [[DYN_TYPE:'S'|'U']]
+    // CHECK-DOWNCAST-NEXT: {{^ .. .. .. ..  .. .. .. .. .. .. .. ..  }}
+    // CHECK-DOWNCAST-NEXT: {{^              \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
+    // CHECK-DOWNCAST-NEXT: {{^              vptr for}} [[DYN_TYPE]]
+    static_cast<T*>(reinterpret_cast<S*>(p));
+    return 0;
   }
 }
index 1b02aa0..33e044d 100644 (file)
@@ -22,7 +22,7 @@ using namespace __ubsan;
 namespace __ubsan {
   const char *TypeCheckKinds[] = {
     "load of", "store to", "reference binding to", "member access within",
-    "member call on", "constructor call on"
+    "member call on", "constructor call on", "downcast of", "downcast of"
   };
 }
 
index dcc1f60..b6cddef 100644 (file)
@@ -42,7 +42,6 @@ static void HandleDynamicTypeCacheMiss(
     << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
 
   // If possible, say what type it actually points to.
-  // FIXME: Demangle the type names.
   DynamicTypeInfo DTI = getDynamicTypeInfo((void*)Pointer);
   if (!DTI.isValid())
     Diag(Pointer, DL_Note, "object has invalid vptr")