1 // RUN: %clangxx_cfi -o %t1 %s 2 // RUN: %expect_crash %t1 a 2>&1 | FileCheck --check-prefix=FAIL %s 3 // RUN: %expect_crash %t1 b 2>&1 | FileCheck --check-prefix=FAIL %s 4 // RUN: %expect_crash %t1 c 2>&1 | FileCheck --check-prefix=FAIL %s 5 // RUN: %t1 d 2>&1 | FileCheck --check-prefix=PASS %s 6 // RUN: %t1 e 2>&1 | FileCheck --check-prefix=PASS %s 7 // RUN: %t1 f 2>&1 | FileCheck --check-prefix=PASS %s 8 // RUN: %expect_crash %t1 g 2>&1 | FileCheck --check-prefix=FAIL %s 9 // RUN: %t1 h 2>&1 | FileCheck --check-prefix=PASS %s 10 11 // RUN: %clangxx_cfi -DB32 -o %t2 %s 12 // RUN: %expect_crash %t2 a 2>&1 | FileCheck --check-prefix=FAIL %s 13 // RUN: %expect_crash %t2 b 2>&1 | FileCheck --check-prefix=FAIL %s 14 // RUN: %expect_crash %t2 c 2>&1 | FileCheck --check-prefix=FAIL %s 15 // RUN: %t2 d 2>&1 | FileCheck --check-prefix=PASS %s 16 // RUN: %t2 e 2>&1 | FileCheck --check-prefix=PASS %s 17 // RUN: %t2 f 2>&1 | FileCheck --check-prefix=PASS %s 18 // RUN: %expect_crash %t2 g 2>&1 | FileCheck --check-prefix=FAIL %s 19 // RUN: %t2 h 2>&1 | FileCheck --check-prefix=PASS %s 20 21 // RUN: %clangxx_cfi -DB64 -o %t3 %s 22 // RUN: %expect_crash %t3 a 2>&1 | FileCheck --check-prefix=FAIL %s 23 // RUN: %expect_crash %t3 b 2>&1 | FileCheck --check-prefix=FAIL %s 24 // RUN: %expect_crash %t3 c 2>&1 | FileCheck --check-prefix=FAIL %s 25 // RUN: %t3 d 2>&1 | FileCheck --check-prefix=PASS %s 26 // RUN: %t3 e 2>&1 | FileCheck --check-prefix=PASS %s 27 // RUN: %t3 f 2>&1 | FileCheck --check-prefix=PASS %s 28 // RUN: %expect_crash %t3 g 2>&1 | FileCheck --check-prefix=FAIL %s 29 // RUN: %t3 h 2>&1 | FileCheck --check-prefix=PASS %s 30 31 // RUN: %clangxx_cfi -DBM -o %t4 %s 32 // RUN: %expect_crash %t4 a 2>&1 | FileCheck --check-prefix=FAIL %s 33 // RUN: %expect_crash %t4 b 2>&1 | FileCheck --check-prefix=FAIL %s 34 // RUN: %expect_crash %t4 c 2>&1 | FileCheck --check-prefix=FAIL %s 35 // RUN: %t4 d 2>&1 | FileCheck --check-prefix=PASS %s 36 // RUN: %t4 e 2>&1 | FileCheck --check-prefix=PASS %s 37 // RUN: %t4 f 2>&1 | FileCheck --check-prefix=PASS %s 38 // RUN: %expect_crash %t4 g 2>&1 | FileCheck --check-prefix=FAIL %s 39 // RUN: %t4 h 2>&1 | FileCheck --check-prefix=PASS %s 40 41 // RUN: %clangxx_cfi -fsanitize=cfi-cast-strict -o %t5 %s 42 // RUN: %expect_crash %t5 a 2>&1 | FileCheck --check-prefix=FAIL %s 43 // RUN: %expect_crash %t5 b 2>&1 | FileCheck --check-prefix=FAIL %s 44 // RUN: %expect_crash %t5 c 2>&1 | FileCheck --check-prefix=FAIL %s 45 // RUN: %expect_crash %t5 d 2>&1 | FileCheck --check-prefix=FAIL %s 46 // RUN: %expect_crash %t5 e 2>&1 | FileCheck --check-prefix=FAIL %s 47 // RUN: %expect_crash %t5 f 2>&1 | FileCheck --check-prefix=FAIL %s 48 // RUN: %expect_crash %t5 g 2>&1 | FileCheck --check-prefix=FAIL %s 49 // RUN: %expect_crash %t5 h 2>&1 | FileCheck --check-prefix=FAIL %s 50 51 // RUN: %clangxx -o %t6 %s 52 // RUN: %t6 a 2>&1 | FileCheck --check-prefix=PASS %s 53 // RUN: %t6 b 2>&1 | FileCheck --check-prefix=PASS %s 54 // RUN: %t6 c 2>&1 | FileCheck --check-prefix=PASS %s 55 // RUN: %t6 d 2>&1 | FileCheck --check-prefix=PASS %s 56 // RUN: %t6 e 2>&1 | FileCheck --check-prefix=PASS %s 57 // RUN: %t6 f 2>&1 | FileCheck --check-prefix=PASS %s 58 // RUN: %t6 g 2>&1 | FileCheck --check-prefix=PASS %s 59 // RUN: %t6 h 2>&1 | FileCheck --check-prefix=PASS %s 60 61 // RUN: %clangxx_cfi_diag -o %t7 %s 62 // RUN: %t7 a 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s 63 // RUN: %t7 b 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s 64 // RUN: %t7 c 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s 65 // RUN: %t7 g 2>&1 | FileCheck --check-prefix=CFI-DIAG-U %s 66 67 // Tests that the CFI enforcement detects bad casts. 68 69 // REQUIRES: cxxabi 70 71 #include <stdio.h> 72 #include "utils.h" 73 74 struct A { 75 virtual void f(); 76 }; 77 78 void A::f() {} 79 80 struct B : A { 81 virtual void f(); 82 }; 83 84 void B::f() {} 85 86 struct C : A { 87 }; 88 89 int main(int argc, char **argv) { 90 #ifdef B32 91 break_optimization(new Deriver<B, 0>); 92 #endif 93 94 #ifdef B64 95 break_optimization(new Deriver<B, 0>); 96 break_optimization(new Deriver<B, 1>); 97 #endif 98 99 #ifdef BM 100 break_optimization(new Deriver<B, 0>); 101 break_optimization(new Deriver<B, 1>); 102 break_optimization(new Deriver<B, 2>); 103 #endif 104 105 B *b = new B; 106 break_optimization(b); 107 108 // FAIL: 1 109 // PASS: 1 110 fprintf(stderr, "1\n"); 111 112 A a; 113 114 // CFI-DIAG-D: runtime error: control flow integrity check for type 'B' failed during base-to-derived cast 115 // CFI-DIAG-D-NEXT: note: vtable is of type '{{(struct )?}}A' 116 117 // CFI-DIAG-U: runtime error: control flow integrity check for type 'B' failed during cast to unrelated type 118 // CFI-DIAG-U-NEXT: note: vtable is of type '{{(struct )?}}A' 119 120 switch (argv[1][0]) { 121 case 'a': 122 static_cast<B *>(&a); // UB 123 break; 124 case 'b': 125 static_cast<B &>(a); // UB 126 break; 127 case 'c': 128 static_cast<B &&>(a); // UB 129 break; 130 case 'd': 131 static_cast<C *>(&a); // UB, strict only 132 break; 133 case 'e': 134 static_cast<C &>(a); // UB, strict only 135 break; 136 case 'f': 137 static_cast<C &&>(a); // UB, strict only 138 break; 139 case 'g': 140 static_cast<B *>(static_cast<void *>(&a)); // Non-UB bad cast 141 break; 142 case 'h': 143 static_cast<C *>(static_cast<void *>(&a)); // Non-UB bad cast, strict only 144 break; 145 } 146 147 // FAIL-NOT: {{^2$}} 148 // PASS: {{^2$}} 149 fprintf(stderr, "2\n"); 150 } 151