From f1d13da249d52dc549945aacb1c4059e4079e412 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Sat, 21 Feb 2015 01:36:08 +0000 Subject: [PATCH] CFI: Add tests for 32-bit, 64-bit and memory bitsets. Break optimization in more places. llvm-svn: 230116 --- compiler-rt/test/cfi/anon-namespace.cpp | 32 ++++++++++++++++ compiler-rt/test/cfi/multiple-inheritance.cpp | 35 ++++++++++++++++++ compiler-rt/test/cfi/overwrite.cpp | 26 +++++++++++++ compiler-rt/test/cfi/simple-fail.cpp | 26 +++++++++++++ compiler-rt/test/cfi/simple-pass.cpp | 4 +- compiler-rt/test/cfi/utils.h | 53 +++++++++++++++++++++++++++ compiler-rt/test/cfi/vdtor.cpp | 26 +++++++++++++ 7 files changed, 199 insertions(+), 3 deletions(-) create mode 100644 compiler-rt/test/cfi/utils.h diff --git a/compiler-rt/test/cfi/anon-namespace.cpp b/compiler-rt/test/cfi/anon-namespace.cpp index f634ab3..0c2c689 100644 --- a/compiler-rt/test/cfi/anon-namespace.cpp +++ b/compiler-rt/test/cfi/anon-namespace.cpp @@ -3,6 +3,21 @@ // RUN: %clangxx_cfi -o %t %t1.o %t2.o // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %clangxx_cfi -c -DTU1 -DB32 -o %t1.o %s +// RUN: %clangxx_cfi -c -DTU2 -DB32 -o %t2.o %S/../cfi/anon-namespace.cpp +// RUN: %clangxx_cfi -o %t %t1.o %t2.o +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -c -DTU1 -DB64 -o %t1.o %s +// RUN: %clangxx_cfi -c -DTU2 -DB64 -o %t2.o %S/../cfi/anon-namespace.cpp +// RUN: %clangxx_cfi -o %t %t1.o %t2.o +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -c -DTU1 -DBM -o %t1.o %s +// RUN: %clangxx_cfi -c -DTU2 -DBM -o %t2.o %S/../cfi/anon-namespace.cpp +// RUN: %clangxx_cfi -o %t %t1.o %t2.o +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + // RUN: %clangxx -c -DTU1 -o %t1.o %s // RUN: %clangxx -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp // RUN: %clangxx -o %t %t1.o %t2.o @@ -19,6 +34,7 @@ // so we have to mangle the file path into the bitset name. #include +#include "utils.h" struct A { virtual void f() = 0; @@ -45,7 +61,23 @@ A *mkb() { #ifdef TU2 int main() { +#ifdef B32 + break_optimization(new Deriver); +#endif + +#ifdef B64 + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + +#ifdef BM + break_optimization(new Deriver); + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + A *a = mkb(); + break_optimization(a); // CFI: 1 // NCFI: 1 diff --git a/compiler-rt/test/cfi/multiple-inheritance.cpp b/compiler-rt/test/cfi/multiple-inheritance.cpp index 1b03af4..523af6f 100644 --- a/compiler-rt/test/cfi/multiple-inheritance.cpp +++ b/compiler-rt/test/cfi/multiple-inheritance.cpp @@ -2,6 +2,18 @@ // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s // RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %clangxx_cfi -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s + // RUN: %clangxx -o %t %s // RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s // RUN: %t x 2>&1 | FileCheck --check-prefix=NCFI %s @@ -10,6 +22,7 @@ // permits calls via virtual tables for the correct base class. #include +#include "utils.h" struct A { virtual void f() = 0; @@ -27,7 +40,29 @@ void C::f() {} void C::g() {} int main(int argc, char **argv) { +#ifdef B32 + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + +#ifdef B64 + break_optimization(new Deriver); + break_optimization(new Deriver); + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + +#ifdef BM + break_optimization(new Deriver); + break_optimization(new Deriver); + break_optimization(new Deriver); + break_optimization(new Deriver); + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + C *c = new C; + break_optimization(c); // CFI: 1 // NCFI: 1 diff --git a/compiler-rt/test/cfi/overwrite.cpp b/compiler-rt/test/cfi/overwrite.cpp index 74cb3fd..d7e58d9 100644 --- a/compiler-rt/test/cfi/overwrite.cpp +++ b/compiler-rt/test/cfi/overwrite.cpp @@ -1,6 +1,15 @@ // RUN: %clangxx_cfi -o %t %s // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %clangxx_cfi -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + // RUN: %clangxx -o %t %s // RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s @@ -10,6 +19,7 @@ // attempting to make a call through it. #include +#include "utils.h" struct A { virtual void f(); @@ -24,8 +34,24 @@ void foo() { void *fake_vtable[] = { (void *)&foo }; int main() { +#ifdef B32 + break_optimization(new Deriver); +#endif + +#ifdef B64 + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + +#ifdef BM + break_optimization(new Deriver); + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + A *a = new A; *((void **)a) = fake_vtable; // UB here + break_optimization(a); // CFI: 1 // NCFI: 1 diff --git a/compiler-rt/test/cfi/simple-fail.cpp b/compiler-rt/test/cfi/simple-fail.cpp index de3b7ed1..d8f3b48 100644 --- a/compiler-rt/test/cfi/simple-fail.cpp +++ b/compiler-rt/test/cfi/simple-fail.cpp @@ -1,6 +1,15 @@ // RUN: %clangxx_cfi -o %t %s // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %clangxx_cfi -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + // RUN: %clangxx -o %t %s // RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s @@ -9,6 +18,7 @@ // pointer to such an object and attempting to make a call through it. #include +#include "utils.h" struct A { virtual void f(); @@ -23,7 +33,23 @@ struct B { void B::f() {} int main() { +#ifdef B32 + break_optimization(new Deriver); +#endif + +#ifdef B64 + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + +#ifdef BM + break_optimization(new Deriver); + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + A *a = new A; + break_optimization(a); // CFI: 1 // NCFI: 1 diff --git a/compiler-rt/test/cfi/simple-pass.cpp b/compiler-rt/test/cfi/simple-pass.cpp index e8eb393..50e7d92 100644 --- a/compiler-rt/test/cfi/simple-pass.cpp +++ b/compiler-rt/test/cfi/simple-pass.cpp @@ -5,9 +5,7 @@ // kinds of valid calls involving classes with various different linkages and // types of inheritance. -inline void break_optimization(void *arg) { - __asm__ __volatile__("" : : "r" (arg) : "memory"); -} +#include "utils.h" struct A { virtual void f(); diff --git a/compiler-rt/test/cfi/utils.h b/compiler-rt/test/cfi/utils.h new file mode 100644 index 0000000..5c290d1 --- /dev/null +++ b/compiler-rt/test/cfi/utils.h @@ -0,0 +1,53 @@ +#ifndef UTILS_H +#define UTILS_H + +inline void break_optimization(void *arg) { + __asm__ __volatile__("" : : "r" (arg) : "memory"); +} + +// Tests will instantiate this class to pad out bit sets to test out the various +// ways we can represent the bit set (32-bit inline, 64-bit inline, memory). +// This class has 37 virtual member functions, which forces us to use a +// pointer-aligned bitset. +template +class Deriver : T { + virtual void f() {} + virtual void g() {} + virtual void f1() {} + virtual void f2() {} + virtual void f3() {} + virtual void f4() {} + virtual void f5() {} + virtual void f6() {} + virtual void f7() {} + virtual void f8() {} + virtual void f9() {} + virtual void f10() {} + virtual void f11() {} + virtual void f12() {} + virtual void f13() {} + virtual void f14() {} + virtual void f15() {} + virtual void f16() {} + virtual void f17() {} + virtual void f18() {} + virtual void f19() {} + virtual void f20() {} + virtual void f21() {} + virtual void f22() {} + virtual void f23() {} + virtual void f24() {} + virtual void f25() {} + virtual void f26() {} + virtual void f27() {} + virtual void f28() {} + virtual void f29() {} + virtual void f30() {} + virtual void f31() {} + virtual void f32() {} + virtual void f33() {} + virtual void f34() {} + virtual void f35() {} +}; + +#endif diff --git a/compiler-rt/test/cfi/vdtor.cpp b/compiler-rt/test/cfi/vdtor.cpp index f8101ba..e21883c 100644 --- a/compiler-rt/test/cfi/vdtor.cpp +++ b/compiler-rt/test/cfi/vdtor.cpp @@ -1,6 +1,15 @@ // RUN: %clangxx_cfi -o %t %s // RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %clangxx_cfi -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + // RUN: %clangxx -o %t %s // RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s @@ -8,6 +17,7 @@ // via 'delete'. #include +#include "utils.h" struct A { virtual ~A(); @@ -22,7 +32,23 @@ struct B { B::~B() {} int main() { +#ifdef B32 + break_optimization(new Deriver); +#endif + +#ifdef B64 + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + +#ifdef BM + break_optimization(new Deriver); + break_optimization(new Deriver); + break_optimization(new Deriver); +#endif + A *a = new A; + break_optimization(a); // CFI: 1 // NCFI: 1 -- 2.7.4