diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:27 +0000 |
commit | 316d58822dada9440bd06ecfc758dcc2364d617c (patch) | |
tree | fe72ec2e6ce9a360dda74d9d57f7acdb0e3c39d6 /test/cfi | |
parent | 0230fcf22fe7d19f03d981c9c2c59a3db0b72ea5 (diff) |
Notes
Diffstat (limited to 'test/cfi')
-rw-r--r-- | test/cfi/CMakeLists.txt | 13 | ||||
-rw-r--r-- | test/cfi/cross-dso/stats.cpp | 8 | ||||
-rw-r--r-- | test/cfi/icall/weak.c | 15 | ||||
-rw-r--r-- | test/cfi/simple-fail.cpp | 6 | ||||
-rw-r--r-- | test/cfi/two-vcalls.cpp | 60 |
5 files changed, 93 insertions, 9 deletions
diff --git a/test/cfi/CMakeLists.txt b/test/cfi/CMakeLists.txt index 4c4debaf1a876..bd51eacb66754 100644 --- a/test/cfi/CMakeLists.txt +++ b/test/cfi/CMakeLists.txt @@ -11,16 +11,19 @@ configure_lit_site_cfg( ) 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 - ubsan - stats sanstats ) - if(COMPILER_RT_HAS_CFI) - list(APPEND CFI_TEST_DEPS cfi) - endif() if(LLVM_ENABLE_PIC AND LLVM_BINUTILS_INCDIR) list(APPEND CFI_TEST_DEPS LLVMgold diff --git a/test/cfi/cross-dso/stats.cpp b/test/cfi/cross-dso/stats.cpp index 3d25d7730c775..6566ea2fc2633 100644 --- a/test/cfi/cross-dso/stats.cpp +++ b/test/cfi/cross-dso/stats.cpp @@ -16,24 +16,24 @@ extern "C" void nvcall(A *a); #ifdef SHARED_LIB extern "C" __attribute__((noinline)) void vcall(A *a) { - // CHECK: stats.cpp:[[@LINE+1]] vcall cfi-vcall 37 + // 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-nvcall 51 + // 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-derived-cast 24 + // 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-unrelated-cast 81 + // CHECK: stats.cpp:[[@LINE+1]] ucast.cfi cfi-unrelated-cast 81 return (A *)(char *)a; } diff --git a/test/cfi/icall/weak.c b/test/cfi/icall/weak.c new file mode 100644 index 0000000000000..40739911109c8 --- /dev/null +++ b/test/cfi/icall/weak.c @@ -0,0 +1,15 @@ +// 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/simple-fail.cpp b/test/cfi/simple-fail.cpp index 92b1322718f89..595ca1617a02a 100644 --- a/test/cfi/simple-fail.cpp +++ b/test/cfi/simple-fail.cpp @@ -52,6 +52,9 @@ // RUN: %clangxx -o %t18 %s // RUN: %t18 2>&1 | FileCheck --check-prefix=NCFI %s +// RUN: %clangxx_cfi -DCHECK_NO_SANITIZE_CFI -o %t19 %s +// 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. @@ -73,6 +76,9 @@ struct B { void B::f() {} +#if defined(CHECK_NO_SANITIZE_CFI) +__attribute__((no_sanitize("cfi"))) +#endif int main() { create_derivers<B>(); diff --git a/test/cfi/two-vcalls.cpp b/test/cfi/two-vcalls.cpp new file mode 100644 index 0000000000000..854b3e0059c12 --- /dev/null +++ b/test/cfi/two-vcalls.cpp @@ -0,0 +1,60 @@ +// RUN: %clangxx_cfi_diag -o %t %s +// 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: win32 +// 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; +} |