summaryrefslogtreecommitdiff
path: root/test/cfi
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:27 +0000
commit316d58822dada9440bd06ecfc758dcc2364d617c (patch)
treefe72ec2e6ce9a360dda74d9d57f7acdb0e3c39d6 /test/cfi
parent0230fcf22fe7d19f03d981c9c2c59a3db0b72ea5 (diff)
Notes
Diffstat (limited to 'test/cfi')
-rw-r--r--test/cfi/CMakeLists.txt13
-rw-r--r--test/cfi/cross-dso/stats.cpp8
-rw-r--r--test/cfi/icall/weak.c15
-rw-r--r--test/cfi/simple-fail.cpp6
-rw-r--r--test/cfi/two-vcalls.cpp60
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;
+}