1 // RUN: %clangxx_cfi -o %t %s 2 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 3 4 // RUN: %clangxx_cfi -DB32 -o %t %s 5 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 6 7 // RUN: %clangxx_cfi -DB64 -o %t %s 8 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 9 10 // RUN: %clangxx_cfi -DBM -o %t %s 11 // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s 12 13 // RUN: %clangxx -o %t %s 14 // RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s 15 16 // RUN: %clangxx_cfi_diag -o %t %s 17 // RUN: %t 2>&1 | FileCheck --check-prefix=CFI-DIAG %s 18 19 // Tests that the CFI enforcement also applies to virtual destructor calls made 20 // via 'delete'. 21 22 #include <stdio.h> 23 #include "utils.h" 24 25 struct A { 26 virtual ~A(); 27 }; 28 29 A::~A() {} 30 31 struct B { 32 virtual ~B(); 33 }; 34 35 B::~B() {} 36 37 int main() { 38 #ifdef B32 39 break_optimization(new Deriver<B, 0>); 40 #endif 41 42 #ifdef B64 43 break_optimization(new Deriver<B, 0>); 44 break_optimization(new Deriver<B, 1>); 45 #endif 46 47 #ifdef BM 48 break_optimization(new Deriver<B, 0>); 49 break_optimization(new Deriver<B, 1>); 50 break_optimization(new Deriver<B, 2>); 51 #endif 52 53 A *a = new A; 54 break_optimization(a); 55 56 // CFI: 1 57 // NCFI: 1 58 fprintf(stderr, "1\n"); 59 60 // CFI-DIAG: runtime error: control flow integrity check for type 'B' failed during virtual call 61 // CFI-DIAG-NEXT: note: vtable is of type 'A' 62 delete (B *)a; // UB here 63 64 // CFI-NOT: 2 65 // NCFI: 2 66 fprintf(stderr, "2\n"); 67 } 68