diff options
Diffstat (limited to 'test/sanitizer_common')
17 files changed, 466 insertions, 0 deletions
diff --git a/test/sanitizer_common/CMakeLists.txt b/test/sanitizer_common/CMakeLists.txt new file mode 100644 index 000000000000..13eecbdc1b2b --- /dev/null +++ b/test/sanitizer_common/CMakeLists.txt @@ -0,0 +1,46 @@ +set(SANITIZER_COMMON_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +set(SANITIZER_COMMON_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) +set(SANITIZER_COMMON_TESTSUITES) + +set(SUPPORTED_TOOLS) +if(CMAKE_SYSTEM_NAME MATCHES "Darwin|Linux|FreeBSD" AND NOT ANDROID) + list(APPEND SUPPORTED_TOOLS asan) +endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT ANDROID) + list(APPEND SUPPORTED_TOOLS tsan) + list(APPEND SUPPORTED_TOOLS msan) + list(APPEND SUPPORTED_TOOLS lsan) +endif() + +# Create a separate config for each tool we support. +foreach(tool ${SUPPORTED_TOOLS}) + string(TOUPPER ${tool} tool_toupper) + if(${tool_toupper}_SUPPORTED_ARCH) + set(SANITIZER_COMMON_LIT_TEST_MODE ${tool}) + 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() +endforeach() + +# Unit tests. +if(COMPILER_RT_INCLUDE_TESTS) + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg) + list(APPEND SANITIZER_COMMON_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit) + list(APPEND SANITIZER_COMMON_TEST_DEPS SanitizerUnitTests) +endif() + +if(SANITIZER_COMMON_TESTSUITES) + add_lit_testsuite(check-sanitizer "Running sanitizer_common tests" + ${SANITIZER_COMMON_TESTSUITES} + DEPENDS ${SANITIZER_COMMON_TEST_DEPS}) + set_target_properties(check-sanitizer PROPERTIES FOLDER + "sanitizer_common tests") +endif() diff --git a/test/sanitizer_common/TestCases/Linux/aligned_alloc.c b/test/sanitizer_common/TestCases/Linux/aligned_alloc.c new file mode 100644 index 000000000000..12af18dd32a1 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/aligned_alloc.c @@ -0,0 +1,8 @@ +// RUN: %clang -std=c11 -O0 %s -o %t && %run %t +#include <stdlib.h> +extern void *aligned_alloc (size_t alignment, size_t size); +int main() { + volatile void *p = aligned_alloc(128, 1024); + free((void*)p); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Linux/clock_gettime.c b/test/sanitizer_common/TestCases/Linux/clock_gettime.c new file mode 100644 index 000000000000..ec1386ef2414 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/clock_gettime.c @@ -0,0 +1,11 @@ +// RUN: %clang %s -Wl,-as-needed -o %t && %run %t +// Regression test for PR15823 +// (http://llvm.org/bugs/show_bug.cgi?id=15823). +#include <stdio.h> +#include <time.h> + +int main() { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Linux/getpass.cc b/test/sanitizer_common/TestCases/Linux/getpass.cc new file mode 100644 index 000000000000..c9a2276cc248 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/getpass.cc @@ -0,0 +1,32 @@ +// RUN: %clangxx -O0 -g %s -lutil -o %t && %run %t | FileCheck %s +#include <assert.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <pty.h> + +int +main (int argc, char** argv) +{ + int master; + int pid = forkpty(&master, NULL, NULL, NULL); + + if(pid == -1) { + fprintf(stderr, "forkpty failed\n"); + return 1; + } else if (pid > 0) { + char buf[1024]; + int res = read(master, buf, sizeof(buf)); + write(1, buf, res); + write(master, "password\n", 9); + while ((res = read(master, buf, sizeof(buf))) > 0) write(1, buf, res); + } else { + char *s = getpass("prompt"); + assert(strcmp(s, "password") == 0); + write(1, "done\n", 5); + } + return 0; +} + +// CHECK: prompt +// CHECK: done diff --git a/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc b/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc new file mode 100644 index 000000000000..a8b51d7a99c0 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc @@ -0,0 +1,19 @@ +// Regression test for a crash in getpwnam_r and similar interceptors. +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <assert.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> + +int main(void) { + struct passwd pwd; + struct passwd *pwdres; + char buf[10000]; + int res = getpwnam_r("no-such-user", &pwd, buf, sizeof(buf), &pwdres); + assert(res == 0); + assert(pwdres == 0); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Linux/lit.local.cfg b/test/sanitizer_common/TestCases/Linux/lit.local.cfg new file mode 100644 index 000000000000..57271b8078a4 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/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 not in ['Linux']: + config.unsupported = True diff --git a/test/sanitizer_common/TestCases/Linux/mlock_test.cc b/test/sanitizer_common/TestCases/Linux/mlock_test.cc new file mode 100644 index 000000000000..69ea7cb91c4f --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/mlock_test.cc @@ -0,0 +1,13 @@ +// RUN: %clang %s -o %t && %run %t +// XFAIL: lsan + +#include <assert.h> +#include <sys/mman.h> + +int main() { + assert(0 == mlockall(MCL_CURRENT)); + assert(0 == mlock((void *)0x12345, 0x5678)); + assert(0 == munlockall()); + assert(0 == munlock((void *)0x987, 0x654)); +} + diff --git a/test/sanitizer_common/TestCases/Linux/open_memstream.cc b/test/sanitizer_common/TestCases/Linux/open_memstream.cc new file mode 100644 index 000000000000..6abe0bfb1483 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/open_memstream.cc @@ -0,0 +1,57 @@ +// RUN: %clangxx -m64 -O0 -g -xc++ %s -o %t && %run %t +// RUN: %clangxx -m64 -O3 -g -xc++ %s -o %t && %run %t + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +#if __has_feature(memory_sanitizer) +#include <sanitizer/msan_interface.h> +static void check_mem_is_good(void *p, size_t s) { + __msan_check_mem_is_initialized(p, s); +} +#elif __has_feature(address_sanitizer) +#include <sanitizer/asan_interface.h> +static void check_mem_is_good(void *p, size_t s) { + assert(__asan_region_is_poisoned(p, s) == 0); +} +#else +static void check_mem_is_good(void *p, size_t s) {} +#endif + +static void run(void) { + char *buf; + size_t buf_len; + fprintf(stderr, " &buf %p, &buf_len %p\n", &buf, &buf_len); + FILE *fp = open_memstream(&buf, &buf_len); + fprintf(fp, "hello"); + fflush(fp); + check_mem_is_good(&buf, sizeof(buf)); + check_mem_is_good(&buf_len, sizeof(buf_len)); + check_mem_is_good(buf, buf_len); + + char *p = new char[1024]; + memset(p, 'a', 1023); + p[1023] = 0; + for (int i = 0; i < 100; ++i) + fprintf(fp, "%s", p); + delete[] p; + fflush(fp); + fprintf(stderr, " %p addr %p, len %zu\n", &buf, buf, buf_len); + check_mem_is_good(&buf, sizeof(buf)); + check_mem_is_good(&buf_len, sizeof(buf_len)); + check_mem_is_good(buf, buf_len); + fclose(fp); + free(buf); +} + +int main(void) { + for (int i = 0; i < 100; ++i) + run(); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Linux/ptrace.cc b/test/sanitizer_common/TestCases/Linux/ptrace.cc new file mode 100644 index 000000000000..2bf0fd2f0f35 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/ptrace.cc @@ -0,0 +1,60 @@ +// RUN: %clangxx -O0 %s -o %t && %run %t + +#include <assert.h> +#include <signal.h> +#include <stdio.h> +#include <sys/ptrace.h> +#include <sys/types.h> +#include <sys/user.h> +#include <sys/wait.h> +#include <unistd.h> + +int main(void) { + pid_t pid; + pid = fork(); + if (pid == 0) { // child + ptrace(PTRACE_TRACEME, 0, NULL, NULL); + execl("/bin/true", "true", NULL); + } else { + wait(NULL); + int res; + +#if __x86_64__ + user_regs_struct regs; + res = ptrace(PTRACE_GETREGS, pid, NULL, ®s); + assert(!res); + if (regs.rip) + printf("%zx\n", regs.rip); + + user_fpregs_struct fpregs; + res = ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs); + assert(!res); + if (fpregs.mxcsr) + printf("%x\n", fpregs.mxcsr); +#endif // __x86_64__ + +#if __powerpc64__ + struct pt_regs regs; + res = ptrace((enum __ptrace_request)PTRACE_GETREGS, pid, NULL, ®s); + assert(!res); + if (regs.nip) + printf("%lx\n", regs.nip); + + elf_fpregset_t fpregs; + res = ptrace((enum __ptrace_request)PTRACE_GETFPREGS, pid, NULL, &fpregs); + assert(!res); + if ((elf_greg_t)fpregs[32]) // fpscr + printf("%lx\n", (elf_greg_t)fpregs[32]); +#endif // __powerpc64__ + + siginfo_t siginfo; + res = ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo); + assert(!res); + assert(siginfo.si_pid == pid); + + ptrace(PTRACE_CONT, pid, NULL, NULL); + + wait(NULL); + } + return 0; +} diff --git a/test/sanitizer_common/TestCases/Linux/timerfd.cc b/test/sanitizer_common/TestCases/Linux/timerfd.cc new file mode 100644 index 000000000000..e7613bb1d111 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/timerfd.cc @@ -0,0 +1,52 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t | FileCheck %s +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <sys/timerfd.h> +#include <unistd.h> + +int main (int argc, char** argv) +{ + int fd = timerfd_create(CLOCK_REALTIME, 0); + assert(fd >= 0); + + struct itimerspec its; + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 1000000; + its.it_interval.tv_sec = its.it_value.tv_sec; + its.it_interval.tv_nsec = its.it_value.tv_nsec; + + int res = timerfd_settime(fd, 0, &its, NULL); + assert(res != -1); + + struct itimerspec its2; + res = timerfd_settime(fd, 0, &its, &its2); + assert(res != -1); + assert(its2.it_interval.tv_sec == its.it_interval.tv_sec); + assert(its2.it_interval.tv_nsec == its.it_interval.tv_nsec); + assert(its2.it_value.tv_sec <= its.it_value.tv_sec); + assert(its2.it_value.tv_nsec <= its.it_value.tv_nsec); + + struct itimerspec its3; + res = timerfd_gettime(fd, &its3); + assert(res != -1); + assert(its3.it_interval.tv_sec == its.it_interval.tv_sec); + assert(its3.it_interval.tv_nsec == its.it_interval.tv_nsec); + assert(its3.it_value.tv_sec <= its.it_value.tv_sec); + assert(its3.it_value.tv_nsec <= its.it_value.tv_nsec); + + + unsigned long long buf; + res = read(fd, &buf, sizeof(buf)); + assert(res == 8); + assert(buf >= 1); + + res = close(fd); + assert(res != -1); + + printf("DONE\n"); + // CHECK: DONE + + return 0; +} diff --git a/test/sanitizer_common/TestCases/corelimit.cc b/test/sanitizer_common/TestCases/corelimit.cc new file mode 100644 index 000000000000..8f54940d04cc --- /dev/null +++ b/test/sanitizer_common/TestCases/corelimit.cc @@ -0,0 +1,16 @@ +// RUN: %clangxx -O0 %s -o %t && %run %t +// XFAIL: lsan + +#include <assert.h> +#include <sys/time.h> +#include <sys/resource.h> + +int main() { + struct rlimit lim_core; + getrlimit(RLIMIT_CORE, &lim_core); + void *p; + if (sizeof(p) == 8) { + assert(0 == lim_core.rlim_max); + } + return 0; +} diff --git a/test/sanitizer_common/TestCases/malloc_hook.cc b/test/sanitizer_common/TestCases/malloc_hook.cc new file mode 100644 index 000000000000..9702249c57e2 --- /dev/null +++ b/test/sanitizer_common/TestCases/malloc_hook.cc @@ -0,0 +1,38 @@ +// RUN: %clangxx -O2 %s -o %t && %run %t 2>&1 | FileCheck %s + +// Malloc/free hooks are not supported on Windows. +// XFAIL: win32 + +#include <stdlib.h> +#include <unistd.h> +#include <sanitizer/allocator_interface.h> + +extern "C" { +const volatile void *global_ptr; + +// Note: avoid calling functions that allocate memory in malloc/free +// to avoid infinite recursion. +void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) { + if (__sanitizer_get_ownership(ptr)) { + write(1, "MallocHook\n", sizeof("MallocHook\n")); + global_ptr = ptr; + } +} +void __sanitizer_free_hook(const volatile void *ptr) { + if (__sanitizer_get_ownership(ptr) && ptr == global_ptr) + write(1, "FreeHook\n", sizeof("FreeHook\n")); +} +} // extern "C" + +int main() { + volatile int *x = new int; + // CHECK: MallocHook + // Check that malloc hook was called with correct argument. + if (global_ptr != (void*)x) { + _exit(1); + } + *x = 0; + delete x; + // CHECK: FreeHook + return 0; +} diff --git a/test/sanitizer_common/TestCases/print-stack-trace.cc b/test/sanitizer_common/TestCases/print-stack-trace.cc new file mode 100644 index 000000000000..1251f67b83cd --- /dev/null +++ b/test/sanitizer_common/TestCases/print-stack-trace.cc @@ -0,0 +1,24 @@ +// RUN: %clangxx -O0 %s -o %t && %tool_options=stack_trace_format=DEFAULT %run %t 2>&1 | FileCheck %s +// RUN: %clangxx -O3 %s -o %t && %tool_options=stack_trace_format=DEFAULT %run %t 2>&1 | FileCheck %s +// RUN: %tool_options='stack_trace_format="frame:%n lineno:%l"' %run %t 2>&1 | FileCheck %s --check-prefix=CUSTOM +// RUN: %tool_options=symbolize_inline_frames=false:stack_trace_format=DEFAULT %run %t 2>&1 | FileCheck %s --check-prefix=NOINLINE + +#include <sanitizer/common_interface_defs.h> + +static inline void FooBarBaz() { + __sanitizer_print_stack_trace(); +} + +int main() { + FooBarBaz(); + return 0; +} +// CHECK: {{ #0 0x.* in __sanitizer_print_stack_trace}} +// CHECK: {{ #1 0x.* in FooBarBaz(\(\))? .*print-stack-trace.cc:9}} +// CHECK: {{ #2 0x.* in main.*print-stack-trace.cc:13}} + +// CUSTOM: frame:1 lineno:9 +// CUSTOM: frame:2 lineno:13 + +// NOINLINE: #0 0x{{.*}} in __sanitizer_print_stack_trace +// NOINLINE: #1 0x{{.*}} in main{{.*}}print-stack-trace.cc:9 diff --git a/test/sanitizer_common/TestCases/pthread_mutexattr_get.cc b/test/sanitizer_common/TestCases/pthread_mutexattr_get.cc new file mode 100644 index 000000000000..26060f395c11 --- /dev/null +++ b/test/sanitizer_common/TestCases/pthread_mutexattr_get.cc @@ -0,0 +1,19 @@ +// RUN: %clangxx -O0 %s -o %t && %run %t + +#include <assert.h> +#include <pthread.h> + +int main(void) { + pthread_mutexattr_t ma; + int res = pthread_mutexattr_init(&ma); + assert(res == 0); + res = pthread_mutexattr_setpshared(&ma, 1); + assert(res == 0); + int pshared; + res = pthread_mutexattr_getpshared(&ma, &pshared); + assert(res == 0); + assert(pshared == 1); + res = pthread_mutexattr_destroy(&ma); + assert(res == 0); + return 0; +} diff --git a/test/sanitizer_common/Unit/lit.site.cfg.in b/test/sanitizer_common/Unit/lit.site.cfg.in new file mode 100644 index 000000000000..2600585702b2 --- /dev/null +++ b/test/sanitizer_common/Unit/lit.site.cfg.in @@ -0,0 +1,15 @@ +## Autogenerated by LLVM/Clang configuration. +# Do not edit! + +# Load common config for all compiler-rt unit tests. +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/unittests/lit.common.unit.configured") + +# Setup config name. +config.name = 'SanitizerCommon-Unit' + +# Setup test source and exec root. For unit tests, we define +# it as build directory with sanitizer_common tests. +# FIXME: De-hardcode this path. +config.test_exec_root = os.path.join("@COMPILER_RT_BINARY_DIR@", "lib", + "sanitizer_common", "tests") +config.test_source_root = config.test_exec_root diff --git a/test/sanitizer_common/lit.common.cfg b/test/sanitizer_common/lit.common.cfg new file mode 100644 index 000000000000..fb37815ff472 --- /dev/null +++ b/test/sanitizer_common/lit.common.cfg @@ -0,0 +1,38 @@ +# -*- Python -*- + +# Setup source root. +config.test_source_root = os.path.join(os.path.dirname(__file__), "TestCases") + +config.name = "SanitizerCommon-" + config.tool_name + +if config.tool_name == "asan": + tool_cflags = ["-fsanitize=address"] + tool_options = "ASAN_OPTIONS" +elif config.tool_name == "tsan": + tool_cflags = ["-fsanitize=thread"] + tool_options = "TSAN_OPTIONS" +elif config.tool_name == "msan": + tool_cflags = ["-fsanitize=memory"] + tool_options = "MSAN_OPTIONS" +elif config.tool_name == "lsan": + tool_cflags = ["-fsanitize=leak"] + tool_options = "LSAN_OPTIONS" +else: + lit_config.fatal("Unknown tool for sanitizer_common tests: %r" % config.tool_name) + +config.available_features.add(config.tool_name) + +clang_cflags = config.debug_info_flags + tool_cflags + [config.target_cflags] +clang_cxxflags = config.cxx_mode_flags + clang_cflags + +def build_invocation(compile_flags): + return " " + " ".join([config.clang] + compile_flags) + " " + +config.substitutions.append( ("%clang ", build_invocation(clang_cflags)) ) +config.substitutions.append( ("%clangxx ", build_invocation(clang_cxxflags)) ) +config.substitutions.append( ("%tool_options", tool_options) ) + +config.suffixes = ['.c', '.cc', '.cpp'] + +if config.host_os not in ['Linux', 'Darwin']: + config.unsupported = True diff --git a/test/sanitizer_common/lit.site.cfg.in b/test/sanitizer_common/lit.site.cfg.in new file mode 100644 index 000000000000..1e94aa567632 --- /dev/null +++ b/test/sanitizer_common/lit.site.cfg.in @@ -0,0 +1,9 @@ +# Load common config for all compiler-rt lit tests. +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") + +# Tool-specific config options. +config.tool_name = "@SANITIZER_COMMON_LIT_TEST_MODE@" + +# Load tool-specific config that would do the real work. +lit_config.load_config(config, "@SANITIZER_COMMON_LIT_SOURCE_DIR@/lit.common.cfg") + |