summaryrefslogtreecommitdiff
path: root/test/safestack
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-09-06 18:41:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-09-06 18:41:23 +0000
commitf31bcc68c72371a2bf63aead9f3373a1ff2053b6 (patch)
treeb259e5d585da0f8cde9579939a74d5ef44c72abd /test/safestack
parentcd2dd3df15523e2be8d2bbace27641d6ac9fa40d (diff)
downloadsrc-test2-f31bcc68c72371a2bf63aead9f3373a1ff2053b6.tar.gz
src-test2-f31bcc68c72371a2bf63aead9f3373a1ff2053b6.zip
Notes
Diffstat (limited to 'test/safestack')
-rw-r--r--test/safestack/CMakeLists.txt29
-rw-r--r--test/safestack/buffer-copy-vla.c26
-rw-r--r--test/safestack/buffer-copy.c25
-rw-r--r--test/safestack/init.c9
-rw-r--r--test/safestack/lit.cfg24
-rw-r--r--test/safestack/lit.site.cfg.in8
-rw-r--r--test/safestack/lto.c12
-rw-r--r--test/safestack/overflow.c23
-rw-r--r--test/safestack/pthread-cleanup.c31
-rw-r--r--test/safestack/pthread.c42
-rw-r--r--test/safestack/utils.h8
11 files changed, 237 insertions, 0 deletions
diff --git a/test/safestack/CMakeLists.txt b/test/safestack/CMakeLists.txt
new file mode 100644
index 000000000000..6f5c2f9b0af4
--- /dev/null
+++ b/test/safestack/CMakeLists.txt
@@ -0,0 +1,29 @@
+set(SAFESTACK_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(SAFESTACK_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+
+set(SAFESTACK_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+if(NOT COMPILER_RT_STANDALONE_BUILD)
+ list(APPEND SAFESTACK_TEST_DEPS safestack)
+
+ # Some tests require LTO, so add a dependency on the relevant LTO plugin.
+ if(LLVM_ENABLE_PIC AND LLVM_BINUTILS_INCDIR)
+ list(APPEND SAFESTACK_TEST_DEPS
+ LLVMgold
+ )
+ endif()
+ if(APPLE)
+ list(APPEND SAFESTACK_TEST_DEPS
+ LTO
+ )
+ endif()
+endif()
+
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ )
+
+add_lit_testsuite(check-safestack "Running the SafeStack tests"
+ ${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS ${SAFESTACK_TEST_DEPS})
+set_target_properties(check-safestack PROPERTIES FOLDER "SafeStack tests")
diff --git a/test/safestack/buffer-copy-vla.c b/test/safestack/buffer-copy-vla.c
new file mode 100644
index 000000000000..356a1ac5c65c
--- /dev/null
+++ b/test/safestack/buffer-copy-vla.c
@@ -0,0 +1,26 @@
+// RUN: %clang_safestack %s -o %t
+// RUN: %run %t
+
+#include "utils.h"
+
+// Test that loads/stores work correctly for VLAs on the unsafe stack.
+
+int main(int argc, char **argv)
+{
+ int i = 128;
+ break_optimization(&i);
+ char buffer[i];
+
+ // check that we can write to a buffer
+ for (i = 0; argv[0][i] && i < sizeof (buffer) - 1; ++i)
+ buffer[i] = argv[0][i];
+ buffer[i] = '\0';
+
+ break_optimization(buffer);
+
+ // check that we can read from a buffer
+ for (i = 0; argv[0][i] && i < sizeof (buffer) - 1; ++i)
+ if (buffer[i] != argv[0][i])
+ return 1;
+ return 0;
+}
diff --git a/test/safestack/buffer-copy.c b/test/safestack/buffer-copy.c
new file mode 100644
index 000000000000..96b2302be1b1
--- /dev/null
+++ b/test/safestack/buffer-copy.c
@@ -0,0 +1,25 @@
+// RUN: %clang_safestack %s -o %t
+// RUN: %run %t
+
+#include "utils.h"
+
+// Test that loads/stores work correctly for variables on the unsafe stack.
+
+int main(int argc, char **argv)
+{
+ int i;
+ char buffer[128];
+
+ // check that we can write to a buffer
+ for (i = 0; argv[0][i] && i < sizeof (buffer) - 1; ++i)
+ buffer[i] = argv[0][i];
+ buffer[i] = '\0';
+
+ break_optimization(buffer);
+
+ // check that we can read from a buffer
+ for (i = 0; argv[0][i] && i < sizeof (buffer) - 1; ++i)
+ if (buffer[i] != argv[0][i])
+ return 1;
+ return 0;
+}
diff --git a/test/safestack/init.c b/test/safestack/init.c
new file mode 100644
index 000000000000..cff75f5f8939
--- /dev/null
+++ b/test/safestack/init.c
@@ -0,0 +1,9 @@
+// RUN: %clang_safestack %s -o %t
+// RUN: %run %t
+
+// Basic smoke test for the runtime library.
+
+int main(int argc, char **argv)
+{
+ return 0;
+}
diff --git a/test/safestack/lit.cfg b/test/safestack/lit.cfg
new file mode 100644
index 000000000000..13fc92fa4b2b
--- /dev/null
+++ b/test/safestack/lit.cfg
@@ -0,0 +1,24 @@
+# -*- Python -*-
+
+import os
+
+# Setup config name.
+config.name = 'SafeStack'
+
+# Setup source root.
+config.test_source_root = os.path.dirname(__file__)
+
+# Test suffixes.
+config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm', '.ll', '.test']
+
+# Add clang substitutions.
+config.substitutions.append( ("%clang_nosafestack ", config.clang + " -O0 -fno-sanitize=safe-stack ") )
+config.substitutions.append( ("%clang_safestack ", config.clang + " -O0 -fsanitize=safe-stack ") )
+
+if config.lto_supported:
+ config.available_features.add('lto')
+ config.substitutions.append((r"%clang_lto_safestack ", ' '.join(config.lto_launch + [config.clang] + config.lto_flags + ['-flto -fsanitize=safe-stack '])))
+
+# SafeStack tests are currently supported on Linux, FreeBSD and Darwin only.
+if config.host_os not in ['Linux', 'FreeBSD', 'Darwin']:
+ config.unsupported = True
diff --git a/test/safestack/lit.site.cfg.in b/test/safestack/lit.site.cfg.in
new file mode 100644
index 000000000000..cb1e7292e5f2
--- /dev/null
+++ b/test/safestack/lit.site.cfg.in
@@ -0,0 +1,8 @@
+## Autogenerated by LLVM/Clang configuration.
+# Do not edit!
+
+# Load common config for all compiler-rt lit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@SAFESTACK_LIT_SOURCE_DIR@/lit.cfg")
diff --git a/test/safestack/lto.c b/test/safestack/lto.c
new file mode 100644
index 000000000000..6ee23a1c72f2
--- /dev/null
+++ b/test/safestack/lto.c
@@ -0,0 +1,12 @@
+// REQUIRES: lto
+
+// RUN: %clang_lto_safestack %s -o %t
+// RUN: %run %t
+
+// Test that safe stack works with LTO.
+
+int main() {
+ char c[] = "hello world";
+ puts(c);
+ return 0;
+}
diff --git a/test/safestack/overflow.c b/test/safestack/overflow.c
new file mode 100644
index 000000000000..14e29823cd99
--- /dev/null
+++ b/test/safestack/overflow.c
@@ -0,0 +1,23 @@
+// RUN: %clang_safestack %s -o %t
+// RUN: %run %t
+
+// RUN: %clang_nosafestack -fno-stack-protector %s -o %t
+// RUN: not %run %t
+
+// Test that buffer overflows on the unsafe stack do not affect variables on the
+// safe stack.
+
+__attribute__((noinline))
+void fct(volatile int *buffer)
+{
+ memset(buffer - 1, 0, 7 * sizeof(int));
+}
+
+int main(int argc, char **argv)
+{
+ int value1 = 42;
+ int buffer[5];
+ int value2 = 42;
+ fct(buffer);
+ return value1 != 42 || value2 != 42;
+}
diff --git a/test/safestack/pthread-cleanup.c b/test/safestack/pthread-cleanup.c
new file mode 100644
index 000000000000..805366c9f1eb
--- /dev/null
+++ b/test/safestack/pthread-cleanup.c
@@ -0,0 +1,31 @@
+// RUN: %clang_safestack %s -pthread -o %t
+// RUN: not --crash %run %t
+
+// Test that unsafe stacks are deallocated correctly on thread exit.
+
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+
+enum { kBufferSize = (1 << 15) };
+
+void *t1_start(void *ptr)
+{
+ char buffer[kBufferSize];
+ return buffer;
+}
+
+int main(int argc, char **argv)
+{
+ pthread_t t1;
+ char *buffer = NULL;
+
+ if (pthread_create(&t1, NULL, t1_start, NULL))
+ abort();
+ if (pthread_join(t1, &buffer))
+ abort();
+
+ // should segfault here
+ memset(buffer, 0, kBufferSize);
+ return 0;
+}
diff --git a/test/safestack/pthread.c b/test/safestack/pthread.c
new file mode 100644
index 000000000000..416586ee13e7
--- /dev/null
+++ b/test/safestack/pthread.c
@@ -0,0 +1,42 @@
+// RUN: %clang_safestack %s -pthread -o %t
+// RUN: %run %t
+
+// XFAIL: darwin
+
+// Test that pthreads receive their own unsafe stack.
+
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include "utils.h"
+
+static int ptr_test = 42;
+
+void *t1_start(void *ptr)
+{
+ if (ptr != &ptr_test)
+ abort();
+
+ // safe stack
+ int val = ptr_test * 5;
+
+ // unsafe stack
+ char buffer[8096]; // two pages
+ memset(buffer, val, sizeof (buffer));
+ break_optimization(buffer);
+
+ return ptr;
+}
+
+int main(int argc, char **argv)
+{
+ pthread_t t1;
+ void *ptr = NULL;
+ if (pthread_create(&t1, NULL, t1_start, &ptr_test))
+ abort();
+ if (pthread_join(t1, &ptr))
+ abort();
+ if (ptr != &ptr_test)
+ abort();
+ return 0;
+}
diff --git a/test/safestack/utils.h b/test/safestack/utils.h
new file mode 100644
index 000000000000..b04e3bdc127e
--- /dev/null
+++ b/test/safestack/utils.h
@@ -0,0 +1,8 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+static inline void break_optimization(void *arg) {
+ __asm__ __volatile__("" : : "r" (arg) : "memory");
+}
+
+#endif