1 // RUN: %clangxx_cfi -o %t1 %s 2 // RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s 3 4 // RUN: %clangxx_cfi -DB32 -o %t2 %s 5 // RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s 6 7 // RUN: %clangxx_cfi -DB64 -o %t3 %s 8 // RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s 9 10 // RUN: %clangxx_cfi -DBM -o %t4 %s 11 // RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s 12 13 // RUN: %clangxx_cfi -O1 -o %t5 %s 14 // RUN: %expect_crash %t5 2>&1 | FileCheck --check-prefix=CFI %s 15 16 // RUN: %clangxx_cfi -O1 -DB32 -o %t6 %s 17 // RUN: %expect_crash %t6 2>&1 | FileCheck --check-prefix=CFI %s 18 19 // RUN: %clangxx_cfi -O1 -DB64 -o %t7 %s 20 // RUN: %expect_crash %t7 2>&1 | FileCheck --check-prefix=CFI %s 21 22 // RUN: %clangxx_cfi -O1 -DBM -o %t8 %s 23 // RUN: %expect_crash %t8 2>&1 | FileCheck --check-prefix=CFI %s 24 25 // RUN: %clangxx_cfi -O2 -o %t9 %s 26 // RUN: %expect_crash %t9 2>&1 | FileCheck --check-prefix=CFI %s 27 28 // RUN: %clangxx_cfi -O2 -DB32 -o %t10 %s 29 // RUN: %expect_crash %t10 2>&1 | FileCheck --check-prefix=CFI %s 30 31 // RUN: %clangxx_cfi -O2 -DB64 -o %t11 %s 32 // RUN: %expect_crash %t11 2>&1 | FileCheck --check-prefix=CFI %s 33 34 // RUN: %clangxx_cfi -O2 -DBM -o %t12 %s 35 // RUN: %expect_crash %t12 2>&1 | FileCheck --check-prefix=CFI %s 36 37 // RUN: %clangxx_cfi -O3 -o %t13 %s 38 // RUN: %expect_crash %t13 2>&1 | FileCheck --check-prefix=CFI %s 39 40 // RUN: %clangxx_cfi -O3 -DB32 -o %t14 %s 41 // RUN: %expect_crash %t14 2>&1 | FileCheck --check-prefix=CFI %s 42 43 // RUN: %clangxx_cfi -O3 -DB64 -o %t15 %s 44 // RUN: %expect_crash %t15 2>&1 | FileCheck --check-prefix=CFI %s 45 46 // RUN: %clangxx_cfi -O3 -DBM -o %t16 %s 47 // RUN: %expect_crash %t16 2>&1 | FileCheck --check-prefix=CFI %s 48 49 // RUN: %clangxx_cfi_diag -o %t17 %s 50 // RUN: %t17 2>&1 | FileCheck --check-prefix=CFI-DIAG %s 51 52 // RUN: %clangxx -o %t18 %s 53 // RUN: %t18 2>&1 | FileCheck --check-prefix=NCFI %s 54 55 // Tests that the CFI mechanism crashes the program when making a 56 // base-to-derived cast from a destructor of the base class, 57 // where both types have virtual tables. 58 59 // REQUIRES: cxxabi 60 61 #include <stdio.h> 62 #include "utils.h" 63 64 template<typename T> 65 class A { 66 public: 67 T* context() { return static_cast<T*>(this); } 68 69 virtual ~A() { 70 break_optimization(context()); 71 } 72 }; 73 74 class B : public A<B> { 75 public: 76 virtual ~B() { } 77 }; 78 79 int main() { 80 // CFI: 1 81 // NCFI: 1 82 fprintf(stderr, "1\n"); 83 84 // CFI-DIAG: runtime error: control flow integrity check for type 'B' failed during base-to-derived cast 85 // CFI-DIAG-NEXT: note: vtable is of type '{{(class )?}}A<{{(class )?}}B>' 86 B* b = new B; 87 break_optimization(b); 88 delete b; // UB here 89 90 // CFI-NOT: {{^2$}} 91 // NCFI: {{^2$}} 92 fprintf(stderr, "2\n"); 93 } 94