Home | History | Annotate | Download | only in cfi
      1 // RUN: %clangxx_cfi -o %t1 %s
      2 // RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s
      3 
      4 // RUN: %clangxx_cfi -DB32 -o %t2 %s
      5 // RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s
      6 
      7 // RUN: %clangxx_cfi -DB64 -o %t3 %s
      8 // RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s
      9 
     10 // RUN: %clangxx_cfi -DBM -o %t4 %s
     11 // RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s
     12 
     13 // RUN: %clangxx -o %t5 %s
     14 // RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s
     15 
     16 // RUN: %clangxx_cfi_diag -o %t6 %s
     17 // RUN: %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s
     18 
     19 // Tests that the CFI mechanism crashes the program when a virtual table is
     20 // replaced with a compatible table of function pointers that does not belong to
     21 // any class, by manually overwriting the virtual table of an object and
     22 // attempting to make a call through it.
     23 
     24 // REQUIRES: cxxabi
     25 
     26 #include <stdio.h>
     27 #include "utils.h"
     28 
     29 struct A {
     30   virtual void f();
     31 };
     32 
     33 void A::f() {}
     34 
     35 void foo() {
     36   fprintf(stderr, "foo\n");
     37 }
     38 
     39 void *fake_vtable[] = { 0, 0, (void *)&foo };
     40 
     41 int main() {
     42   create_derivers<A>();
     43 
     44   A *a = new A;
     45   *((void **)a) = fake_vtable + 2; // UB here
     46   break_optimization(a);
     47 
     48   // CFI: 1
     49   // NCFI: 1
     50   fprintf(stderr, "1\n");
     51 
     52   // CFI-NOT: foo
     53   // NCFI: foo
     54   // CFI-DIAG: runtime error: control flow integrity check for type 'A' failed during virtual call
     55   // CFI-DIAG-NEXT: note: invalid vtable
     56   a->f();
     57 
     58   // CFI-NOT: {{^2$}}
     59   // NCFI: {{^2$}}
     60   fprintf(stderr, "2\n");
     61 }
     62