1*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t1-so.so 2*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso %s -o %t1 %t1-so.so 3*7c3d14c8STreehugger Robot // RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s 4*7c3d14c8STreehugger Robot // RUN: %expect_crash %t1 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s 5*7c3d14c8STreehugger Robot 6*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %t2-so.so 7*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso -DB32 %s -o %t2 %t2-so.so 8*7c3d14c8STreehugger Robot // RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s 9*7c3d14c8STreehugger Robot // RUN: %expect_crash %t2 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s 10*7c3d14c8STreehugger Robot 11*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %t3-so.so 12*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso -DB64 %s -o %t3 %t3-so.so 13*7c3d14c8STreehugger Robot // RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s 14*7c3d14c8STreehugger Robot // RUN: %expect_crash %t3 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s 15*7c3d14c8STreehugger Robot 16*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %t4-so.so 17*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso -DBM %s -o %t4 %t4-so.so 18*7c3d14c8STreehugger Robot // RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s 19*7c3d14c8STreehugger Robot // RUN: %expect_crash %t4 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s 20*7c3d14c8STreehugger Robot 21*7c3d14c8STreehugger Robot // RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t5-so.so 22*7c3d14c8STreehugger Robot // RUN: %clangxx -DBM %s -o %t5 %t5-so.so 23*7c3d14c8STreehugger Robot // RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s 24*7c3d14c8STreehugger Robot // RUN: %t5 x 2>&1 | FileCheck --check-prefix=NCFI %s 25*7c3d14c8STreehugger Robot 26*7c3d14c8STreehugger Robot // RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t6-so.so 27*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso -DBM %s -o %t6 %t6-so.so 28*7c3d14c8STreehugger Robot // RUN: %t6 2>&1 | FileCheck --check-prefix=NCFI %s 29*7c3d14c8STreehugger Robot // RUN: %t6 x 2>&1 | FileCheck --check-prefix=NCFI %s 30*7c3d14c8STreehugger Robot 31*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso_diag -DSHARED_LIB %s -fPIC -shared -o %t7-so.so 32*7c3d14c8STreehugger Robot // RUN: %clangxx_cfi_dso_diag %s -o %t7 %t7-so.so 33*7c3d14c8STreehugger Robot // RUN: %t7 2>&1 | FileCheck --check-prefix=CFI-DIAG-CALL %s 34*7c3d14c8STreehugger Robot // RUN: %t7 x 2>&1 | FileCheck --check-prefix=CFI-DIAG-CALL --check-prefix=CFI-DIAG-CAST %s 35*7c3d14c8STreehugger Robot 36*7c3d14c8STreehugger Robot // Tests that the CFI mechanism crashes the program when making a virtual call 37*7c3d14c8STreehugger Robot // to an object of the wrong class but with a compatible vtable, by casting a 38*7c3d14c8STreehugger Robot // pointer to such an object and attempting to make a call through it. 39*7c3d14c8STreehugger Robot 40*7c3d14c8STreehugger Robot // REQUIRES: cxxabi 41*7c3d14c8STreehugger Robot 42*7c3d14c8STreehugger Robot #include <stdio.h> 43*7c3d14c8STreehugger Robot #include <string.h> 44*7c3d14c8STreehugger Robot 45*7c3d14c8STreehugger Robot struct A { 46*7c3d14c8STreehugger Robot virtual void f(); 47*7c3d14c8STreehugger Robot }; 48*7c3d14c8STreehugger Robot 49*7c3d14c8STreehugger Robot void *create_B(); 50*7c3d14c8STreehugger Robot 51*7c3d14c8STreehugger Robot #ifdef SHARED_LIB 52*7c3d14c8STreehugger Robot 53*7c3d14c8STreehugger Robot #include "../utils.h" 54*7c3d14c8STreehugger Robot struct B { 55*7c3d14c8STreehugger Robot virtual void f(); 56*7c3d14c8STreehugger Robot }; f()57*7c3d14c8STreehugger Robotvoid B::f() {} 58*7c3d14c8STreehugger Robot create_B()59*7c3d14c8STreehugger Robotvoid *create_B() { 60*7c3d14c8STreehugger Robot create_derivers<B>(); 61*7c3d14c8STreehugger Robot return (void *)(new B()); 62*7c3d14c8STreehugger Robot } 63*7c3d14c8STreehugger Robot 64*7c3d14c8STreehugger Robot #else 65*7c3d14c8STreehugger Robot f()66*7c3d14c8STreehugger Robotvoid A::f() {} 67*7c3d14c8STreehugger Robot main(int argc,char * argv[])68*7c3d14c8STreehugger Robotint main(int argc, char *argv[]) { 69*7c3d14c8STreehugger Robot void *p = create_B(); 70*7c3d14c8STreehugger Robot A *a; 71*7c3d14c8STreehugger Robot 72*7c3d14c8STreehugger Robot // CFI: =0= 73*7c3d14c8STreehugger Robot // CFI-CAST: =0= 74*7c3d14c8STreehugger Robot // NCFI: =0= 75*7c3d14c8STreehugger Robot fprintf(stderr, "=0=\n"); 76*7c3d14c8STreehugger Robot 77*7c3d14c8STreehugger Robot if (argc > 1 && argv[1][0] == 'x') { 78*7c3d14c8STreehugger Robot // Test cast. BOOM. 79*7c3d14c8STreehugger Robot // CFI-DIAG-CAST: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type 80*7c3d14c8STreehugger Robot // CFI-DIAG-CAST-NEXT: note: vtable is of type '{{(struct )?}}B' 81*7c3d14c8STreehugger Robot a = (A*)p; 82*7c3d14c8STreehugger Robot } else { 83*7c3d14c8STreehugger Robot // Invisible to CFI. Test virtual call later. 84*7c3d14c8STreehugger Robot memcpy(&a, &p, sizeof(a)); 85*7c3d14c8STreehugger Robot } 86*7c3d14c8STreehugger Robot 87*7c3d14c8STreehugger Robot // CFI: =1= 88*7c3d14c8STreehugger Robot // CFI-CAST-NOT: =1= 89*7c3d14c8STreehugger Robot // NCFI: =1= 90*7c3d14c8STreehugger Robot fprintf(stderr, "=1=\n"); 91*7c3d14c8STreehugger Robot 92*7c3d14c8STreehugger Robot // CFI-DIAG-CALL: runtime error: control flow integrity check for type 'A' failed during virtual call 93*7c3d14c8STreehugger Robot // CFI-DIAG-CALL-NEXT: note: vtable is of type '{{(struct )?}}B' 94*7c3d14c8STreehugger Robot a->f(); // UB here 95*7c3d14c8STreehugger Robot 96*7c3d14c8STreehugger Robot // CFI-NOT: =2= 97*7c3d14c8STreehugger Robot // CFI-CAST-NOT: =2= 98*7c3d14c8STreehugger Robot // NCFI: =2= 99*7c3d14c8STreehugger Robot fprintf(stderr, "=2=\n"); 100*7c3d14c8STreehugger Robot } 101*7c3d14c8STreehugger Robot #endif 102