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