1 // RUN: %clangxx_cfi -o %t %s 2 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 3 // RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s 4 5 // RUN: %clangxx_cfi -DB32 -o %t %s 6 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 7 // RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s 8 9 // RUN: %clangxx_cfi -DB64 -o %t %s 10 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 11 // RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s 12 13 // RUN: %clangxx_cfi -DBM -o %t %s 14 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 15 // RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s 16 17 // RUN: %clangxx -o %t %s 18 // RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s 19 // RUN: %t x 2>&1 | FileCheck --check-prefix=NCFI %s 20 21 // Tests that the CFI mechanism is sensitive to multiple inheritance and only 22 // permits calls via virtual tables for the correct base class. 23 24 #include <stdio.h> 25 #include "utils.h" 26 27 struct A { 28 virtual void f() = 0; 29 }; 30 31 struct B { 32 virtual void g() = 0; 33 }; 34 35 struct C : A, B { 36 virtual void f(), g(); 37 }; 38 39 void C::f() {} 40 void C::g() {} 41 42 int main(int argc, char **argv) { 43 #ifdef B32 44 break_optimization(new Deriver<A, 0>); 45 break_optimization(new Deriver<B, 0>); 46 #endif 47 48 #ifdef B64 49 break_optimization(new Deriver<A, 0>); 50 break_optimization(new Deriver<A, 1>); 51 break_optimization(new Deriver<B, 0>); 52 break_optimization(new Deriver<B, 1>); 53 #endif 54 55 #ifdef BM 56 break_optimization(new Deriver<A, 0>); 57 break_optimization(new Deriver<A, 1>); 58 break_optimization(new Deriver<A, 2>); 59 break_optimization(new Deriver<B, 0>); 60 break_optimization(new Deriver<B, 1>); 61 break_optimization(new Deriver<B, 2>); 62 #endif 63 64 C *c = new C; 65 break_optimization(c); 66 67 // CFI: 1 68 // NCFI: 1 69 fprintf(stderr, "1\n"); 70 71 if (argc > 1) { 72 A *a = c; 73 ((B *)a)->g(); // UB here 74 } else { 75 B *b = c; 76 ((A *)b)->f(); // UB here 77 } 78 79 // CFI-NOT: 2 80 // NCFI: 2 81 fprintf(stderr, "2\n"); 82 } 83