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
74struct A {
75 virtual void f();
76};
77
78void A::f() {}
79
80struct B : A {
81 virtual void f();
82};
83
84void B::f() {}
85
86struct C : A {
87};
88
89int 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