diff options
Diffstat (limited to 'test/cfi/nvcall.cpp')
-rw-r--r-- | test/cfi/nvcall.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/test/cfi/nvcall.cpp b/test/cfi/nvcall.cpp new file mode 100644 index 000000000000..04419bd9d855 --- /dev/null +++ b/test/cfi/nvcall.cpp @@ -0,0 +1,72 @@ +// RUN: %clangxx_cfi -o %t1 %s +// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB32 -o %t2 %s +// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB64 -o %t3 %s +// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DBM -o %t4 %s +// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx -o %t5 %s +// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s + +// RUN: %clangxx_cfi_diag -o %t6 %s +// RUN: %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s + +// Tests that the CFI mechanism crashes the program when making a non-virtual +// call to an object of the wrong class, by casting a pointer to such an object +// and attempting to make a call through it. + +// REQUIRES: cxxabi + +#include <stdio.h> +#include "utils.h" + +struct A { + virtual void v(); +}; + +void A::v() {} + +struct B { + void f(); + virtual void g(); +}; + +void B::f() {} +void B::g() {} + +int main() { +#ifdef B32 + break_optimization(new Deriver<B, 0>); +#endif + +#ifdef B64 + break_optimization(new Deriver<B, 0>); + break_optimization(new Deriver<B, 1>); +#endif + +#ifdef BM + break_optimization(new Deriver<B, 0>); + break_optimization(new Deriver<B, 1>); + break_optimization(new Deriver<B, 2>); +#endif + + A *a = new A; + break_optimization(a); + + // CFI: 1 + // NCFI: 1 + fprintf(stderr, "1\n"); + + // CFI-DIAG: runtime error: control flow integrity check for type 'B' failed during non-virtual call + // CFI-DIAG-NEXT: note: vtable is of type '{{(struct )?}}A' + ((B *)a)->f(); // UB here + + // CFI-NOT: {{^2$}} + // NCFI: {{^2$}} + fprintf(stderr, "2\n"); +} |