diff options
Diffstat (limited to 'test/sanitizer_common')
-rw-r--r-- | test/sanitizer_common/CMakeLists.txt | 29 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/Linux/assert.cc | 24 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc | 3 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/Linux/open_memstream.cc | 1 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc | 48 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/Posix/decorate_proc_maps.cc | 60 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/Posix/lit.local.cfg | 9 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/strcasestr.c | 16 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/strcspn.c | 13 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/strpbrk.c | 14 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/strspn.c | 13 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/strstr.c | 12 | ||||
-rw-r--r-- | test/sanitizer_common/lit.common.cfg | 1 | ||||
-rw-r--r-- | test/sanitizer_common/lit.site.cfg.in | 2 |
14 files changed, 236 insertions, 9 deletions
diff --git a/test/sanitizer_common/CMakeLists.txt b/test/sanitizer_common/CMakeLists.txt index 13eecbdc1b2b..7eca7f7672d0 100644 --- a/test/sanitizer_common/CMakeLists.txt +++ b/test/sanitizer_common/CMakeLists.txt @@ -16,16 +16,27 @@ endif() # Create a separate config for each tool we support. foreach(tool ${SUPPORTED_TOOLS}) string(TOUPPER ${tool} tool_toupper) - if(${tool_toupper}_SUPPORTED_ARCH) + if(${tool_toupper}_SUPPORTED_ARCH AND NOT COMPILER_RT_STANDALONE_BUILD) + list(APPEND SANITIZER_COMMON_TEST_DEPS ${tool}) + endif() + foreach(arch ${${tool_toupper}_SUPPORTED_ARCH}) set(SANITIZER_COMMON_LIT_TEST_MODE ${tool}) + set(SANITIZER_COMMON_TEST_TARGET_ARCH ${arch}) + if(${arch} MATCHES "arm|aarch64") + # This is only true if we're cross-compiling. + set(SANITIZER_COMMON_TEST_TARGET_CFLAGS + ${COMPILER_RT_TEST_COMPILER_CFLAGS}) + else() + get_target_flags_for_arch(${arch} SANITIZER_COMMON_TEST_TARGET_CFLAGS) + string(REPLACE ";" " " SANITIZER_COMMON_TEST_TARGET_CFLAGS "${SANITIZER_COMMON_TEST_TARGET_CFLAGS}") + endif() + set(CONFIG_NAME ${tool}-${arch}-${OS_NAME}) configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/${tool}/lit.site.cfg) - list(APPEND SANITIZER_COMMON_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${tool}) - if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND SANITIZER_COMMON_TEST_DEPS ${tool}) - endif() - endif() + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg) + list(APPEND SANITIZER_COMMON_TESTSUITES + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) + endforeach() endforeach() # Unit tests. @@ -37,7 +48,9 @@ if(COMPILER_RT_INCLUDE_TESTS) list(APPEND SANITIZER_COMMON_TEST_DEPS SanitizerUnitTests) endif() -if(SANITIZER_COMMON_TESTSUITES) +# FIXME: Re-enable on 64-bit Windows. +if(SANITIZER_COMMON_TESTSUITES AND + (NOT OS_NAME MATCHES "Windows" OR CMAKE_SIZEOF_VOID_P EQUAL 4)) add_lit_testsuite(check-sanitizer "Running sanitizer_common tests" ${SANITIZER_COMMON_TESTSUITES} DEPENDS ${SANITIZER_COMMON_TEST_DEPS}) diff --git a/test/sanitizer_common/TestCases/Linux/assert.cc b/test/sanitizer_common/TestCases/Linux/assert.cc new file mode 100644 index 000000000000..7f9b0a061da0 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/assert.cc @@ -0,0 +1,24 @@ +// Test the handle_abort option. +// RUN: %clang %s -o %t +// RUN: not --crash %run %t 2>&1 | FileCheck --check-prefix=CHECK0 %s +// RUN: %tool_options=handle_abort=0 not --crash %run %t 2>&1 | FileCheck --check-prefix=CHECK0 %s +// RUN: %tool_options=handle_abort=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK1 %s +// FIXME: implement in other sanitizers, not just asan. +// XFAIL: msan +// XFAIL: lsan +// XFAIL: tsan +#include <assert.h> +#include <stdio.h> +#include <sanitizer/asan_interface.h> + +void death() { + fprintf(stderr, "DEATH CALLBACK\n"); +} + +int main(int argc, char **argv) { + __sanitizer_set_death_callback(death); + assert(argc == 100); +} +// CHECK1: ERROR: {{.*}}Sanitizer: +// CHECK1: DEATH CALLBACK +// CHECK0-NOT: Sanitizer diff --git a/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc b/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc index a8b51d7a99c0..c0d6cfea1fbe 100644 --- a/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc +++ b/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc @@ -2,6 +2,7 @@ // RUN: %clangxx -O0 -g %s -o %t && %run %t #include <assert.h> +#include <errno.h> #include <pwd.h> #include <signal.h> #include <stdio.h> @@ -13,7 +14,7 @@ int main(void) { struct passwd *pwdres; char buf[10000]; int res = getpwnam_r("no-such-user", &pwd, buf, sizeof(buf), &pwdres); - assert(res == 0); + assert(res == 0 || res == ENOENT); assert(pwdres == 0); return 0; } diff --git a/test/sanitizer_common/TestCases/Linux/open_memstream.cc b/test/sanitizer_common/TestCases/Linux/open_memstream.cc index 6abe0bfb1483..69097c094a93 100644 --- a/test/sanitizer_common/TestCases/Linux/open_memstream.cc +++ b/test/sanitizer_common/TestCases/Linux/open_memstream.cc @@ -1,5 +1,6 @@ // RUN: %clangxx -m64 -O0 -g -xc++ %s -o %t && %run %t // RUN: %clangxx -m64 -O3 -g -xc++ %s -o %t && %run %t +// REQUIRES: x86_64-supported-target #include <assert.h> #include <stdio.h> diff --git a/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc b/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc new file mode 100644 index 000000000000..643fb48ae773 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc @@ -0,0 +1,48 @@ +// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0 allow_user_segv_handler=1" %run %t 2>&1 | FileCheck %s + +// JVM uses SEGV to preempt threads. All threads do a load from a known address +// periodically. When runtime needs to preempt threads, it unmaps the page. +// Threads start triggering SEGV one by one. The signal handler blocks +// threads while runtime does its thing. Then runtime maps the page again +// and resumes the threads. +// Previously this pattern conflicted with stop-the-world machinery, +// because it briefly reset SEGV handler to SIG_DFL. +// As the consequence JVM just silently died. + +// This test sets memory flushing rate to maximum, then does series of +// "benign" SEGVs that are handled by signal handler, and ensures that +// the process survive. + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <sys/mman.h> +#include <string.h> +#include <unistd.h> + +unsigned long page_size; +void *guard; + +void handler(int signo, siginfo_t *info, void *uctx) { + mprotect(guard, page_size, PROT_READ | PROT_WRITE); +} + +int main() { + page_size = sysconf(_SC_PAGESIZE); + struct sigaction a, old; + memset(&a, 0, sizeof(a)); + memset(&old, 0, sizeof(old)); + a.sa_sigaction = handler; + a.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &a, &old); + guard = mmap(0, 3 * page_size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); + guard = (char*)guard + page_size; // work around a kernel bug + for (int i = 0; i < 1000000; i++) { + mprotect(guard, page_size, PROT_NONE); + *(int*)guard = 1; + } + sigaction(SIGSEGV, &old, 0); + fprintf(stderr, "DONE\n"); +} + +// CHECK: DONE diff --git a/test/sanitizer_common/TestCases/Posix/decorate_proc_maps.cc b/test/sanitizer_common/TestCases/Posix/decorate_proc_maps.cc new file mode 100644 index 000000000000..622471767655 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/decorate_proc_maps.cc @@ -0,0 +1,60 @@ +// RUN: %clangxx -g %s -o %t +// RUN: %tool_options=decorate_proc_maps=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%tool_name +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +bool CopyFdToFd(int in_fd, int out_fd) { + const size_t kBufSize = 0x10000; + static char buf[kBufSize]; + while (true) { + ssize_t got = read(in_fd, buf, kBufSize); + if (got > 0) { + write(out_fd, buf, got); + } else if (got == 0) { + break; + } else if (errno != EAGAIN || errno != EWOULDBLOCK || errno != EINTR) { + fprintf(stderr, "error reading file, errno %d\n", errno); + return false; + } + } + return true; +} + +void *ThreadFn(void *arg) { + (void)arg; + int fd = open("/proc/self/maps", O_RDONLY); + bool res = CopyFdToFd(fd, 2); + close(fd); + return (void *)!res; +} + +int main(void) { + pthread_t t; + void *res; + pthread_create(&t, 0, ThreadFn, 0); + pthread_join(t, &res); + return (int)(size_t)res; +} + +// CHECK-asan: rw-p {{.*}} [low shadow] +// CHECK-asan: ---p {{.*}} [shadow gap] +// CHECK-asan: rw-p {{.*}} [high shadow] + +// CHECK-msan: ---p {{.*}} [invalid] +// CHECK-msan: rw-p {{.*}} [shadow] +// CHECK-msan: ---p {{.*}} [origin] + +// CHECK-tsan: rw-p {{.*}} [shadow] +// CHECK-tsan: rw-p {{.*}} [meta shadow] +// CHECK-tsan: rw-p {{.*}} [trace 0] +// CHECK-tsan: rw-p {{.*}} [trace header 0] +// CHECK-tsan: rw-p {{.*}} [trace 1] +// CHECK-tsan: rw-p {{.*}} [trace header 1] + +// Nothing interesting with standalone LSan. +// CHECK-lsan: decorate_proc_maps diff --git a/test/sanitizer_common/TestCases/Posix/lit.local.cfg b/test/sanitizer_common/TestCases/Posix/lit.local.cfg new file mode 100644 index 000000000000..a6d96d3054cf --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/lit.local.cfg @@ -0,0 +1,9 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +root = getRoot(config) + +if root.host_os in ['Windows', 'Darwin']: + config.unsupported = True diff --git a/test/sanitizer_common/TestCases/strcasestr.c b/test/sanitizer_common/TestCases/strcasestr.c new file mode 100644 index 000000000000..4de3cac7e253 --- /dev/null +++ b/test/sanitizer_common/TestCases/strcasestr.c @@ -0,0 +1,16 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 + +// There's no interceptor for strcasestr on Windows +// XFAIL: win32 + +#define _GNU_SOURCE +#include <assert.h> +#include <string.h> +int main(int argc, char **argv) { + char *r = 0; + char s1[] = "aB"; + char s2[] = "b"; + r = strcasestr(s1, s2); + assert(r == s1 + 1); + return 0; +} diff --git a/test/sanitizer_common/TestCases/strcspn.c b/test/sanitizer_common/TestCases/strcspn.c new file mode 100644 index 000000000000..066a27bbdf2c --- /dev/null +++ b/test/sanitizer_common/TestCases/strcspn.c @@ -0,0 +1,13 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 + +#include <assert.h> +#include <string.h> + +int main(int argc, char **argv) { + size_t r; + char s1[] = "ad"; + char s2[] = "cd"; + r = strcspn(s1, s2); + assert(r == 1); + return 0; +} diff --git a/test/sanitizer_common/TestCases/strpbrk.c b/test/sanitizer_common/TestCases/strpbrk.c new file mode 100644 index 000000000000..318e3a4977f2 --- /dev/null +++ b/test/sanitizer_common/TestCases/strpbrk.c @@ -0,0 +1,14 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 + +#include <assert.h> +#include <string.h> + + +int main(int argc, char **argv) { + char *r = 0; + char s1[] = "ad"; + char s2[] = "cd"; + r = strpbrk(s1, s2); + assert(r == s1 + 1); + return 0; +} diff --git a/test/sanitizer_common/TestCases/strspn.c b/test/sanitizer_common/TestCases/strspn.c new file mode 100644 index 000000000000..a9a24305c6f1 --- /dev/null +++ b/test/sanitizer_common/TestCases/strspn.c @@ -0,0 +1,13 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 + +#include <assert.h> +#include <string.h> + +int main(int argc, char **argv) { + size_t r; + char s1[] = "ab"; + char s2[] = "ac"; + r = strspn(s1, s2); + assert(r == 1); + return 0; +} diff --git a/test/sanitizer_common/TestCases/strstr.c b/test/sanitizer_common/TestCases/strstr.c new file mode 100644 index 000000000000..2089ac7b5fcb --- /dev/null +++ b/test/sanitizer_common/TestCases/strstr.c @@ -0,0 +1,12 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 + +#include <assert.h> +#include <string.h> +int main(int argc, char **argv) { + char *r = 0; + char s1[] = "ab"; + char s2[] = "b"; + r = strstr(s1, s2); + assert(r == s1 + 1); + return 0; +} diff --git a/test/sanitizer_common/lit.common.cfg b/test/sanitizer_common/lit.common.cfg index fb37815ff472..f2d3fec6baa2 100644 --- a/test/sanitizer_common/lit.common.cfg +++ b/test/sanitizer_common/lit.common.cfg @@ -30,6 +30,7 @@ def build_invocation(compile_flags): config.substitutions.append( ("%clang ", build_invocation(clang_cflags)) ) config.substitutions.append( ("%clangxx ", build_invocation(clang_cxxflags)) ) +config.substitutions.append( ("%tool_name", config.tool_name) ) config.substitutions.append( ("%tool_options", tool_options) ) config.suffixes = ['.c', '.cc', '.cpp'] diff --git a/test/sanitizer_common/lit.site.cfg.in b/test/sanitizer_common/lit.site.cfg.in index 1e94aa567632..64a3edf6c682 100644 --- a/test/sanitizer_common/lit.site.cfg.in +++ b/test/sanitizer_common/lit.site.cfg.in @@ -3,6 +3,8 @@ lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configu # Tool-specific config options. config.tool_name = "@SANITIZER_COMMON_LIT_TEST_MODE@" +config.target_cflags = "@SANITIZER_COMMON_TEST_TARGET_CFLAGS@" +config.target_arch = "@SANITIZER_COMMON_TEST_TARGET_ARCH@" # Load tool-specific config that would do the real work. lit_config.load_config(config, "@SANITIZER_COMMON_LIT_SOURCE_DIR@/lit.common.cfg") |