xref: /llvm-project/compiler-rt/test/cfi/mfcall.cpp (revision 714301d784308c74724ab30ea566fa14fc01d300)
1 // UNSUPPORTED: target={{.*windows-msvc.*}}
2 
3 // RUN: %clangxx_cfi -o %t %s
4 // RUN: %expect_crash %run %t a
5 // RUN: %expect_crash %run %t b
6 // RUN: %expect_crash %run %t c
7 // RUN: %expect_crash %run %t d
8 // RUN: %expect_crash %run %t e
9 // RUN: %run %t f
10 // RUN: %run %t g
11 
12 // RUN: %clangxx_cfi_diag -o %t2 %s
13 // RUN: %run %t2 a 2>&1 | FileCheck --check-prefix=A %s
14 // RUN: %run %t2 b 2>&1 | FileCheck --check-prefix=B %s
15 // RUN: %run %t2 c 2>&1 | FileCheck --check-prefix=C %s
16 // RUN: %run %t2 d 2>&1 | FileCheck --check-prefix=D %s
17 // RUN: %run %t2 e 2>&1 | FileCheck --check-prefix=E %s
18 
19 #include <assert.h>
20 #include <string.h>
21 
22 struct SBase1 {
b1SBase123   void b1() {}
24 };
25 
26 struct SBase2 {
b2SBase227   void b2() {}
28 };
29 
30 struct S : SBase1, SBase2 {
f1S31   void f1() {}
f2S32   int f2() { return 1; }
g1S33   virtual void g1() {}
g2S34   virtual int g2() { return 1; }
g3S35   virtual int g3() { return 1; }
36 };
37 
38 struct T {
f1T39   void f1() {}
f2T40   int f2() { return 2; }
g1T41   virtual void g1() {}
g2T42   virtual int g2() { return 2; }
g3T43   virtual void g3() {}
44 };
45 
46 typedef void (S::*S_void)();
47 
48 typedef int (S::*S_int)();
49 typedef int (T::*T_int)();
50 
51 template <typename To, typename From>
bitcast(From f)52 To bitcast(From f) {
53   assert(sizeof(To) == sizeof(From));
54   To t;
55   memcpy(&t, &f, sizeof(f));
56   return t;
57 }
58 
main(int argc,char ** argv)59 int main(int argc, char **argv) {
60   S s;
61   T t;
62 
63   switch (argv[1][0]) {
64     case 'a':
65       // A: runtime error: control flow integrity check for type 'int (S::*)()' failed during non-virtual pointer to member function call
66       // A: note: S::f1() defined here
67       (s.*bitcast<S_int>(&S::f1))();
68       break;
69     case 'b':
70       // B: runtime error: control flow integrity check for type 'int (T::*)()' failed during non-virtual pointer to member function call
71       // B: note: S::f2() defined here
72       (t.*bitcast<T_int>(&S::f2))();
73       break;
74     case 'c':
75       // C: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual pointer to member function call
76       // C: note: vtable is of type 'S'
77       (s.*bitcast<S_int>(&S::g1))();
78       break;
79     case 'd':
80       // D: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual pointer to member function call
81       // D: note: vtable is of type 'T'
82       (reinterpret_cast<S &>(t).*&S::g2)();
83       break;
84     case 'e':
85       // E: runtime error: control flow integrity check for type 'void (S::*)()' failed during virtual pointer to member function call
86       // E: note: vtable is of type 'S'
87       (s.*bitcast<S_void>(&T::g3))();
88       break;
89     case 'f':
90       (s.*&SBase1::b1)();
91       break;
92     case 'g':
93       (s.*&SBase2::b2)();
94       break;
95   }
96 }
97