diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 11:52:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 11:52:19 +0000 |
commit | 5c909fa013fc285f010a95e8d387e0ef3412da9c (patch) | |
tree | 1059d068ad281f4776ff44cd414574f99a460023 /test/cfi | |
parent | f31bcc68c72371a2bf63aead9f3373a1ff2053b6 (diff) | |
download | src-5c909fa013fc285f010a95e8d387e0ef3412da9c.tar.gz src-5c909fa013fc285f010a95e8d387e0ef3412da9c.zip |
Vendor import of compiler-rt trunk r256633:vendor/compiler-rt/compiler-rt-trunk-r256633
Notes
Notes:
svn path=/vendor/compiler-rt/dist/; revision=292925
svn path=/vendor/compiler-rt/compiler-rt-trunk-r256633/; revision=292926; tag=vendor/compiler-rt/compiler-rt-trunk-r256633
Diffstat (limited to 'test/cfi')
-rw-r--r-- | test/cfi/CMakeLists.txt | 9 | ||||
-rw-r--r-- | test/cfi/anon-namespace.cpp | 15 | ||||
-rw-r--r-- | test/cfi/bad-cast.cpp | 15 | ||||
-rw-r--r-- | test/cfi/base-derived-destructor.cpp | 93 | ||||
-rw-r--r-- | test/cfi/create-derivers.test | 20 | ||||
-rw-r--r-- | test/cfi/cross-dso/icall/icall-from-dso.cpp | 26 | ||||
-rw-r--r-- | test/cfi/cross-dso/icall/icall.cpp | 21 | ||||
-rw-r--r-- | test/cfi/cross-dso/icall/lit.local.cfg | 3 | ||||
-rw-r--r-- | test/cfi/cross-dso/lit.local.cfg | 9 | ||||
-rw-r--r-- | test/cfi/cross-dso/simple-fail.cpp | 92 | ||||
-rw-r--r-- | test/cfi/cross-dso/simple-pass.cpp | 65 | ||||
-rw-r--r-- | test/cfi/icall/bad-signature.c | 27 | ||||
-rw-r--r-- | test/cfi/icall/external-call.c | 27 | ||||
-rw-r--r-- | test/cfi/icall/lit.local.cfg | 3 | ||||
-rw-r--r-- | test/cfi/lit.cfg | 7 | ||||
-rw-r--r-- | test/cfi/multiple-inheritance.cpp | 22 | ||||
-rw-r--r-- | test/cfi/nvcall.cpp | 15 | ||||
-rw-r--r-- | test/cfi/overwrite.cpp | 15 | ||||
-rw-r--r-- | test/cfi/sibling.cpp | 15 | ||||
-rw-r--r-- | test/cfi/simple-fail.cpp | 15 | ||||
-rw-r--r-- | test/cfi/utils.h | 94 | ||||
-rw-r--r-- | test/cfi/vdtor.cpp | 15 |
22 files changed, 458 insertions, 165 deletions
diff --git a/test/cfi/CMakeLists.txt b/test/cfi/CMakeLists.txt index 21463ac408de..c4f7eb92c524 100644 --- a/test/cfi/CMakeLists.txt +++ b/test/cfi/CMakeLists.txt @@ -3,12 +3,11 @@ configure_lit_site_cfg( ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg ) -set(CFI_TEST_DEPS) +set(CFI_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) if(NOT COMPILER_RT_STANDALONE_BUILD) list(APPEND CFI_TEST_DEPS - FileCheck - clang - not + cfi + opt ubsan ) if(LLVM_ENABLE_PIC AND LLVM_BINUTILS_INCDIR) @@ -21,7 +20,7 @@ if(NOT COMPILER_RT_STANDALONE_BUILD) LTO ) endif() - if(WIN32 AND EXISTS ${CMAKE_SOURCE_DIR}/tools/lld) + if(WIN32 AND COMPILER_RT_HAS_LLD_SOURCES) list(APPEND CFI_TEST_DEPS lld ) diff --git a/test/cfi/anon-namespace.cpp b/test/cfi/anon-namespace.cpp index f25f3405516e..8e6c1c1157d5 100644 --- a/test/cfi/anon-namespace.cpp +++ b/test/cfi/anon-namespace.cpp @@ -68,20 +68,7 @@ A *mkb() { #ifdef TU2 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 + create_derivers<B>(); A *a = mkb(); break_optimization(a); diff --git a/test/cfi/bad-cast.cpp b/test/cfi/bad-cast.cpp index 9ba6f6dbacec..e2f4f25a4a28 100644 --- a/test/cfi/bad-cast.cpp +++ b/test/cfi/bad-cast.cpp @@ -87,20 +87,7 @@ struct C : A { }; int main(int argc, char **argv) { -#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 + create_derivers<B>(); B *b = new B; break_optimization(b); diff --git a/test/cfi/base-derived-destructor.cpp b/test/cfi/base-derived-destructor.cpp new file mode 100644 index 000000000000..c5e9db1092a6 --- /dev/null +++ b/test/cfi/base-derived-destructor.cpp @@ -0,0 +1,93 @@ +// 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_cfi -O1 -o %t5 %s +// RUN: %expect_crash %t5 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O1 -DB32 -o %t6 %s +// RUN: %expect_crash %t6 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O1 -DB64 -o %t7 %s +// RUN: %expect_crash %t7 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O1 -DBM -o %t8 %s +// RUN: %expect_crash %t8 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O2 -o %t9 %s +// RUN: %expect_crash %t9 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O2 -DB32 -o %t10 %s +// RUN: %expect_crash %t10 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O2 -DB64 -o %t11 %s +// RUN: %expect_crash %t11 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O2 -DBM -o %t12 %s +// RUN: %expect_crash %t12 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O3 -o %t13 %s +// RUN: %expect_crash %t13 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O3 -DB32 -o %t14 %s +// RUN: %expect_crash %t14 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O3 -DB64 -o %t15 %s +// RUN: %expect_crash %t15 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O3 -DBM -o %t16 %s +// RUN: %expect_crash %t16 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi_diag -o %t17 %s +// RUN: %t17 2>&1 | FileCheck --check-prefix=CFI-DIAG %s + +// RUN: %clangxx -o %t18 %s +// RUN: %t18 2>&1 | FileCheck --check-prefix=NCFI %s + +// Tests that the CFI mechanism crashes the program when making a +// base-to-derived cast from a destructor of the base class, +// where both types have virtual tables. + +// REQUIRES: cxxabi + +#include <stdio.h> +#include "utils.h" + +template<typename T> +class A { + public: + T* context() { return static_cast<T*>(this); } + + virtual ~A() { + break_optimization(context()); + } +}; + +class B : public A<B> { + public: + virtual ~B() { } +}; + +int main() { + // CFI: 1 + // NCFI: 1 + fprintf(stderr, "1\n"); + + // CFI-DIAG: runtime error: control flow integrity check for type 'B' failed during base-to-derived cast + // CFI-DIAG-NEXT: note: vtable is of type '{{(class )?}}A<{{(class )?}}B>' + B* b = new B; + break_optimization(b); + delete b; // UB here + + // CFI-NOT: {{^2$}} + // NCFI: {{^2$}} + fprintf(stderr, "2\n"); +} diff --git a/test/cfi/create-derivers.test b/test/cfi/create-derivers.test new file mode 100644 index 000000000000..79521e4d085a --- /dev/null +++ b/test/cfi/create-derivers.test @@ -0,0 +1,20 @@ +REQUIRES: asserts + +RUN: %clangxx_cfi -c -o %t1.o %S/simple-fail.cpp +RUN: opt -lowerbitsets -debug-only=lowerbitsets -o /dev/null %t1.o 2>&1 | FileCheck --check-prefix=B0 %s +B0: {{1B|B@@}}: {{.*}} size 1 + +RUN: %clangxx_cfi -DB32 -c -o %t2.o %S/simple-fail.cpp +RUN: opt -lowerbitsets -debug-only=lowerbitsets -o /dev/null %t2.o 2>&1 | FileCheck --check-prefix=B32 %s +B32: {{1B|B@@}}: {{.*}} size 24 +B32-NOT: all-ones + +RUN: %clangxx_cfi -DB64 -c -o %t3.o %S/simple-fail.cpp +RUN: opt -lowerbitsets -debug-only=lowerbitsets -o /dev/null %t3.o 2>&1 | FileCheck --check-prefix=B64 %s +B64: {{1B|B@@}}: {{.*}} size 54 +B64-NOT: all-ones + +RUN: %clangxx_cfi -DBM -c -o %t4.o %S/simple-fail.cpp +RUN: opt -lowerbitsets -debug-only=lowerbitsets -o /dev/null %t4.o 2>&1 | FileCheck --check-prefix=BM %s +BM: {{1B|B@@}}: {{.*}} size 84 +BM-NOT: all-ones diff --git a/test/cfi/cross-dso/icall/icall-from-dso.cpp b/test/cfi/cross-dso/icall/icall-from-dso.cpp new file mode 100644 index 000000000000..1995f05f43d4 --- /dev/null +++ b/test/cfi/cross-dso/icall/icall-from-dso.cpp @@ -0,0 +1,26 @@ +// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t-so.so +// RUN: %clangxx_cfi_dso %s -o %t %t-so.so && %expect_crash %t 2>&1 | FileCheck %s + +#include <stdio.h> + +#ifdef SHARED_LIB +void g(); +void f() { + // CHECK: =1= + fprintf(stderr, "=1=\n"); + ((void (*)(void))g)(); + // CHECK: =2= + fprintf(stderr, "=2=\n"); + ((void (*)(int))g)(42); // UB here + // CHECK-NOT: =3= + fprintf(stderr, "=3=\n"); +} +#else +void f(); +void g() { +} + +int main() { + f(); +} +#endif diff --git a/test/cfi/cross-dso/icall/icall.cpp b/test/cfi/cross-dso/icall/icall.cpp new file mode 100644 index 000000000000..d7cc2f9ca94d --- /dev/null +++ b/test/cfi/cross-dso/icall/icall.cpp @@ -0,0 +1,21 @@ +// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t-so.so +// RUN: %clangxx_cfi_dso %s -o %t %t-so.so && %expect_crash %t 2>&1 | FileCheck %s + +#include <stdio.h> + +#ifdef SHARED_LIB +void f() { +} +#else +void f(); +int main() { + // CHECK: =1= + fprintf(stderr, "=1=\n"); + ((void (*)(void))f)(); + // CHECK: =2= + fprintf(stderr, "=2=\n"); + ((void (*)(int))f)(42); // UB here + // CHECK-NOT: =3= + fprintf(stderr, "=3=\n"); +} +#endif diff --git a/test/cfi/cross-dso/icall/lit.local.cfg b/test/cfi/cross-dso/icall/lit.local.cfg new file mode 100644 index 000000000000..db08765a2bb2 --- /dev/null +++ b/test/cfi/cross-dso/icall/lit.local.cfg @@ -0,0 +1,3 @@ +# The cfi-icall checker is only supported on x86 and x86_64 for now. +if config.root.host_arch not in ['x86', 'x86_64']: + config.unsupported = True diff --git a/test/cfi/cross-dso/lit.local.cfg b/test/cfi/cross-dso/lit.local.cfg new file mode 100644 index 000000000000..57271b8078a4 --- /dev/null +++ b/test/cfi/cross-dso/lit.local.cfg @@ -0,0 +1,9 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +root = getRoot(config) + +if root.host_os not in ['Linux']: + config.unsupported = True diff --git a/test/cfi/cross-dso/simple-fail.cpp b/test/cfi/cross-dso/simple-fail.cpp new file mode 100644 index 000000000000..64db288a95b5 --- /dev/null +++ b/test/cfi/cross-dso/simple-fail.cpp @@ -0,0 +1,92 @@ +// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t1-so.so +// RUN: %clangxx_cfi_dso %s -o %t1 %t1-so.so +// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %expect_crash %t1 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s + +// RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %t2-so.so +// RUN: %clangxx_cfi_dso -DB32 %s -o %t2 %t2-so.so +// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %expect_crash %t2 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s + +// RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %t3-so.so +// RUN: %clangxx_cfi_dso -DB64 %s -o %t3 %t3-so.so +// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %expect_crash %t3 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s + +// RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %t4-so.so +// RUN: %clangxx_cfi_dso -DBM %s -o %t4 %t4-so.so +// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %expect_crash %t4 x 2>&1 | FileCheck --check-prefix=CFI-CAST %s + +// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t5-so.so +// RUN: %clangxx -DBM %s -o %t5 %t5-so.so +// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s +// RUN: %t5 x 2>&1 | FileCheck --check-prefix=NCFI %s + +// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t6-so.so +// RUN: %clangxx_cfi_dso -DBM %s -o %t6 %t6-so.so +// RUN: %t6 2>&1 | FileCheck --check-prefix=NCFI %s +// RUN: %t6 x 2>&1 | FileCheck --check-prefix=NCFI %s + +// Tests that the CFI mechanism crashes the program when making a virtual call +// to an object of the wrong class but with a compatible vtable, by casting a +// pointer to such an object and attempting to make a call through it. + +// REQUIRES: cxxabi + +#include <stdio.h> +#include <string.h> + +struct A { + virtual void f(); +}; + +void *create_B(); + +#ifdef SHARED_LIB + +#include "../utils.h" +struct B { + virtual void f(); +}; +void B::f() {} + +void *create_B() { + create_derivers<B>(); + return (void *)(new B()); +} + +#else + +void A::f() {} + +int main(int argc, char *argv[]) { + void *p = create_B(); + A *a; + + // CFI: =0= + // CFI-CAST: =0= + // NCFI: =0= + fprintf(stderr, "=0=\n"); + + if (argc > 1 && argv[1][0] == 'x') { + // Test cast. BOOM. + a = (A*)p; + } else { + // Invisible to CFI. Test virtual call later. + memcpy(&a, &p, sizeof(a)); + } + + // CFI: =1= + // CFI-CAST-NOT: =1= + // NCFI: =1= + fprintf(stderr, "=1=\n"); + + a->f(); // UB here + + // CFI-NOT: =2= + // CFI-CAST-NOT: =2= + // NCFI: =2= + fprintf(stderr, "=2=\n"); +} +#endif diff --git a/test/cfi/cross-dso/simple-pass.cpp b/test/cfi/cross-dso/simple-pass.cpp new file mode 100644 index 000000000000..42f7a273453e --- /dev/null +++ b/test/cfi/cross-dso/simple-pass.cpp @@ -0,0 +1,65 @@ +// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t1-so.so +// RUN: %clangxx_cfi_dso %s -o %t1 %t1-so.so +// RUN: %t1 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %t2-so.so +// RUN: %clangxx_cfi_dso -DB32 %s -o %t2 %t2-so.so +// RUN: %t2 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %t3-so.so +// RUN: %clangxx_cfi_dso -DB64 %s -o %t3 %t3-so.so +// RUN: %t3 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %t4-so.so +// RUN: %clangxx_cfi_dso -DBM %s -o %t4 %t4-so.so +// RUN: %t4 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t5-so.so +// RUN: %clangxx -DBM %s -o %t5 %t5-so.so +// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s +// RUN: %t5 x 2>&1 | FileCheck --check-prefix=NCFI %s + +// Tests that the CFI mechanism crashes the program when making a virtual call +// to an object of the wrong class but with a compatible vtable, by casting a +// pointer to such an object and attempting to make a call through it. + +// REQUIRES: cxxabi + +#include <stdio.h> +#include <string.h> + +struct A { + virtual void f(); +}; + +A *create_B(); + +#ifdef SHARED_LIB + +#include "../utils.h" +struct B : public A { + virtual void f(); +}; +void B::f() {} + +A *create_B() { + create_derivers<B>(); + return new B(); +} + +#else + +void A::f() {} + +int main(int argc, char *argv[]) { + A *a = create_B(); + + // CFI: =1= + // NCFI: =1= + fprintf(stderr, "=1=\n"); + a->f(); // OK + // CFI: =2= + // NCFI: =2= + fprintf(stderr, "=2=\n"); +} +#endif diff --git a/test/cfi/icall/bad-signature.c b/test/cfi/icall/bad-signature.c new file mode 100644 index 000000000000..43de1178fe6c --- /dev/null +++ b/test/cfi/icall/bad-signature.c @@ -0,0 +1,27 @@ +// RUN: %clangxx -o %t1 %s +// RUN: %t1 2>&1 | FileCheck --check-prefix=NCFI %s + +// RUN: %clangxx_cfi -o %t2 %s +// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi_diag -g -o %t3 %s +// RUN: %t3 2>&1 | FileCheck --check-prefix=CFI-DIAG %s + +#include <stdio.h> + +void f() { +} + +int main() { + // CFI: 1 + // NCFI: 1 + fprintf(stderr, "1\n"); + + // CFI-DIAG: runtime error: control flow integrity check for type 'void (int)' failed during indirect function call + // CFI-DIAG: f() defined here + ((void (*)(int))f)(42); // UB here + + // CFI-NOT: 2 + // NCFI: 2 + fprintf(stderr, "2\n"); +} diff --git a/test/cfi/icall/external-call.c b/test/cfi/icall/external-call.c new file mode 100644 index 000000000000..43fc25207562 --- /dev/null +++ b/test/cfi/icall/external-call.c @@ -0,0 +1,27 @@ +// RUN: %clangxx_cfi -o %t1 %s +// RUN: %t1 c 1 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: %t1 s 2 2>&1 | FileCheck --check-prefix=CFI %s + +// This test uses jump tables containing PC-relative references to external +// symbols, which the Mach-O object writer does not currently support. +// XFAIL: darwin + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> + +int main(int argc, char **argv) { + // CFI: 1 + fprintf(stderr, "1\n"); + + double (*fn)(double); + if (argv[1][0] == 's') + fn = sin; + else + fn = cos; + + fn(atof(argv[2])); + + // CFI: 2 + fprintf(stderr, "2\n"); +} diff --git a/test/cfi/icall/lit.local.cfg b/test/cfi/icall/lit.local.cfg new file mode 100644 index 000000000000..db08765a2bb2 --- /dev/null +++ b/test/cfi/icall/lit.local.cfg @@ -0,0 +1,3 @@ +# The cfi-icall checker is only supported on x86 and x86_64 for now. +if config.root.host_arch not in ['x86', 'x86_64']: + config.unsupported = True diff --git a/test/cfi/lit.cfg b/test/cfi/lit.cfg index 1fa5a1e25137..687c80f4f08d 100644 --- a/test/cfi/lit.cfg +++ b/test/cfi/lit.cfg @@ -2,7 +2,7 @@ import lit.formats import os config.name = 'cfi' -config.suffixes = ['.cpp'] +config.suffixes = ['.c', '.cpp', '.test'] config.test_source_root = os.path.dirname(__file__) clangxx = ' '.join([config.clang] + config.cxx_mode_flags) @@ -10,8 +10,11 @@ clangxx = ' '.join([config.clang] + config.cxx_mode_flags) config.substitutions.append((r"%clangxx ", clangxx + ' ')) if config.lto_supported: clangxx_cfi = ' '.join(config.lto_launch + [clangxx] + config.lto_flags + ['-flto -fsanitize=cfi ']) + clangxx_cfi_diag = clangxx_cfi + '-fno-sanitize-trap=cfi -fsanitize-recover=cfi ' config.substitutions.append((r"%clangxx_cfi ", clangxx_cfi)) - config.substitutions.append((r"%clangxx_cfi_diag ", clangxx_cfi + '-fno-sanitize-trap=cfi -fsanitize-recover=cfi ')) + config.substitutions.append((r"%clangxx_cfi_diag ", clangxx_cfi_diag)) + config.substitutions.append((r"%clangxx_cfi_dso ", clangxx_cfi + '-fsanitize-cfi-cross-dso ')) + config.substitutions.append((r"%clangxx_cfi_dso_diag ", clangxx_cfi_diag + '-fsanitize-cfi-cross-dso ')) else: config.unsupported = True diff --git a/test/cfi/multiple-inheritance.cpp b/test/cfi/multiple-inheritance.cpp index e2a9abebb955..a3b2ac56f633 100644 --- a/test/cfi/multiple-inheritance.cpp +++ b/test/cfi/multiple-inheritance.cpp @@ -46,26 +46,8 @@ void C::f() {} void C::g() {} int main(int argc, char **argv) { -#ifdef B32 - break_optimization(new Deriver<A, 0>); - break_optimization(new Deriver<B, 0>); -#endif - -#ifdef B64 - break_optimization(new Deriver<A, 0>); - break_optimization(new Deriver<A, 1>); - break_optimization(new Deriver<B, 0>); - break_optimization(new Deriver<B, 1>); -#endif - -#ifdef BM - break_optimization(new Deriver<A, 0>); - break_optimization(new Deriver<A, 1>); - break_optimization(new Deriver<A, 2>); - break_optimization(new Deriver<B, 0>); - break_optimization(new Deriver<B, 1>); - break_optimization(new Deriver<B, 2>); -#endif + create_derivers<A>(); + create_derivers<B>(); C *c = new C; break_optimization(c); diff --git a/test/cfi/nvcall.cpp b/test/cfi/nvcall.cpp index 04419bd9d855..9d8f5f49f38d 100644 --- a/test/cfi/nvcall.cpp +++ b/test/cfi/nvcall.cpp @@ -40,20 +40,7 @@ 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 + create_derivers<B>(); A *a = new A; break_optimization(a); diff --git a/test/cfi/overwrite.cpp b/test/cfi/overwrite.cpp index a24e628326f3..90f995d87bca 100644 --- a/test/cfi/overwrite.cpp +++ b/test/cfi/overwrite.cpp @@ -39,20 +39,7 @@ void foo() { void *fake_vtable[] = { 0, 0, (void *)&foo }; int main() { -#ifdef B32 - break_optimization(new Deriver<A, 0>); -#endif - -#ifdef B64 - break_optimization(new Deriver<A, 0>); - break_optimization(new Deriver<A, 1>); -#endif - -#ifdef BM - break_optimization(new Deriver<A, 0>); - break_optimization(new Deriver<A, 1>); - break_optimization(new Deriver<A, 2>); -#endif + create_derivers<A>(); A *a = new A; *((void **)a) = fake_vtable + 2; // UB here diff --git a/test/cfi/sibling.cpp b/test/cfi/sibling.cpp index a865cbc0cf6b..9f32302ed5e6 100644 --- a/test/cfi/sibling.cpp +++ b/test/cfi/sibling.cpp @@ -37,20 +37,7 @@ struct C : A { }; 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 + create_derivers<B>(); B *b = new B; break_optimization(b); diff --git a/test/cfi/simple-fail.cpp b/test/cfi/simple-fail.cpp index c7bebb0deccc..92b1322718f8 100644 --- a/test/cfi/simple-fail.cpp +++ b/test/cfi/simple-fail.cpp @@ -74,20 +74,7 @@ struct B { void B::f() {} 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 + create_derivers<B>(); A *a = new A; break_optimization(a); diff --git a/test/cfi/utils.h b/test/cfi/utils.h index 5c290d151069..430359d8c50c 100644 --- a/test/cfi/utils.h +++ b/test/cfi/utils.h @@ -5,49 +5,63 @@ 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. +// 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). Instantiating this class will trigger the instantiation of I +// templates with I virtual tables for classes deriving from T, I-2 of which +// will be of size sizeof(void*) * 5, 1 of which will be of size sizeof(void*) +// * 3, and 1 of which will be of size sizeof(void*) * 9. (Under the MS ABI +// each virtual table will be sizeof(void*) bytes smaller). Each category +// of virtual tables is aligned to a different power of 2, precluding the +// all-ones optimization. As a result, the bit vector for the base class will +// need to contain at least I*2 entries to accommodate all the derived virtual +// tables. template <typename T, unsigned I> -class Deriver : T { +struct Deriver : T { + Deriver() { + break_optimization(new Deriver<T, I-1>); + } 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() {} + virtual void h() {} }; +template <typename T> +struct Deriver<T, 0> : T { + virtual void f() {} + void g() {} +}; + +template <typename T> +struct Deriver<T, 1> : T { + Deriver() { + break_optimization(new Deriver<T, 0>); + } + virtual void f() {} + virtual void g() {} + virtual void h() {} + virtual void i() {} + virtual void j() {} + virtual void k() {} + virtual void l() {} +}; + +// Instantiate enough classes to force CFI checks for type T to use bit +// vectors of size 32 (if B32 defined), 64 (if B64 defined) or >64 (if BM +// defined). +template <typename T> +void create_derivers() { +#ifdef B32 + break_optimization(new Deriver<T, 10>); +#endif + +#ifdef B64 + break_optimization(new Deriver<T, 25>); +#endif + +#ifdef BM + break_optimization(new Deriver<T, 40>); +#endif +} + #endif diff --git a/test/cfi/vdtor.cpp b/test/cfi/vdtor.cpp index fb484ea73308..522d24c2a470 100644 --- a/test/cfi/vdtor.cpp +++ b/test/cfi/vdtor.cpp @@ -37,20 +37,7 @@ struct B { B::~B() {} 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 + create_derivers<B>(); A *a = new A; break_optimization(a); |