diff options
Diffstat (limited to 'test/cfi')
40 files changed, 0 insertions, 2379 deletions
diff --git a/test/cfi/CMakeLists.txt b/test/cfi/CMakeLists.txt deleted file mode 100644 index 4dbbf1759fcc..000000000000 --- a/test/cfi/CMakeLists.txt +++ /dev/null @@ -1,104 +0,0 @@ -set(CFI_TESTSUITES) - -macro (add_cfi_test_suites lld thinlto newpm) - set(suffix) - if (${lld}) - set(suffix ${suffix}-lld) - endif() - if (${thinlto}) - set(suffix ${suffix}-thinlto) - endif() - if (${newpm}) - set(suffix ${suffix}-newpm) - endif() - set(suffix ${suffix}-${CFI_TEST_TARGET_ARCH}) - - set(CFI_TEST_USE_LLD ${lld}) - set(CFI_TEST_USE_THINLTO ${thinlto}) - set(CFI_TEST_USE_NEWPM ${newpm}) - - set(CFI_LIT_TEST_MODE Standalone) - set(CFI_TEST_CONFIG_SUFFIX -standalone${suffix}) - configure_lit_site_cfg( - ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/Standalone${suffix}/lit.site.cfg - ) - list(APPEND CFI_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Standalone${suffix}) - - set(CFI_LIT_TEST_MODE Devirt) - set(CFI_TEST_CONFIG_SUFFIX -devirt${suffix}) - configure_lit_site_cfg( - ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/Devirt${suffix}/lit.site.cfg - ) - list(APPEND CFI_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Devirt${suffix}) -endmacro() - -set(CFI_TEST_ARCH ${CFI_SUPPORTED_ARCH}) -if(APPLE) - darwin_filter_host_archs(CFI_SUPPORTED_ARCH CFI_TEST_ARCH) -endif() - -foreach(arch ${CFI_TEST_ARCH}) - set(CFI_TEST_TARGET_ARCH ${arch}) - get_test_cc_for_arch(${arch} CFI_TEST_TARGET_CC CFI_TEST_TARGET_CFLAGS) - if (APPLE) - # FIXME: enable ThinLTO tests after fixing http://llvm.org/pr32741 - add_cfi_test_suites(False False False) - elseif(WIN32) - add_cfi_test_suites(True False False) - add_cfi_test_suites(True True False) - else() - add_cfi_test_suites(False False False) - add_cfi_test_suites(False True False) - add_cfi_test_suites(False False True) - add_cfi_test_suites(False True True) - if (COMPILER_RT_HAS_LLD AND NOT arch STREQUAL "i386") - add_cfi_test_suites(True False False) - add_cfi_test_suites(True True False) - endif() - endif() -endforeach() - -set(CFI_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -list(APPEND CFI_TEST_DEPS - ubsan - stats -) -if(COMPILER_RT_HAS_CFI) - list(APPEND CFI_TEST_DEPS cfi) -endif() - -if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND CFI_TEST_DEPS - opt - sanstats - ) - if(LLVM_ENABLE_PIC AND LLVM_BINUTILS_INCDIR) - list(APPEND CFI_TEST_DEPS - LLVMgold - ) - endif() - if(APPLE) - list(APPEND CFI_TEST_DEPS - LTO - ) - endif() - if(NOT APPLE AND COMPILER_RT_HAS_LLD) - list(APPEND CFI_TEST_DEPS - lld - ) - endif() -endif() - -add_lit_testsuite(check-cfi "Running the cfi regression tests" - ${CFI_TESTSUITES} - DEPENDS ${CFI_TEST_DEPS}) - -add_lit_target(check-cfi-and-supported "Running the cfi regression tests" - ${CFI_TESTSUITES} - PARAMS check_supported=1 - DEPENDS ${CFI_TEST_DEPS}) - -set_target_properties(check-cfi PROPERTIES FOLDER "Compiler-RT Misc") -set_target_properties(check-cfi-and-supported PROPERTIES FOLDER "Compiler-RT Misc") diff --git a/test/cfi/README.txt b/test/cfi/README.txt deleted file mode 100644 index 6b82f5edc235..000000000000 --- a/test/cfi/README.txt +++ /dev/null @@ -1,8 +0,0 @@ -The tests in this directory use a common convention for exercising the -functionality associated with bit sets of different sizes. When certain -macros are defined the tests instantiate classes that force the bit sets -to be of certain sizes. - -- B32 forces 32-bit bit sets. -- B64 forces 64-bit bit sets. -- BM forces memory bit sets. diff --git a/test/cfi/anon-namespace.cpp b/test/cfi/anon-namespace.cpp deleted file mode 100644 index 2a7ed9c0ac5e..000000000000 --- a/test/cfi/anon-namespace.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// RUN: %clangxx_cfi -c -DTU1 -o %t1.o %s -// RUN: %clangxx_cfi -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp -// RUN: %clangxx_cfi -o %t1 %t1.o %t2.o -// RUN: %expect_crash %run %t1 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 %t2 %t1.o %t2.o -// RUN: %expect_crash %run %t2 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 %t3 %t1.o %t2.o -// RUN: %expect_crash %run %t3 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 %t4 %t1.o %t2.o -// RUN: %expect_crash %run %t4 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 %t5 %t1.o %t2.o -// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s - -// RUN: %clangxx_cfi_diag -c -DTU1 -o %t1.o %s -// RUN: %clangxx_cfi_diag -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp -// RUN: %clangxx_cfi_diag -o %t6 %t1.o %t2.o -// RUN: %run %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s - -// Tests that the CFI mechanism treats classes in the anonymous namespace in -// different translation units as having distinct identities. This is done by -// compiling two translation units TU1 and TU2 containing a class named B in an -// anonymous namespace, and testing that the program crashes if TU2 attempts to -// use a TU1 B as a TU2 B. - -// FIXME: This test should not require that the paths supplied to the compiler -// are different. It currently does so because bitset names have global scope -// so we have to mangle the file path into the bitset name. - -// REQUIRES: cxxabi - -#include <stdio.h> -#include "utils.h" - -struct A { - virtual void f() = 0; -}; - -namespace { - -struct B : A { - virtual void f() {} -}; - -} - -A *mkb(); - -#ifdef TU1 - -A *mkb() { - return new B; -} - -#endif // TU1 - -#ifdef TU2 - -int main() { - create_derivers<B>(); - - A *a = mkb(); - break_optimization(a); - - // CFI: 1 - // NCFI: 1 - fprintf(stderr, "1\n"); - - // CFI-DIAG: runtime error: control flow integrity check for type '(anonymous namespace)::B' failed during base-to-derived cast - // CFI-DIAG-NEXT: note: vtable is of type '{{.*}}anonymous namespace{{.*}}::B' - // CFI-DIAG: runtime error: control flow integrity check for type '(anonymous namespace)::B' failed during virtual call - // CFI-DIAG-NEXT: note: vtable is of type '{{.*}}anonymous namespace{{.*}}::B' - ((B *)a)->f(); // UB here - - // CFI-NOT: {{^2$}} - // NCFI: {{^2$}} - fprintf(stderr, "2\n"); -} - -#endif // TU2 diff --git a/test/cfi/bad-cast.cpp b/test/cfi/bad-cast.cpp deleted file mode 100644 index 1c4f19e9e642..000000000000 --- a/test/cfi/bad-cast.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// RUN: %clangxx_cfi -o %t1 %s -// RUN: %expect_crash %run %t1 a 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t1 b 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t1 c 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %run %t1 d 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t1 e 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t1 f 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %expect_crash %run %t1 g 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %run %t1 h 2>&1 | FileCheck --check-prefix=PASS %s - -// RUN: %clangxx_cfi -DB32 -o %t2 %s -// RUN: %expect_crash %run %t2 a 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t2 b 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t2 c 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %run %t2 d 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t2 e 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t2 f 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %expect_crash %run %t2 g 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %run %t2 h 2>&1 | FileCheck --check-prefix=PASS %s - -// RUN: %clangxx_cfi -DB64 -o %t3 %s -// RUN: %expect_crash %run %t3 a 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t3 b 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t3 c 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %run %t3 d 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t3 e 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t3 f 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %expect_crash %run %t3 g 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %run %t3 h 2>&1 | FileCheck --check-prefix=PASS %s - -// RUN: %clangxx_cfi -DBM -o %t4 %s -// RUN: %expect_crash %run %t4 a 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t4 b 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t4 c 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %run %t4 d 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t4 e 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t4 f 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %expect_crash %run %t4 g 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %run %t4 h 2>&1 | FileCheck --check-prefix=PASS %s - -// RUN: %clangxx_cfi -fsanitize=cfi-cast-strict -o %t5 %s -// RUN: %expect_crash %run %t5 a 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t5 b 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t5 c 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t5 d 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t5 e 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t5 f 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t5 g 2>&1 | FileCheck --check-prefix=FAIL %s -// RUN: %expect_crash %run %t5 h 2>&1 | FileCheck --check-prefix=FAIL %s - -// RUN: %clangxx -o %t6 %s -// RUN: %run %t6 a 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t6 b 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t6 c 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t6 d 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t6 e 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t6 f 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t6 g 2>&1 | FileCheck --check-prefix=PASS %s -// RUN: %run %t6 h 2>&1 | FileCheck --check-prefix=PASS %s - -// RUN: %clangxx_cfi_diag -o %t7 %s -// RUN: %run %t7 a 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s -// RUN: %run %t7 b 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s -// RUN: %run %t7 c 2>&1 | FileCheck --check-prefix=CFI-DIAG-D %s -// RUN: %run %t7 g 2>&1 | FileCheck --check-prefix=CFI-DIAG-U %s - -// Tests that the CFI enforcement detects bad casts. - -// REQUIRES: cxxabi - -#include <stdio.h> -#include "utils.h" - -struct A { - virtual void f(); -}; - -void A::f() {} - -struct B : A { - virtual void f(); -}; - -void B::f() {} - -struct C : A { -}; - -int main(int argc, char **argv) { - create_derivers<B>(); - - B *b = new B; - break_optimization(b); - - // FAIL: 1 - // PASS: 1 - fprintf(stderr, "1\n"); - - A a; - - // CFI-DIAG-D: runtime error: control flow integrity check for type 'B' failed during base-to-derived cast - // CFI-DIAG-D-NEXT: note: vtable is of type '{{(struct )?}}A' - - // CFI-DIAG-U: runtime error: control flow integrity check for type 'B' failed during cast to unrelated type - // CFI-DIAG-U-NEXT: note: vtable is of type '{{(struct )?}}A' - - switch (argv[1][0]) { - case 'a': - static_cast<B *>(&a); // UB - break; - case 'b': - static_cast<B &>(a); // UB - break; - case 'c': - static_cast<B &&>(a); // UB - break; - case 'd': - static_cast<C *>(&a); // UB, strict only - break; - case 'e': - static_cast<C &>(a); // UB, strict only - break; - case 'f': - static_cast<C &&>(a); // UB, strict only - break; - case 'g': - static_cast<B *>(static_cast<void *>(&a)); // Non-UB bad cast - break; - case 'h': - static_cast<C *>(static_cast<void *>(&a)); // Non-UB bad cast, strict only - break; - } - - // FAIL-NOT: {{^2$}} - // PASS: {{^2$}} - fprintf(stderr, "2\n"); -} diff --git a/test/cfi/bad-split.cpp b/test/cfi/bad-split.cpp deleted file mode 100644 index dbbd7ecef0ce..000000000000 --- a/test/cfi/bad-split.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// GlobalSplit used to lose type metadata for classes with virtual bases but no virtual methods. -// RUN: %clangxx_cfi -o %t1 %s && %run %t1 - -// UNSUPPORTED: windows-msvc - -struct Z { -}; - -struct ZZ : public virtual Z { -}; - -struct A : public ZZ { -}; - -struct B : public A { -}; - -int main() { - A* a = new B(); - B *b = (B*)a; -} diff --git a/test/cfi/base-derived-destructor.cpp b/test/cfi/base-derived-destructor.cpp deleted file mode 100644 index 33c7445d55ea..000000000000 --- a/test/cfi/base-derived-destructor.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// RUN: %clangxx_cfi -o %t1 %s -// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB32 -o %t2 %s -// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB64 -o %t3 %s -// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DBM -o %t4 %s -// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O1 -o %t5 %s -// RUN: %expect_crash %run %t5 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O1 -DB32 -o %t6 %s -// RUN: %expect_crash %run %t6 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O1 -DB64 -o %t7 %s -// RUN: %expect_crash %run %t7 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O1 -DBM -o %t8 %s -// RUN: %expect_crash %run %t8 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O2 -o %t9 %s -// RUN: %expect_crash %run %t9 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O2 -DB32 -o %t10 %s -// RUN: %expect_crash %run %t10 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O2 -DB64 -o %t11 %s -// RUN: %expect_crash %run %t11 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O2 -DBM -o %t12 %s -// RUN: %expect_crash %run %t12 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O3 -o %t13 %s -// RUN: %expect_crash %run %t13 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O3 -DB32 -o %t14 %s -// RUN: %expect_crash %run %t14 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O3 -DB64 -o %t15 %s -// RUN: %expect_crash %run %t15 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O3 -DBM -o %t16 %s -// RUN: %expect_crash %run %t16 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi_diag -o %t17 %s -// RUN: %run %t17 2>&1 | FileCheck --check-prefix=CFI-DIAG %s - -// RUN: %clangxx -o %t18 %s -// RUN: %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 deleted file mode 100644 index b651d9be6bd9..000000000000 --- a/test/cfi/create-derivers.test +++ /dev/null @@ -1,21 +0,0 @@ -REQUIRES: asserts - -%% Explicit -flto to override possible -flto=thin in %clangxx_cfi -RUN: %clangxx_cfi -flto -c -o %t1.o %S/simple-fail.cpp -RUN: opt -lowertypetests -debug-only=lowertypetests -o /dev/null %t1.o 2>&1 | FileCheck --check-prefix=B0 %s -B0: {{1B|B@@}}: {{.*}} size 1 - -RUN: %clangxx_cfi -DB32 -flto -c -o %t2.o %S/simple-fail.cpp -RUN: opt -lowertypetests -debug-only=lowertypetests -o /dev/null %t2.o 2>&1 | FileCheck --check-prefix=B32 %s -B32: {{1B|B@@}}: {{.*}} size 2{{3|4}} -B32-NOT: all-ones - -RUN: %clangxx_cfi -DB64 -flto -c -o %t3.o %S/simple-fail.cpp -RUN: opt -lowertypetests -debug-only=lowertypetests -o /dev/null %t3.o 2>&1 | FileCheck --check-prefix=B64 %s -B64: {{1B|B@@}}: {{.*}} size 5{{3|4}} -B64-NOT: all-ones - -RUN: %clangxx_cfi -DBM -flto -c -o %t4.o %S/simple-fail.cpp -RUN: opt -lowertypetests -debug-only=lowertypetests -o /dev/null %t4.o 2>&1 | FileCheck --check-prefix=BM %s -BM: {{1B|B@@}}: {{.*}} size 8{{3|4}} -BM-NOT: all-ones diff --git a/test/cfi/cross-dso-diagnostic.cpp b/test/cfi/cross-dso-diagnostic.cpp deleted file mode 100644 index b8a88722768e..000000000000 --- a/test/cfi/cross-dso-diagnostic.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Check that cross-DSO diagnostics print the names of both modules - -// RUN: %clangxx_cfi_diag -g -DSHARED_LIB -fPIC -shared -o %dynamiclib %s %ld_flags_rpath_so -// RUN: %clangxx_cfi_diag -g -o %t_exe_suffix %s %ld_flags_rpath_exe -// RUN: %t_exe_suffix 2>&1 | FileCheck -DDSONAME=%xdynamiclib_namespec %s - -// UNSUPPORTED: windows-msvc -// REQUIRES: cxxabi - -#include <dlfcn.h> -#include <stdio.h> - -struct S1 { - virtual void f1(); -}; - -#ifdef SHARED_LIB - -void S1::f1() {} - -__attribute__((visibility("default"))) extern "C" -void* dso_symbol() { return new S1(); } - -#else - -int main() { - void* (*fp)(void) = - reinterpret_cast<void*(*)(void)>(dlsym(RTLD_DEFAULT, "dso_symbol")); - if (!fp) { - perror("failed to resolve dso_symbol"); - return 1; - } - - // CHECK: runtime error: control flow integrity check for type 'void *()' failed during indirect function call - // CHECK: dso_symbol defined here - // CHECK: check failed in {{.*}}_exe_suffix, destination function located in {{.*}}[[DSONAME]] - void *S = fp(); // trigger cfi-icall failure - - // CHECK: runtime error: control flow integrity check for type 'S1' failed during cast to unrelated type - // CHECK: invalid vtable - // CHECK: check failed in {{.*}}_exe_suffix, vtable located in {{.*}}[[DSONAME]] - S1 *Scast = reinterpret_cast<S1*>(S); // trigger cfi-unrelated-cast failure - - return 0; -} - -#endif // SHARED_LIB diff --git a/test/cfi/cross-dso/icall/diag.cpp b/test/cfi/cross-dso/icall/diag.cpp deleted file mode 100644 index 579ee835604a..000000000000 --- a/test/cfi/cross-dso/icall/diag.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// Cross-DSO diagnostics. -// The rules are: -// * If the library needs diagnostics, the main executable must request at -// least some diagnostics as well (to link the diagnostic runtime). -// * -fsanitize-trap on the caller side overrides everything. -// * otherwise, the callee decides between trap/recover/norecover. - -// Full-recover. -// RUN: %clangxx_cfi_dso_diag -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso_diag -g %s -o %t %ld_flags_rpath_exe - -// RUN: %t icv 2>&1 | FileCheck %s --check-prefix=ICALL-DIAG --check-prefix=CAST-DIAG \ -// RUN: --check-prefix=VCALL-DIAG --check-prefix=ALL-RECOVER - -// RUN: %t i_v 2>&1 | FileCheck %s --check-prefix=ICALL-DIAG --check-prefix=CAST-NODIAG \ -// RUN: --check-prefix=VCALL-DIAG --check-prefix=ALL-RECOVER - -// RUN: %t _cv 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-DIAG \ -// RUN: --check-prefix=VCALL-DIAG --check-prefix=ALL-RECOVER - -// RUN: %t ic_ 2>&1 | FileCheck %s --check-prefix=ICALL-DIAG --check-prefix=CAST-DIAG \ -// RUN: --check-prefix=VCALL-NODIAG --check-prefix=ALL-RECOVER - -// Trap on icall, no-recover on cast. -// RUN: %clangxx_cfi_dso_diag -fsanitize-trap=cfi-icall -fno-sanitize-recover=cfi-unrelated-cast \ -// RUN: -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso_diag -fsanitize-trap=cfi-icall -fno-sanitize-recover=cfi-unrelated-cast \ -// RUN: -g %s -o %t %ld_flags_rpath_exe - -// RUN: %expect_crash %t icv 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-NODIAG \ -// RUN: --check-prefix=VCALL-NODIAG --check-prefix=ICALL-FATAL - -// RUN: not %t _cv 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-DIAG \ -// RUN: --check-prefix=VCALL-NODIAG --check-prefix=CAST-FATAL - -// RUN: %t __v 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-NODIAG \ -// RUN: --check-prefix=VCALL-DIAG - -// Callee: trap on icall, no-recover on cast. -// Caller: recover on everything. -// The same as in the previous case, behaviour is decided by the callee. -// RUN: %clangxx_cfi_dso_diag -fsanitize-trap=cfi-icall -fno-sanitize-recover=cfi-unrelated-cast \ -// RUN: -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso_diag \ -// RUN: -g %s -o %t %ld_flags_rpath_exe - -// RUN: %expect_crash %t icv 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-NODIAG \ -// RUN: --check-prefix=VCALL-NODIAG --check-prefix=ICALL-FATAL - -// RUN: not %t _cv 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-DIAG \ -// RUN: --check-prefix=VCALL-NODIAG --check-prefix=CAST-FATAL - -// RUN: %t __v 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-NODIAG \ -// RUN: --check-prefix=VCALL-DIAG - -// Caller in trapping mode, callee with full diagnostic+recover. -// Caller wins. -// cfi-nvcall is non-trapping in the main executable to link the diagnostic runtime library. -// RUN: %clangxx_cfi_dso_diag \ -// RUN: -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso -fno-sanitize-trap=cfi-nvcall \ -// RUN: -g %s -o %t %ld_flags_rpath_exe - -// RUN: %expect_crash %t icv 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-NODIAG \ -// RUN: --check-prefix=VCALL-NODIAG --check-prefix=ICALL-FATAL - -// RUN: %expect_crash %t _cv 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-NODIAG \ -// RUN: --check-prefix=VCALL-NODIAG --check-prefix=CAST-FATAL - -// RUN: %expect_crash %t __v 2>&1 | FileCheck %s --check-prefix=ICALL-NODIAG --check-prefix=CAST-NODIAG \ -// RUN: --check-prefix=VCALL-NODIAG --check-prefix=VCALL-FATAL - -// REQUIRES: cxxabi - -#include <assert.h> -#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[]) { - assert(argc == 2); - assert(strlen(argv[1]) == 3); - - // ICALL-FATAL: =0= - // CAST-FATAL: =0= - // VCALL-FATAL: =0= - // ALL-RECOVER: =0= - fprintf(stderr, "=0=\n"); - - void *p; - if (argv[1][0] == 'i') { - // ICALL-DIAG: runtime error: control flow integrity check for type 'void *(int)' failed during indirect function call - // ICALL-DIAG-NEXT: note: create_B() defined here - // ICALL-NODIAG-NOT: runtime error: control flow integrity check {{.*}} during indirect function call - p = ((void *(*)(int))create_B)(42); - } else { - p = create_B(); - } - - // ICALL-FATAL-NOT: =1= - // CAST-FATAL: =1= - // VCALL-FATAL: =1= - // ALL-RECOVER: =1= - fprintf(stderr, "=1=\n"); - - A *a; - if (argv[1][1] == 'c') { - // CAST-DIAG: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type - // CAST-DIAG-NEXT: note: vtable is of type '{{(struct )?}}B' - // CAST-NODIAG-NOT: runtime error: control flow integrity check {{.*}} during cast to unrelated type - a = (A*)p; - } else { - // Invisible to CFI. - memcpy(&a, &p, sizeof(a)); - } - - // ICALL-FATAL-NOT: =2= - // CAST-FATAL-NOT: =2= - // VCALL-FATAL: =2= - // ALL-RECOVER: =2= - fprintf(stderr, "=2=\n"); - - // VCALL-DIAG: runtime error: control flow integrity check for type 'A' failed during virtual call - // VCALL-DIAG-NEXT: note: vtable is of type '{{(struct )?}}B' - // VCALL-NODIAG-NOT: runtime error: control flow integrity check {{.*}} during virtual call - if (argv[1][2] == 'v') { - a->f(); // UB here - } - - // ICALL-FATAL-NOT: =3= - // CAST-FATAL-NOT: =3= - // VCALL-FATAL-NOT: =3= - // ALL-RECOVER: =3= - fprintf(stderr, "=3=\n"); - -} -#endif diff --git a/test/cfi/cross-dso/icall/dlopen.cpp b/test/cfi/cross-dso/icall/dlopen.cpp deleted file mode 100644 index c9674c3fb412..000000000000 --- a/test/cfi/cross-dso/icall/dlopen.cpp +++ /dev/null @@ -1,149 +0,0 @@ -// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %t1-so.so -// RUN: %clangxx_cfi_dso %s -o %t1 -// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %t1 cast 2>&1 | FileCheck --check-prefix=CFI-CAST %s -// RUN: %expect_crash %t1 dlclose 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 -// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %t2 cast 2>&1 | FileCheck --check-prefix=CFI-CAST %s -// RUN: %expect_crash %t2 dlclose 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 -// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %t3 cast 2>&1 | FileCheck --check-prefix=CFI-CAST %s -// RUN: %expect_crash %t3 dlclose 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 -// RUN: %expect_crash %t4 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %t4 cast 2>&1 | FileCheck --check-prefix=CFI-CAST %s -// RUN: %expect_crash %t4 dlclose 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx -g -DBM -DSHARED_LIB -DNOCFI %s -fPIC -shared -o %t5-so.so -// RUN: %clangxx -g -DBM -DNOCFI %s -ldl -o %t5 -// RUN: %t5 2>&1 | FileCheck --check-prefix=NCFI %s -// RUN: %t5 cast 2>&1 | FileCheck --check-prefix=NCFI %s -// RUN: %t5 dlclose 2>&1 | FileCheck --check-prefix=NCFI %s - -// Test that calls to uninstrumented library are unchecked. -// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %t6-so.so -// RUN: %clangxx_cfi_dso -DBM %s -o %t6 -// RUN: %t6 2>&1 | FileCheck --check-prefix=NCFI %s -// RUN: %t6 cast 2>&1 | FileCheck --check-prefix=NCFI %s - -// Call-after-dlclose is checked on the caller side. -// RUN: %expect_crash %t6 dlclose 2>&1 | FileCheck --check-prefix=CFI %s - -// Tests calls into dlopen-ed library. -// REQUIRES: cxxabi - -#include <assert.h> -#include <dlfcn.h> -#include <stdio.h> -#include <stdint.h> -#include <string.h> -#include <sys/mman.h> - -#include <string> - -struct A { - virtual void f(); -}; - -#ifdef SHARED_LIB - -#include "../../utils.h" -struct B { - virtual void f(); -}; -void B::f() {} - -extern "C" void *create_B() { - create_derivers<B>(); - return (void *)(new B()); -} - -extern "C" __attribute__((aligned(4096))) void do_nothing() {} - -#else - -void A::f() {} - -static const int kCodeAlign = 4096; -static const int kCodeSize = 4096; -static char saved_code[kCodeSize]; -static char *real_start; - -static void save_code(char *p) { - real_start = (char *)(((uintptr_t)p) & ~(kCodeAlign - 1)); - memcpy(saved_code, real_start, kCodeSize); -} - -static void restore_code() { - char *code = - (char *)mmap(real_start, kCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0); - assert(code == real_start); - memcpy(code, saved_code, kCodeSize); - __builtin___clear_cache(code, code + kCodeSize); -} - -int main(int argc, char *argv[]) { - const bool test_cast = argc > 1 && strcmp(argv[1], "cast") == 0; - const bool test_dlclose = argc > 1 && strcmp(argv[1], "dlclose") == 0; - - std::string name = std::string(argv[0]) + "-so.so"; - void *handle = dlopen(name.c_str(), RTLD_NOW); - assert(handle); - void *(*create_B)() = (void *(*)())dlsym(handle, "create_B"); - assert(create_B); - - void *p = create_B(); - A *a; - - // CFI: =0= - // CFI-CAST: =0= - // NCFI: =0= - fprintf(stderr, "=0=\n"); - - if (test_cast) { - // 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"); - - if (test_dlclose) { - // Imitate an attacker sneaking in an executable page where a dlclose()d - // library was loaded. This needs to pass w/o CFI, so for the testing - // purpose, we just copy the bytes of a "void f() {}" function back and - // forth. - void (*do_nothing)() = (void (*)())dlsym(handle, "do_nothing"); - assert(do_nothing); - save_code((char *)do_nothing); - - int res = dlclose(handle); - assert(res == 0); - - restore_code(); - - do_nothing(); // UB here - } else { - 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/icall/icall-from-dso.cpp b/test/cfi/cross-dso/icall/icall-from-dso.cpp deleted file mode 100644 index 125e030b5063..000000000000 --- a/test/cfi/cross-dso/icall/icall-from-dso.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso %s -o %t %ld_flags_rpath_exe && %expect_crash %t 2>&1 | FileCheck %s - -// RUN: %clangxx_cfi_dso_diag -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso_diag -g %s -o %t %ld_flags_rpath_exe && %t 2>&1 | FileCheck %s --check-prefix=CFI-DIAG - -#include <stdio.h> - -#ifdef SHARED_LIB -void g(); -void f() { - // CHECK-DIAG: =1= - // CHECK: =1= - fprintf(stderr, "=1=\n"); - ((void (*)(void))g)(); - // CHECK-DIAG: =2= - // CHECK: =2= - fprintf(stderr, "=2=\n"); - // CFI-DIAG: runtime error: control flow integrity check for type 'void (int)' failed during indirect function call - // CFI-DIAG-NEXT: note: g() defined here - ((void (*)(int))g)(42); // UB here - // CHECK-DIAG: =3= - // 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 deleted file mode 100644 index 9e9bfd07ed59..000000000000 --- a/test/cfi/cross-dso/icall/icall.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso %s -o %t %ld_flags_rpath_exe && %expect_crash %t 2>&1 | FileCheck %s - -// RUN: %clangxx_cfi_dso_diag -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso_diag -g %s -o %t %ld_flags_rpath_exe && %t 2>&1 | FileCheck %s --check-prefix=CFI-DIAG - -#include <stdio.h> - -#ifdef SHARED_LIB -void f() { -} -#else -void f(); -int main() { - // CHECK-DIAG: =1= - // CHECK: =1= - fprintf(stderr, "=1=\n"); - ((void (*)(void))f)(); - // CHECK-DIAG: =2= - // CHECK: =2= - fprintf(stderr, "=2=\n"); - // CFI-DIAG: runtime error: control flow integrity check for type 'void (int)' failed during indirect function call - // CFI-DIAG-NEXT: note: f() defined here - ((void (*)(int))f)(42); // UB here - // CHECK-DIAG: =3= - // 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 deleted file mode 100644 index db08765a2bb2..000000000000 --- a/test/cfi/cross-dso/icall/lit.local.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# 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 deleted file mode 100644 index 245d434faed9..000000000000 --- a/test/cfi/cross-dso/lit.local.cfg +++ /dev/null @@ -1,13 +0,0 @@ -def getRoot(config): - if not config.parent: - return config - return getRoot(config.parent) - -root = getRoot(config) - -if root.host_os not in ['Linux', 'FreeBSD', 'NetBSD']: - config.unsupported = True - -# Android O (API level 26) has support for cross-dso cfi in libdl.so. -if config.android and 'android-26' not in config.available_features: - config.unsupported = True diff --git a/test/cfi/cross-dso/shadow_is_read_only.cpp b/test/cfi/cross-dso/shadow_is_read_only.cpp deleted file mode 100644 index 8811506afe85..000000000000 --- a/test/cfi/cross-dso/shadow_is_read_only.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// RUN: %clangxx_cfi_dso -std=c++11 -g -DSHARED_LIB %s -fPIC -shared -o %t-cfi-so.so -// RUN: %clangxx -std=c++11 -g -DSHARED_LIB %s -fPIC -shared -o %t-nocfi-so.so -// RUN: %clangxx_cfi_dso -std=c++11 -g %s -o %t - -// RUN: %expect_crash %t start 2>&1 | FileCheck %s -// RUN: %expect_crash %t mmap 2>&1 | FileCheck %s -// RUN: %expect_crash %t dlopen %t-cfi-so.so 2>&1 | FileCheck %s -// RUN: %expect_crash %t dlclose %t-cfi-so.so 2>&1 | FileCheck %s -// RUN: %expect_crash %t dlopen %t-nocfi-so.so 2>&1 | FileCheck %s -// RUN: %expect_crash %t dlclose %t-nocfi-so.so 2>&1 | FileCheck %s - -// Tests that shadow is read-only most of the time. -// REQUIRES: cxxabi - -// Uses private API that is not available on Android. -// UNSUPPORTED: android - -#include <assert.h> -#include <dlfcn.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> - -struct A { - virtual void f(); -}; - -#ifdef SHARED_LIB - -void A::f() {} - -extern "C" A *create_A() { return new A(); } - -#else - -constexpr unsigned kShadowGranularity = 12; - -namespace __cfi { -uintptr_t GetShadow(); -} - -void write_shadow(void *ptr) { - uintptr_t base = __cfi::GetShadow(); - uint16_t *s = - (uint16_t *)(base + (((uintptr_t)ptr >> kShadowGranularity) << 1)); - fprintf(stderr, "going to crash\n"); - // CHECK: going to crash - *s = 42; - fprintf(stderr, "did not crash\n"); - // CHECK-NOT: did not crash - exit(1); -} - -int main(int argc, char *argv[]) { - assert(argc > 1); - const bool test_mmap = strcmp(argv[1], "mmap") == 0; - const bool test_start = strcmp(argv[1], "start") == 0; - const bool test_dlopen = strcmp(argv[1], "dlopen") == 0; - const bool test_dlclose = strcmp(argv[1], "dlclose") == 0; - const char *lib = argc > 2 ? argv[2] : nullptr; - - if (test_start) - write_shadow((void *)&main); - - if (test_mmap) { - void *p = mmap(nullptr, 1 << 20, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); - assert(p != MAP_FAILED); - write_shadow((char *)p + 100); - } else { - void *handle = dlopen(lib, RTLD_NOW); - assert(handle); - void *create_A = dlsym(handle, "create_A"); - assert(create_A); - - if (test_dlopen) - write_shadow(create_A); - - int res = dlclose(handle); - assert(res == 0); - - if (test_dlclose) - write_shadow(create_A); - } -} -#endif diff --git a/test/cfi/cross-dso/simple-fail.cpp b/test/cfi/cross-dso/simple-fail.cpp deleted file mode 100644 index 93503ebe5b36..000000000000 --- a/test/cfi/cross-dso/simple-fail.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso %s -o %t %ld_flags_rpath_exe -// RUN: %expect_crash %t 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %t x 2>&1 | FileCheck --check-prefix=CFI-CAST %s - -// RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso -DB32 %s -o %t %ld_flags_rpath_exe -// RUN: %expect_crash %t 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %t x 2>&1 | FileCheck --check-prefix=CFI-CAST %s - -// RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso -DB64 %s -o %t %ld_flags_rpath_exe -// RUN: %expect_crash %t 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %t x 2>&1 | FileCheck --check-prefix=CFI-CAST %s - -// RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso -DBM %s -o %t %ld_flags_rpath_exe -// RUN: %expect_crash %t 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %t x 2>&1 | FileCheck --check-prefix=CFI-CAST %s - -// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx -DBM %s -o %t %ld_flags_rpath_exe -// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s -// RUN: %t x 2>&1 | FileCheck --check-prefix=NCFI %s - -// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso -DBM %s -o %t %ld_flags_rpath_exe -// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s -// RUN: %t x 2>&1 | FileCheck --check-prefix=NCFI %s - -// RUN: %clangxx_cfi_dso_diag -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso_diag %s -o %t %ld_flags_rpath_exe -// RUN: %t 2>&1 | FileCheck --check-prefix=CFI-DIAG-CALL %s -// RUN: %t x 2>&1 | FileCheck --check-prefix=CFI-DIAG-CALL --check-prefix=CFI-DIAG-CAST %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. - // CFI-DIAG-CAST: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type - // CFI-DIAG-CAST-NEXT: note: vtable is of type '{{(struct )?}}B' - 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"); - - // CFI-DIAG-CALL: runtime error: control flow integrity check for type 'A' failed during virtual call - // CFI-DIAG-CALL-NEXT: note: vtable is of type '{{(struct )?}}B' - 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 deleted file mode 100644 index 6ce64713a6e2..000000000000 --- a/test/cfi/cross-dso/simple-pass.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// RUN: %clangxx_cfi_dso -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso -g %s -o %t %ld_flags_rpath_exe -// RUN: %t 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi_dso -DB32 -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso -DB32 %s -o %t %ld_flags_rpath_exe -// RUN: %t 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi_dso -DB64 -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso -DB64 %s -o %t %ld_flags_rpath_exe -// RUN: %t 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi_dso -DBM -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_dso -DBM %s -o %t %ld_flags_rpath_exe -// RUN: %t 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx -DBM -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx -DBM %s -o %t %ld_flags_rpath_exe -// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s -// RUN: %t 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/cross-dso/stats.cpp b/test/cfi/cross-dso/stats.cpp deleted file mode 100644 index 09a7217bf066..000000000000 --- a/test/cfi/cross-dso/stats.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// RUN: %clangxx_cfi_dso -DSHARED_LIB -fPIC -g -fsanitize-stats -shared -o %t.so %s -// RUN: %clangxx_cfi_dso -g -fsanitize-stats -o %t %s %t.so -// RUN: env SANITIZER_STATS_PATH=%t.stats %t -// RUN: sanstats %t.stats | FileCheck %s - -// CFI-icall is not implemented in thinlto mode => ".cfi" suffixes are missing -// in sanstats output. - -// FIXME: %t.stats must be transferred from device to host for this to work on Android. -// XFAIL: android - -struct ABase {}; - -struct A : ABase { - virtual void vf() {} - void nvf() {} -}; - -extern "C" void vcall(A *a); -extern "C" void nvcall(A *a); - -#ifdef SHARED_LIB - -extern "C" __attribute__((noinline)) void vcall(A *a) { - // CHECK: stats.cpp:[[@LINE+1]] vcall.cfi cfi-vcall 37 - a->vf(); -} - -extern "C" __attribute__((noinline)) void nvcall(A *a) { - // CHECK: stats.cpp:[[@LINE+1]] nvcall.cfi cfi-nvcall 51 - a->nvf(); -} - -#else - -extern "C" __attribute__((noinline)) A *dcast(A *a) { - // CHECK: stats.cpp:[[@LINE+1]] dcast.cfi cfi-derived-cast 24 - return (A *)(ABase *)a; -} - -extern "C" __attribute__((noinline)) A *ucast(A *a) { - // CHECK: stats.cpp:[[@LINE+1]] ucast.cfi cfi-unrelated-cast 81 - return (A *)(char *)a; -} - -extern "C" __attribute__((noinline)) void unreachable(A *a) { - // CHECK-NOT: unreachable - a->vf(); -} - -int main() { - A a; - for (unsigned i = 0; i != 37; ++i) - vcall(&a); - for (unsigned i = 0; i != 51; ++i) - nvcall(&a); - for (unsigned i = 0; i != 24; ++i) - dcast(&a); - for (unsigned i = 0; i != 81; ++i) - ucast(&a); - for (unsigned i = 0; i != 0; ++i) - unreachable(&a); -} - -#endif diff --git a/test/cfi/cross-dso/target_out_of_bounds.cpp b/test/cfi/cross-dso/target_out_of_bounds.cpp deleted file mode 100644 index 6353f030a6ac..000000000000 --- a/test/cfi/cross-dso/target_out_of_bounds.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// RUN: %clangxx_cfi_dso_diag -std=c++11 %s -o %t -// RUN: %t zero 2>&1 | FileCheck --check-prefix=CHECK-ZERO %s -// RUN: %t unaddressable 2>&1 | FileCheck --check-prefix=CHECK-UNADDR %s -// RUN: %t 2>&1 | FileCheck --check-prefix=CHECK-TYPEINFO %s - -// RUN: %clangxx_cfi_diag -std=c++11 %s -o %t2 -// RUN: %t2 zero 2>&1 | FileCheck --check-prefix=CHECK-ZERO %s -// RUN: %t2 unaddressable 2>&1 | FileCheck --check-prefix=CHECK-UNADDR %s -// RUN: %t2 2>&1 | FileCheck --check-prefix=CHECK-TYPEINFO %s - -// REQUIRES: cxxabi - -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> - -struct A { - virtual void f(); -}; - -void A::f() {} - -int main(int argc, char *argv[]) { - char *volatile p = reinterpret_cast<char *>(new A()); - if (argc > 1 && strcmp(argv[1], "unaddressable") == 0) { - void *vtable = mmap(nullptr, 4096, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); - // Create an object with a vtable in an unaddressable memory region. - *(uintptr_t *)p = (uintptr_t)vtable + 64; - // CHECK-UNADDR: runtime error: control flow integrity check for type 'A' failed during cast - // CHECK-UNADDR: note: invalid vtable - // CHECK-UNADDR: <memory cannot be printed> - // CHECK-UNADDR: runtime error: control flow integrity check for type 'A' failed during cast - // CHECK-UNADDR: note: invalid vtable - // CHECK-UNADDR: <memory cannot be printed> - } else if (argc > 1 && strcmp(argv[1], "zero") == 0) { - // Create an object with a vtable outside of any known DSO, but still in an - // addressable area. - void *vtable = calloc(1, 128); - *(uintptr_t *)p = (uintptr_t)vtable + 64; - // CHECK-ZERO: runtime error: control flow integrity check for type 'A' failed during cast - // CHECK-ZERO: note: invalid vtable - // CHECK-ZERO: 00 00 00 00 00 00 00 00 - // CHECK-ZERO: runtime error: control flow integrity check for type 'A' failed during cast - // CHECK-ZERO: note: invalid vtable - // CHECK-ZERO: 00 00 00 00 00 00 00 00 - } else { - // Create an object with a seemingly fine vtable, but with an unaddressable - // typeinfo pointer. - void *vtable = calloc(1, 128); - memset(vtable, 0xFE, 128); - *(uintptr_t *)p = (uintptr_t)vtable + 64; - // CHECK-TYPEINFO: runtime error: control flow integrity check for type 'A' failed during cast - // CHECK-TYPEINFO: note: invalid vtable - // CHECK-TYPEINFO: fe fe fe fe fe fe fe fe - // CHECK-TYPEINFO: runtime error: control flow integrity check for type 'A' failed during cast - // CHECK-TYPEINFO: note: invalid vtable - // CHECK-TYPEINFO: fe fe fe fe fe fe fe fe - } - - A *volatile pa = reinterpret_cast<A *>(p); - pa = reinterpret_cast<A *>(p); -} diff --git a/test/cfi/cross-dso/util/cfi_stubs.h b/test/cfi/cross-dso/util/cfi_stubs.h deleted file mode 100644 index b742074f037e..000000000000 --- a/test/cfi/cross-dso/util/cfi_stubs.h +++ /dev/null @@ -1,30 +0,0 @@ -// This is a hack to access CFI interface that Android has in libdl.so on -// device, but not in the NDK. -#include <dlfcn.h> -#include <stdint.h> -#include <stdlib.h> - -typedef void (*cfi_slowpath_ty)(uint64_t, void *); -typedef void (*cfi_slowpath_diag_ty)(uint64_t, void *, void *); - -static cfi_slowpath_ty cfi_slowpath; -static cfi_slowpath_diag_ty cfi_slowpath_diag; - -__attribute__((constructor(0), no_sanitize("cfi"))) static void init() { - cfi_slowpath = (cfi_slowpath_ty)dlsym(RTLD_NEXT, "__cfi_slowpath"); - cfi_slowpath_diag = - (cfi_slowpath_diag_ty)dlsym(RTLD_NEXT, "__cfi_slowpath_diag"); - if (!cfi_slowpath || !cfi_slowpath_diag) abort(); -} - -extern "C" { -__attribute__((visibility("hidden"), no_sanitize("cfi"))) void __cfi_slowpath( - uint64_t Type, void *Addr) { - cfi_slowpath(Type, Addr); -} - -__attribute__((visibility("hidden"), no_sanitize("cfi"))) void -__cfi_slowpath_diag(uint64_t Type, void *Addr, void *Diag) { - cfi_slowpath_diag(Type, Addr, Diag); -} -} diff --git a/test/cfi/icall/bad-signature.c b/test/cfi/icall/bad-signature.c deleted file mode 100644 index 183e62738bb2..000000000000 --- a/test/cfi/icall/bad-signature.c +++ /dev/null @@ -1,27 +0,0 @@ -// RUN: %clang -o %t1 %s -// RUN: %t1 2>&1 | FileCheck --check-prefix=NCFI %s - -// RUN: %clang_cfi -o %t2 %s -// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clang_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 deleted file mode 100644 index 27c447878164..000000000000 --- a/test/cfi/icall/external-call.c +++ /dev/null @@ -1,28 +0,0 @@ -// RUN: %clang_cfi -lm -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. -// The test passes on i386 Darwin and fails on x86_64, hence unsupported instead of xfail. -// UNSUPPORTED: 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 deleted file mode 100644 index db08765a2bb2..000000000000 --- a/test/cfi/icall/lit.local.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# 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/icall/weak.c b/test/cfi/icall/weak.c deleted file mode 100644 index 40739911109c..000000000000 --- a/test/cfi/icall/weak.c +++ /dev/null @@ -1,15 +0,0 @@ -// Test that weak symbols stay weak. -// RUN: %clang_cfi -lm -o %t1 %s && %t1 -// XFAIL: darwin - -__attribute__((weak)) void does_not_exist(void); - -__attribute__((noinline)) -void foo(void (*p)(void)) { - p(); -} - -int main(int argc, char **argv) { - if (does_not_exist) - foo(does_not_exist); -} diff --git a/test/cfi/icall/wrong-signature-mixed-lto.c b/test/cfi/icall/wrong-signature-mixed-lto.c deleted file mode 100644 index 0e5fb8508c90..000000000000 --- a/test/cfi/icall/wrong-signature-mixed-lto.c +++ /dev/null @@ -1,41 +0,0 @@ -// Test that the checking is done with the actual type of f() even when the -// calling module has an incorrect declaration. Test a mix of lto types. -// -// -flto below overrides -flto=thin in %clang_cfi -// RUN: %clang_cfi %s -DMODULE_A -c -o %t1_a.o -// RUN: %clang_cfi %s -DMODULE_B -c -o %t1_b.o -flto -// RUN: %clang_cfi %t1_a.o %t1_b.o -o %t1 -// RUN: %expect_crash %t1 2>&1 | FileCheck --check-prefix=CFI %s -// -// RUN: %clang_cfi %s -DMODULE_A -c -o %t2_a.o -flto -// RUN: %clang_cfi %s -DMODULE_B -c -o %t2_b.o -// RUN: %clang_cfi %t2_a.o %t2_b.o -o %t2 -// RUN: %expect_crash %t2 2>&1 | FileCheck --check-prefix=CFI %s -// -// RUN: %clang_cfi %s -DMODULE_A -c -o %t3_a.o -// RUN: %clang_cfi %s -DMODULE_B -c -o %t3_b.o -// RUN: %clang_cfi %t3_a.o %t3_b.o -o %t3 -// RUN: %expect_crash %t3 2>&1 | FileCheck --check-prefix=CFI %s -// -// REQUIRES: thinlto - -#include <stdio.h> - -#if defined(MODULE_B) -int f() { - return 42; -} -#elif defined(MODULE_A) -void f(); - -int main() { - // CFI: 1 - fprintf(stderr, "1\n"); - - void (*volatile p)() = &f; - p(); - - // CFI-NOT: 2 - fprintf(stderr, "2\n"); -} -#endif diff --git a/test/cfi/lit.cfg b/test/cfi/lit.cfg deleted file mode 100644 index cbffe6ea8a65..000000000000 --- a/test/cfi/lit.cfg +++ /dev/null @@ -1,46 +0,0 @@ -import lit.formats -import os - -config.name = 'cfi' + config.name_suffix -config.suffixes = ['.c', '.cpp', '.test'] -config.test_source_root = os.path.dirname(__file__) - -def build_invocation(compile_flags): - return " " + " ".join([config.clang] + compile_flags) + " " - -clang = build_invocation([config.target_cflags]) -clangxx = build_invocation([config.target_cflags] + config.cxx_mode_flags) - -config.substitutions.append((r"%clang ", clang + ' ')) -config.substitutions.append((r"%clangxx ", clangxx + ' ')) -if config.lto_supported: - clang_cfi = clang + '-fsanitize=cfi ' - - if config.cfi_lit_test_mode == "Devirt": - config.available_features.add('devirt') - clang_cfi += '-fwhole-program-vtables ' - config.substitutions.append((r"%expect_crash_unless_devirt ", "")) - else: - config.substitutions.append((r"%expect_crash_unless_devirt ", config.expect_crash)) - - cxx = ' '.join(config.cxx_mode_flags) + ' ' - diag = '-fno-sanitize-trap=cfi -fsanitize-recover=cfi ' - non_dso = '-fvisibility=hidden ' - dso = '-fsanitize-cfi-cross-dso -fvisibility=default ' - if config.android: - dso += '-include ' + config.test_source_root + '/cross-dso/util/cfi_stubs.h ' - config.substitutions.append((r"%clang_cfi ", clang_cfi + non_dso)) - config.substitutions.append((r"%clangxx_cfi ", clang_cfi + cxx + non_dso)) - config.substitutions.append((r"%clang_cfi_diag ", clang_cfi + non_dso + diag)) - config.substitutions.append((r"%clangxx_cfi_diag ", clang_cfi + cxx + non_dso + diag)) - config.substitutions.append((r"%clangxx_cfi_dso ", clang_cfi + cxx + dso)) - config.substitutions.append((r"%clangxx_cfi_dso_diag ", clang_cfi + cxx + dso + diag)) - config.substitutions.append((r"%debug_info_flags", ' '.join(config.debug_info_flags))) -else: - config.unsupported = True - -if config.default_sanitizer_opts: - config.environment['UBSAN_OPTIONS'] = ':'.join(config.default_sanitizer_opts) - -if lit_config.params.get('check_supported', None) and config.unsupported: - raise BaseException("Tests unsupported") diff --git a/test/cfi/lit.site.cfg.in b/test/cfi/lit.site.cfg.in deleted file mode 100644 index a735e8812acd..000000000000 --- a/test/cfi/lit.site.cfg.in +++ /dev/null @@ -1,13 +0,0 @@ -@LIT_SITE_CFG_IN_HEADER@ - -config.name_suffix = "@CFI_TEST_CONFIG_SUFFIX@" -config.cfi_lit_test_mode = "@CFI_LIT_TEST_MODE@" -config.target_arch = "@CFI_TEST_TARGET_ARCH@" -config.target_cflags = "@CFI_TEST_TARGET_CFLAGS@" -config.use_lld = @CFI_TEST_USE_LLD@ -config.use_lto = True # CFI *requires* LTO. -config.use_thinlto = @CFI_TEST_USE_THINLTO@ -config.use_newpm = @CFI_TEST_USE_NEWPM@ - -lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") -lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") diff --git a/test/cfi/mfcall.cpp b/test/cfi/mfcall.cpp deleted file mode 100644 index 4d561d943f41..000000000000 --- a/test/cfi/mfcall.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// UNSUPPORTED: windows-msvc - -// RUN: %clangxx_cfi -o %t %s -// RUN: %expect_crash %run %t a -// RUN: %expect_crash %run %t b -// RUN: %expect_crash %run %t c -// RUN: %expect_crash %run %t d -// RUN: %expect_crash %run %t e -// RUN: %run %t f -// RUN: %run %t g - -// RUN: %clangxx_cfi_diag -o %t2 %s -// RUN: %run %t2 a 2>&1 | FileCheck --check-prefix=A %s -// RUN: %run %t2 b 2>&1 | FileCheck --check-prefix=B %s -// RUN: %run %t2 c 2>&1 | FileCheck --check-prefix=C %s -// RUN: %run %t2 d 2>&1 | FileCheck --check-prefix=D %s -// RUN: %run %t2 e 2>&1 | FileCheck --check-prefix=E %s - -#include <assert.h> -#include <string.h> - -struct SBase1 { - void b1() {} -}; - -struct SBase2 { - void b2() {} -}; - -struct S : SBase1, SBase2 { - void f1() {} - int f2() { return 1; } - virtual void g1() {} - virtual int g2() { return 1; } - virtual int g3() { return 1; } -}; - -struct T { - void f1() {} - int f2() { return 2; } - virtual void g1() {} - virtual int g2() { return 2; } - virtual void g3() {} -}; - -typedef void (S::*S_void)(); - -typedef int (S::*S_int)(); -typedef int (T::*T_int)(); - -template <typename To, typename From> -To bitcast(From f) { - assert(sizeof(To) == sizeof(From)); - To t; - memcpy(&t, &f, sizeof(f)); - return t; -} - -int main(int argc, char **argv) { - S s; - T t; - - switch (argv[1][0]) { - case 'a': - // A: runtime error: control flow integrity check for type 'int (S::*)()' failed during non-virtual pointer to member function call - // A: note: S::f1() defined here - (s.*bitcast<S_int>(&S::f1))(); - break; - case 'b': - // B: runtime error: control flow integrity check for type 'int (T::*)()' failed during non-virtual pointer to member function call - // B: note: S::f2() defined here - (t.*bitcast<T_int>(&S::f2))(); - break; - case 'c': - // C: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual pointer to member function call - // C: note: vtable is of type 'S' - (s.*bitcast<S_int>(&S::g1))(); - break; - case 'd': - // D: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual pointer to member function call - // D: note: vtable is of type 'T' - (reinterpret_cast<S &>(t).*&S::g2)(); - break; - case 'e': - // E: runtime error: control flow integrity check for type 'void (S::*)()' failed during virtual pointer to member function call - // E: note: vtable is of type 'S' - (s.*bitcast<S_void>(&T::g3))(); - break; - case 'f': - (s.*&SBase1::b1)(); - break; - case 'g': - (s.*&SBase2::b2)(); - break; - } -} diff --git a/test/cfi/multiple-inheritance.cpp b/test/cfi/multiple-inheritance.cpp deleted file mode 100644 index b8520d8b08b1..000000000000 --- a/test/cfi/multiple-inheritance.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// RUN: %clangxx_cfi -o %t1 %s -// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %run %t1 x 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB32 -o %t2 %s -// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %run %t2 x 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB64 -o %t3 %s -// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %run %t3 x 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DBM -o %t4 %s -// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s -// RUN: %expect_crash %run %t4 x 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx -o %t5 %s -// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s -// RUN: %run %t5 x 2>&1 | FileCheck --check-prefix=NCFI %s - -// RUN: %clangxx_cfi_diag -o %t6 %s -// RUN: %run %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG2 %s -// RUN: %run %t6 x 2>&1 | FileCheck --check-prefix=CFI-DIAG1 %s - -// Tests that the CFI mechanism is sensitive to multiple inheritance and only -// permits calls via virtual tables for the correct base class. - -// REQUIRES: cxxabi - -#include <stdio.h> -#include "utils.h" - -struct A { - virtual void f() = 0; -}; - -struct B { - virtual void g() = 0; -}; - -struct C : A, B { - virtual void f(), g(); -}; - -void C::f() {} -void C::g() {} - -int main(int argc, char **argv) { - create_derivers<A>(); - create_derivers<B>(); - - C *c = new C; - break_optimization(c); - - // CFI: 1 - // NCFI: 1 - fprintf(stderr, "1\n"); - - if (argc > 1) { - A *a = c; - // CFI-DIAG1: runtime error: control flow integrity check for type 'B' failed during cast to unrelated type - // CFI-DIAG1-NEXT: note: vtable is of type '{{(struct )?}}C' - ((B *)a)->g(); // UB here - } else { - // CFI-DIAG2: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type - // CFI-DIAG2-NEXT: note: vtable is of type '{{(struct )?}}C' - B *b = c; - ((A *)b)->f(); // UB here - } - - // CFI-NOT: {{^2$}} - // NCFI: {{^2$}} - fprintf(stderr, "2\n"); -} diff --git a/test/cfi/nvcall.cpp b/test/cfi/nvcall.cpp deleted file mode 100644 index b61adb1fed06..000000000000 --- a/test/cfi/nvcall.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// RUN: %clangxx_cfi -o %t1 %s -// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB32 -o %t2 %s -// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB64 -o %t3 %s -// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DBM -o %t4 %s -// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx -o %t5 %s -// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s - -// RUN: %clangxx_cfi_diag -o %t6 %s -// RUN: %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() { - create_derivers<B>(); - - 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"); -} diff --git a/test/cfi/overwrite.cpp b/test/cfi/overwrite.cpp deleted file mode 100644 index 7d7ad1c77f0c..000000000000 --- a/test/cfi/overwrite.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// RUN: %clangxx_cfi -o %t1 %s -// RUN: %expect_crash_unless_devirt %run %t1 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB32 -o %t2 %s -// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB64 -o %t3 %s -// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DBM -o %t4 %s -// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx -o %t5 %s -// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s - -// RUN: %clangxx_cfi_diag -o %t6 %s -// RUN: %run %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s - -// Tests that the CFI mechanism crashes the program when a virtual table is -// replaced with a compatible table of function pointers that does not belong to -// any class, by manually overwriting the virtual table of an object and -// attempting to make a call through it. - -// REQUIRES: cxxabi - -#include <stdio.h> -#include "utils.h" - -struct A { - virtual void f(); -}; - -void A::f() {} - -void foo() { - fprintf(stderr, "foo\n"); -} - -void *fake_vtable[] = { 0, 0, (void *)&foo }; - -int main() { - create_derivers<A>(); - - A *a = new A; - *((void **)a) = fake_vtable + 2; // UB here - break_optimization(a); - - // CFI: 1 - // NCFI: 1 - fprintf(stderr, "1\n"); - - // CFI-NOT: foo - // NCFI: foo - // CFI-DIAG: runtime error: control flow integrity check for type 'A' failed during virtual call - // CFI-DIAG-NEXT: note: invalid vtable - a->f(); - - // We don't check for the absence of a 2 here because under devirtualization - // our virtual call may be devirtualized and we will proceed with execution - // rather than crashing. - - // NCFI: {{^2$}} - fprintf(stderr, "2\n"); -} diff --git a/test/cfi/sibling.cpp b/test/cfi/sibling.cpp deleted file mode 100644 index fb6e2f295ff3..000000000000 --- a/test/cfi/sibling.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// XFAIL: * - -// RUN: %clangxx_cfi -o %t1 %s -// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB32 -o %t2 %s -// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB64 -o %t3 %s -// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DBM -o %t4 %s -// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx -o %t5 %s -// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s - -// Tests that the CFI enforcement distinguishes between non-overriding siblings. -// XFAILed as not implemented yet. - -#include <stdio.h> -#include "utils.h" - -struct A { - virtual void f(); -}; - -void A::f() {} - -struct B : A { - virtual void f(); -}; - -void B::f() {} - -struct C : A { -}; - -int main() { - create_derivers<B>(); - - B *b = new B; - break_optimization(b); - - // CFI: 1 - // NCFI: 1 - fprintf(stderr, "1\n"); - - ((C *)b)->f(); // UB here - - // CFI-NOT: 2 - // NCFI: 2 - fprintf(stderr, "2\n"); -} diff --git a/test/cfi/simple-fail.cpp b/test/cfi/simple-fail.cpp deleted file mode 100644 index ef36fb08ab4e..000000000000 --- a/test/cfi/simple-fail.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// RUN: %clangxx_cfi -o %t1 %s -// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB32 -o %t2 %s -// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB64 -o %t3 %s -// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DBM -o %t4 %s -// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O1 -o %t5 %s -// RUN: %expect_crash %run %t5 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O1 -DB32 -o %t6 %s -// RUN: %expect_crash %run %t6 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O1 -DB64 -o %t7 %s -// RUN: %expect_crash %run %t7 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O1 -DBM -o %t8 %s -// RUN: %expect_crash %run %t8 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O2 -o %t9 %s -// RUN: %expect_crash %run %t9 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O2 -DB32 -o %t10 %s -// RUN: %expect_crash %run %t10 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O2 -DB64 -o %t11 %s -// RUN: %expect_crash %run %t11 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O2 -DBM -o %t12 %s -// RUN: %expect_crash %run %t12 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O3 -o %t13 %s -// RUN: %expect_crash %run %t13 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O3 -DB32 -o %t14 %s -// RUN: %expect_crash %run %t14 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O3 -DB64 -o %t15 %s -// RUN: %expect_crash %run %t15 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -O3 -DBM -o %t16 %s -// RUN: %expect_crash %run %t16 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi_diag -o %t17 %s -// RUN: %run %t17 2>&1 | FileCheck --check-prefix=CFI-DIAG %s - -// RUN: %clangxx -o %t18 %s -// RUN: %run %t18 2>&1 | FileCheck --check-prefix=NCFI %s - -// RUN: %clangxx_cfi -DCHECK_NO_SANITIZE_CFI -o %t19 %s -// RUN: %run %t19 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 "utils.h" - -struct A { - virtual void f(); -}; - -void A::f() {} - -struct B { - virtual void f(); -}; - -void B::f() {} - -#if defined(CHECK_NO_SANITIZE_CFI) -__attribute__((no_sanitize("cfi"))) -#endif -int main() { - create_derivers<B>(); - - 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 cast to unrelated type - // CFI-DIAG-NEXT: note: vtable is of type '{{(struct )?}}A' - // CFI-DIAG: runtime error: control flow integrity check for type 'B' failed during 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"); -} diff --git a/test/cfi/simple-pass.cpp b/test/cfi/simple-pass.cpp deleted file mode 100644 index de791fc1073f..000000000000 --- a/test/cfi/simple-pass.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// -mretpoline does not work yet on Darwin. -// XFAIL: darwin - -// RUN: %clangxx_cfi -o %t %s -// RUN: %run %t -// RUN: %clangxx_cfi -mretpoline -o %t2 %s -// RUN: %run %t2 - -// Tests that the CFI mechanism does not crash the program when making various -// kinds of valid calls involving classes with various different linkages and -// types of inheritance, and both virtual and non-virtual member functions. - -#include "utils.h" - -struct A { - virtual void f(); - void g(); -}; - -void A::f() {} -void A::g() {} - -struct A2 : A { - virtual void f(); - void g(); -}; - -void A2::f() {} -void A2::g() {} - -struct B { - virtual void f() {} - void g() {} -}; - -struct B2 : B { - virtual void f() {} - void g() {} -}; - -namespace { - -struct C { - virtual void f(); - void g(); -}; - -void C::f() {} -void C::g() {} - -struct C2 : C { - virtual void f(); - void g(); -}; - -void C2::f() {} -void C2::g() {} - -struct D { - virtual void f() {} - void g() {} -}; - -struct D2 : D { - virtual void f() {} - void g() {} -}; - -} - -struct E { - virtual void f() {} - void g() {} -}; - -struct E2 : virtual E { - virtual void f() {} - void g() {} -}; - -int main() { - A *a = new A; - break_optimization(a); - a->f(); - a->g(); - a = new A2; - break_optimization(a); - a->f(); - a->g(); - - B *b = new B; - break_optimization(b); - b->f(); - b->g(); - b = new B2; - break_optimization(b); - b->f(); - b->g(); - - C *c = new C; - break_optimization(c); - c->f(); - c->g(); - c = new C2; - break_optimization(c); - c->f(); - c->g(); - - D *d = new D; - break_optimization(d); - d->f(); - d->g(); - d = new D2; - break_optimization(d); - d->f(); - d->g(); - - E *e = new E; - break_optimization(e); - e->f(); - e->g(); - e = new E2; - break_optimization(e); - e->f(); - e->g(); -} diff --git a/test/cfi/stats.cpp b/test/cfi/stats.cpp deleted file mode 100644 index ca6b3bf0df48..000000000000 --- a/test/cfi/stats.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// RUN: %clangxx_cfi %debug_info_flags -fsanitize-stats -o %t %s -// RUN: env SANITIZER_STATS_PATH=%t.stats %run %t -// RUN: sanstats %t.stats | FileCheck %s - -// FIXME: We currently emit the wrong debug info under devirtualization. -// UNSUPPORTED: devirt - -// FIXME: %t.stats must be transferred from device to host for this to work on Android. -// XFAIL: android - -struct ABase {}; - -struct A : ABase { - virtual void vf() {} - void nvf() {} -}; - -extern "C" __attribute__((noinline)) void vcall(A *a) { - // CHECK: stats.cpp:[[@LINE+1]] {{_?}}vcall cfi-vcall 37 - a->vf(); -} - -extern "C" __attribute__((noinline)) void nvcall(A *a) { - // CHECK: stats.cpp:[[@LINE+1]] {{_?}}nvcall cfi-nvcall 51 - a->nvf(); -} - -extern "C" __attribute__((noinline)) A *dcast(A *a) { - // CHECK: stats.cpp:[[@LINE+1]] {{_?}}dcast cfi-derived-cast 24 - return (A *)(ABase *)a; -} - -extern "C" __attribute__((noinline)) A *ucast(A *a) { - // CHECK: stats.cpp:[[@LINE+1]] {{_?}}ucast cfi-unrelated-cast 81 - return (A *)(char *)a; -} - -extern "C" __attribute__((noinline)) void unreachable(A *a) { - // CHECK-NOT: unreachable - a->vf(); -} - -int main() { - A a; - for (unsigned i = 0; i != 37; ++i) - vcall(&a); - for (unsigned i = 0; i != 51; ++i) - nvcall(&a); - for (unsigned i = 0; i != 24; ++i) - dcast(&a); - for (unsigned i = 0; i != 81; ++i) - ucast(&a); - for (unsigned i = 0; i != 0; ++i) - unreachable(&a); -} diff --git a/test/cfi/target_uninstrumented.cpp b/test/cfi/target_uninstrumented.cpp deleted file mode 100644 index c2db9d609f47..000000000000 --- a/test/cfi/target_uninstrumented.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// RUN: %clangxx -g -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so -// RUN: %clangxx_cfi_diag -g %s -o %t %ld_flags_rpath_exe -// RUN: %run %t 2>&1 | FileCheck %s - -// REQUIRES: cxxabi -// UNSUPPORTED: windows-msvc - -#include <stdio.h> -#include <string.h> - -struct A { - virtual void f(); -}; - -void *create_B(); - -#ifdef SHARED_LIB - -struct B { - virtual void f(); -}; -void B::f() {} - -void *create_B() { - return (void *)(new B()); -} - -#else - -void A::f() {} - -int main(int argc, char *argv[]) { - void *p = create_B(); - // CHECK: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type - // CHECK: invalid vtable - // CHECK: check failed in {{.*}}, vtable located in {{.*}}libtarget_uninstrumented.cpp.dynamic.so - A *a = (A *)p; - memset(p, 0, sizeof(A)); - - // CHECK: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type - // CHECK: invalid vtable - // CHECK: check failed in {{.*}}, vtable located in (unknown) - a = (A *)p; - // CHECK: done - fprintf(stderr, "done %p\n", a); -} -#endif diff --git a/test/cfi/two-vcalls.cpp b/test/cfi/two-vcalls.cpp deleted file mode 100644 index ff823c498027..000000000000 --- a/test/cfi/two-vcalls.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// RUN: %clangxx_cfi_diag -o %t %s -// RUN: %run %t 2>&1 | FileCheck %s - -// This test checks that we don't generate two type checks, -// if two virtual calls are in the same function. - -// UNSUPPORTED: windows-msvc -// REQUIRES: cxxabi - -// TODO(krasin): implement the optimization to not emit two type checks. -// XFAIL: * -#include <stdio.h> - -class Base { - public: - virtual void Foo() { - fprintf(stderr, "Base::Foo\n"); - } - - virtual void Bar() { - fprintf(stderr, "Base::Bar\n"); - } -}; - -class Derived : public Base { - public: - void Foo() override { - fprintf(stderr, "Derived::Foo\n"); - } - - void Bar() override { - printf("Derived::Bar\n"); - } -}; - -__attribute__((noinline)) void print(Base* ptr) { - ptr->Foo(); - // Corrupt the vtable pointer. We expect that the optimization will - // check vtable before the first vcall then store it in a local - // variable, and reuse it for the second vcall. With no optimization, - // CFI will complain about the virtual table being corrupted. - *reinterpret_cast<void**>(ptr) = 0; - ptr->Bar(); -} - - -int main() { - Base b; - Derived d; - // CHECK: Base::Foo - // CHECK: Base::Bar - print(&b); - - // CHECK: Derived::Foo - // CHECK-NOT: runtime error - // CHECK: Derived::Bar - print(&d); - - return 0; -} diff --git a/test/cfi/utils.h b/test/cfi/utils.h deleted file mode 100644 index 430359d8c50c..000000000000 --- a/test/cfi/utils.h +++ /dev/null @@ -1,67 +0,0 @@ -#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). 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> -struct Deriver : T { - Deriver() { - break_optimization(new Deriver<T, I-1>); - } - virtual void f() {} - virtual void g() {} - 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 deleted file mode 100644 index defa4ce15f50..000000000000 --- a/test/cfi/vdtor.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// RUN: %clangxx_cfi -o %t1 %s -// RUN: %expect_crash %run %t1 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB32 -o %t2 %s -// RUN: %expect_crash %run %t2 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DB64 -o %t3 %s -// RUN: %expect_crash %run %t3 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx_cfi -DBM -o %t4 %s -// RUN: %expect_crash %run %t4 2>&1 | FileCheck --check-prefix=CFI %s - -// RUN: %clangxx -o %t5 %s -// RUN: %run %t5 2>&1 | FileCheck --check-prefix=NCFI %s - -// RUN: %clangxx_cfi_diag -o %t6 %s -// RUN: %run %t6 2>&1 | FileCheck --check-prefix=CFI-DIAG %s - -// Tests that the CFI enforcement also applies to virtual destructor calls made -// via 'delete'. - -// REQUIRES: cxxabi - -#include <stdio.h> -#include "utils.h" - -struct A { - virtual ~A(); -}; - -A::~A() {} - -struct B { - virtual ~B(); -}; - -B::~B() {} - -int main() { - create_derivers<B>(); - - 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 virtual call - // CFI-DIAG-NEXT: note: vtable is of type '{{(struct )?}}A' - delete (B *)a; // UB here - - // CFI-NOT: {{^2$}} - // NCFI: {{^2$}} - fprintf(stderr, "2\n"); -} diff --git a/test/cfi/vtable-may-alias.cpp b/test/cfi/vtable-may-alias.cpp deleted file mode 100644 index f63b53b8c9e6..000000000000 --- a/test/cfi/vtable-may-alias.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// RUN: %clangxx_cfi -o %t %s -// RUN: %run %t - -// In this example, both __typeid_A_global_addr and __typeid_B_global_addr will -// refer to the same address. Make sure that the compiler does not assume that -// they do not alias. - -struct A { - virtual void f() = 0; -}; - -struct B : A { - virtual void f() {} -}; - -__attribute__((weak)) void foo(void *p) { - B *b = (B *)p; - A *a = (A *)b; - a->f(); -} - -int main() { - B b; - foo(&b); -} |
