diff options
Diffstat (limited to 'test')
439 files changed, 10736 insertions, 1444 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ab16f42d33d4..554ba5fa0f0e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -61,7 +61,8 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS) compiler_rt_test_runtime(ubsan cfi) compiler_rt_test_runtime(sanitizer_common) - if(COMPILER_RT_BUILD_LIBFUZZER) + # OpenBSD not supporting asan, cannot run the tests + if(COMPILER_RT_BUILD_LIBFUZZER AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD" AND NOT ANDROID) compiler_rt_test_runtime(fuzzer) endif() @@ -78,6 +79,9 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS) if(COMPILER_RT_BUILD_XRAY) compiler_rt_test_runtime(xray) endif() + # ShadowCallStack does not yet provide a runtime with compiler-rt, the tests + # include their own minimal runtime + add_subdirectory(shadowcallstack) endif() if(COMPILER_RT_STANDALONE_BUILD) diff --git a/test/asan/CMakeLists.txt b/test/asan/CMakeLists.txt index 739ae56e782b..e6d1df5e039a 100644 --- a/test/asan/CMakeLists.txt +++ b/test/asan/CMakeLists.txt @@ -8,7 +8,7 @@ set(ASAN_DYNAMIC_TESTSUITES) # unreliable. Remove the asan tests from check-all in this configuration. set(SHADOW_MAPPING_UNRELIABLE FALSE) if(OS_NAME MATCHES "Windows" AND CMAKE_SIZEOF_VOID_P EQUAL 8 AND - ${CMAKE_SYSTEM_VERSION} LESS 6.2) + CMAKE_SYSTEM_VERSION LESS 6.2) set(SHADOW_MAPPING_UNRELIABLE TRUE) message(WARNING "Disabling ASan tests because they are unreliable on Windows 7 and earlier") endif() @@ -18,10 +18,10 @@ if (SHADOW_MAPPING_UNRELIABLE) endif() macro(get_bits_for_arch arch bits) - if (${arch} MATCHES "i386|arm|mips|mipsel") - set(${bits} 32) - elseif (${arch} MATCHES "x86_64|powerpc64|powerpc64le|aarch64|mips64|mips64el|s390x") + if (${arch} MATCHES "x86_64|powerpc64|powerpc64le|aarch64|arm64|mips64|mips64el|s390x") set(${bits} 64) + elseif (${arch} MATCHES "i386|arm|mips|mipsel") + set(${bits} 32) else() message(FATAL_ERROR "Unknown target architecture: ${arch}") endif() @@ -40,6 +40,9 @@ set(ASAN_TEST_ARCH ${ASAN_SUPPORTED_ARCH}) if(APPLE) darwin_filter_host_archs(ASAN_SUPPORTED_ARCH ASAN_TEST_ARCH) endif() +if(OS_NAME MATCHES "SunOS") + list(REMOVE_ITEM ASAN_TEST_ARCH x86_64) +endif() foreach(arch ${ASAN_TEST_ARCH}) if(ANDROID) @@ -48,10 +51,7 @@ foreach(arch ${ASAN_TEST_ARCH}) set(ASAN_TEST_TARGET_ARCH ${arch}) endif() - set(ASAN_TEST_IOS "0") - pythonize_bool(ASAN_TEST_IOS) - set(ASAN_TEST_IOSSIM "0") - pythonize_bool(ASAN_TEST_IOSSIM) + set(ASAN_TEST_APPLE_PLATFORM "osx") string(TOLOWER "-${arch}-${OS_NAME}" ASAN_TEST_CONFIG_SUFFIX) get_bits_for_arch(${arch} ASAN_TEST_BITS) @@ -90,16 +90,13 @@ if(APPLE) set(EXCLUDE_FROM_ALL ON) set(ASAN_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER}) - set(ASAN_TEST_IOS "1") - pythonize_bool(ASAN_TEST_IOS) set(ASAN_TEST_DYNAMIC True) foreach(arch ${DARWIN_iossim_ARCHS}) - set(ASAN_TEST_IOSSIM "1") - pythonize_bool(ASAN_TEST_IOSSIM) + set(ASAN_TEST_APPLE_PLATFORM "iossim") set(ASAN_TEST_TARGET_ARCH ${arch}) set(ASAN_TEST_TARGET_CFLAGS "-arch ${arch} -isysroot ${DARWIN_iossim_SYSROOT} ${COMPILER_RT_TEST_COMPILER_CFLAGS}") - set(ASAN_TEST_CONFIG_SUFFIX "-${arch}-iossim") + set(ASAN_TEST_CONFIG_SUFFIX "-${arch}-${ASAN_TEST_APPLE_PLATFORM}") get_bits_for_arch(${arch} ASAN_TEST_BITS) string(TOUPPER ${arch} ARCH_UPPER_CASE) set(CONFIG_NAME "IOSSim${ARCH_UPPER_CASE}Config") @@ -113,11 +110,10 @@ if(APPLE) endforeach() foreach (arch ${DARWIN_ios_ARCHS}) - set(ASAN_TEST_IOSSIM "0") - pythonize_bool(ASAN_TEST_IOSSIM) + set(ASAN_TEST_APPLE_PLATFORM "ios") set(ASAN_TEST_TARGET_ARCH ${arch}) set(ASAN_TEST_TARGET_CFLAGS "-arch ${arch} -isysroot ${DARWIN_ios_SYSROOT} ${COMPILER_RT_TEST_COMPILER_CFLAGS}") - set(ASAN_TEST_CONFIG_SUFFIX "-${arch}-ios") + set(ASAN_TEST_CONFIG_SUFFIX "-${arch}-${ASAN_TEST_APPLE_PLATFORM}") get_bits_for_arch(${arch} ASAN_TEST_BITS) string(TOUPPER ${arch} ARCH_UPPER_CASE) set(CONFIG_NAME "IOS${ARCH_UPPER_CASE}Config") diff --git a/test/asan/TestCases/Darwin/asan_gen_prefixes.cc b/test/asan/TestCases/Darwin/asan_gen_prefixes.cc index 9f3a66a7a708..fe337433d08d 100644 --- a/test/asan/TestCases/Darwin/asan_gen_prefixes.cc +++ b/test/asan/TestCases/Darwin/asan_gen_prefixes.cc @@ -1,4 +1,4 @@ -// Make sure __asan_gen_* strings have the correct prefixes on Darwin +// Make sure ___asan_gen_* strings have the correct prefixes on Darwin // ("L" in __TEXT,__cstring, "l" in __TEXT,__const // RUN: %clang_asan %s -S -o %t.s @@ -9,8 +9,8 @@ int x, y, z; int main() { return 0; } // CHECK: .section{{.*}}__TEXT,__const -// CHECK: l___asan_gen_ +// CHECK: l____asan_gen_ // CHECK: .section{{.*}}__TEXT,__cstring,cstring_literals -// CHECK: L___asan_gen_ -// CHECK: L___asan_gen_ -// CHECK: L___asan_gen_ +// CHECK: L____asan_gen_ +// CHECK: L____asan_gen_ +// CHECK: L____asan_gen_ diff --git a/test/asan/TestCases/Darwin/odr-lto.cc b/test/asan/TestCases/Darwin/odr-lto.cc index 40abec5827d5..56dd89b164c2 100644 --- a/test/asan/TestCases/Darwin/odr-lto.cc +++ b/test/asan/TestCases/Darwin/odr-lto.cc @@ -3,15 +3,10 @@ // REQUIRES: lto -// RUN: %clangxx_asan -DPART=0 -c %s -o %t-1.o -flto -// RUN: %clangxx_asan -DPART=1 -c %s -o %t-2.o -flto -// RUN: %clangxx_asan %t-1.o %t-2.o -o %t -flto -// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-ODR - // RUN: %clangxx_asan -DPART=0 -c %s -o %t-1.o -flto -mllvm -asan-use-private-alias // RUN: %clangxx_asan -DPART=1 -c %s -o %t-2.o -flto -mllvm -asan-use-private-alias // RUN: %clangxx_asan %t-1.o %t-2.o -o %t -flto -// RUN: %env_asan_opts=use_odr_indicator=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NO-ODR +// RUN: %env_asan_opts=use_odr_indicator=1 %run %t 2>&1 | FileCheck %s #include <stdio.h> #include <stdlib.h> @@ -40,6 +35,5 @@ void putstest() #endif // PART == 1 -// CHECK-ODR: ERROR: AddressSanitizer: odr-violation -// CHECK-NO-ODR-NOT: ERROR: AddressSanitizer: odr-violation -// CHECK-NO-ODR: Done. +// CHECK-NOT: ERROR: AddressSanitizer: odr-violation +// CHECK: Done. diff --git a/test/asan/TestCases/Linux/activation-options.cc b/test/asan/TestCases/Linux/activation-options.cc index 1a1ad3f8c499..39924c4b1d03 100644 --- a/test/asan/TestCases/Linux/activation-options.cc +++ b/test/asan/TestCases/Linux/activation-options.cc @@ -28,7 +28,6 @@ // RUN: ASAN_ACTIVATION_OPTIONS=include=%t.asan.options.%b %run %t --fix-name 2>&1 | \ // RUN: FileCheck %s --check-prefix=CHECK-HELP --check-prefix=CHECK-FOUND -// XFAIL: arm-linux-gnueabi // XFAIL: android #if !defined(SHARED_LIB) diff --git a/test/asan/TestCases/Linux/allocator_oom_test.cc b/test/asan/TestCases/Linux/allocator_oom_test.cc index 6382003781ce..c450ae5bb8e9 100644 --- a/test/asan/TestCases/Linux/allocator_oom_test.cc +++ b/test/asan/TestCases/Linux/allocator_oom_test.cc @@ -32,7 +32,7 @@ // AArch64 bots fail on this test. // TODO(alekseys): Android lit do not run ulimit on device. // REQUIRES: shadow-scale-3 -// UNSUPPORTED: s390,android,arm,aarch64 +// UNSUPPORTED: s390,android,aarch64 #include <stdlib.h> #include <string.h> @@ -84,5 +84,5 @@ int main(int argc, char **argv) { // CHECK-REALLOC: realloc: // CHECK-MALLOC-REALLOC: realloc-after-malloc: -// CHECK-CRASH: AddressSanitizer's allocator is terminating the process +// CHECK-CRASH: SUMMARY: AddressSanitizer: out-of-memory // CHECK-NULL: x: 0 diff --git a/test/asan/TestCases/Linux/clang_gcc_abi.cc b/test/asan/TestCases/Linux/clang_gcc_abi.cc index 79710dc837b9..e0ae3f1f8afd 100644 --- a/test/asan/TestCases/Linux/clang_gcc_abi.cc +++ b/test/asan/TestCases/Linux/clang_gcc_abi.cc @@ -3,8 +3,7 @@ // RUN: %clangxx_asan -O2 -x c %s -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -O3 -x c %s -o %t && not %run %t 2>&1 | FileCheck %s -// REQUIRES: arm-target-arch, fast-unwinder-works -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: (arm-target-arch || armhf-target-arch), fast-unwinder-works #include <stdlib.h> diff --git a/test/asan/TestCases/Linux/clone_test.cc b/test/asan/TestCases/Linux/clone_test.cc index f6eb26100f5e..0b86238ccad6 100644 --- a/test/asan/TestCases/Linux/clone_test.cc +++ b/test/asan/TestCases/Linux/clone_test.cc @@ -5,7 +5,6 @@ // RUN: %clangxx_asan -O1 %s -o %t && %run %t | FileCheck %s // RUN: %clangxx_asan -O2 %s -o %t && %run %t | FileCheck %s // RUN: %clangxx_asan -O3 %s -o %t && %run %t | FileCheck %s -// XFAIL: arm-linux-gnueabi #include <stdio.h> #include <sched.h> diff --git a/test/asan/TestCases/Linux/coverage-missing.cc b/test/asan/TestCases/Linux/coverage-missing.cc index 585aee69a029..32aada645deb 100644 --- a/test/asan/TestCases/Linux/coverage-missing.cc +++ b/test/asan/TestCases/Linux/coverage-missing.cc @@ -2,18 +2,18 @@ // First case: coverage from executable. main() is called on every code path. // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %t -DFOOBAR -DMAIN -// RUN: rm -rf %T/coverage-missing -// RUN: mkdir -p %T/coverage-missing -// RUN: cd %T/coverage-missing -// RUN: %env_asan_opts=coverage=1:coverage_dir=%T/coverage-missing %run %t +// RUN: rm -rf %t-dir +// RUN: mkdir -p %t-dir +// RUN: cd %t-dir +// RUN: %env_asan_opts=coverage=1:coverage_dir=%t-dir %run %t // RUN: %sancov print *.sancov > main.txt // RUN: rm *.sancov // RUN: count 1 < main.txt -// RUN: %env_asan_opts=coverage=1:coverage_dir=%T/coverage-missing %run %t x +// RUN: %env_asan_opts=coverage=1:coverage_dir=%t-dir %run %t x // RUN: %sancov print *.sancov > foo.txt // RUN: rm *.sancov // RUN: count 3 < foo.txt -// RUN: %env_asan_opts=coverage=1:coverage_dir=%T/coverage-missing %run %t x x +// RUN: %env_asan_opts=coverage=1:coverage_dir=%t-dir %run %t x x // RUN: %sancov print *.sancov > bar.txt // RUN: rm *.sancov // RUN: count 4 < bar.txt @@ -26,18 +26,18 @@ // RUN: not grep "^<" %t.log // Second case: coverage from DSO. -// cd %T +// cd %t-dir // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %dynamiclib -DFOOBAR -shared -fPIC // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %dynamiclib -o %t -DMAIN // RUN: cd .. -// RUN: rm -rf %T/coverage-missing -// RUN: mkdir -p %T/coverage-missing -// RUN: cd %T/coverage-missing -// RUN: %env_asan_opts=coverage=1:coverage_dir=%T/coverage-missing %run %t x +// RUN: rm -rf %t-dir +// RUN: mkdir -p %t-dir +// RUN: cd %t-dir +// RUN: %env_asan_opts=coverage=1:coverage_dir=%t-dir %run %t x // RUN: %sancov print %xdynamiclib_filename.*.sancov > foo.txt // RUN: rm *.sancov // RUN: count 2 < foo.txt -// RUN: %env_asan_opts=coverage=1:coverage_dir=%T/coverage-missing %run %t x x +// RUN: %env_asan_opts=coverage=1:coverage_dir=%t-dir %run %t x x // RUN: %sancov print %xdynamiclib_filename.*.sancov > bar.txt // RUN: rm *.sancov // RUN: count 3 < bar.txt diff --git a/test/asan/TestCases/Linux/interception_readdir_r_test.cc b/test/asan/TestCases/Linux/interception_readdir_r_test.cc index 93b553c3744f..987dff27523a 100644 --- a/test/asan/TestCases/Linux/interception_readdir_r_test.cc +++ b/test/asan/TestCases/Linux/interception_readdir_r_test.cc @@ -1,15 +1,18 @@ // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 // XFAIL: android + +// RUN: rm -rf %t-dir +// RUN: mkdir -p %t-dir // -// RUN: %clangxx_asan -O0 %s -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -O1 %s -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -O2 %s -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -O3 %s -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O0 %s -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O1 %s -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O2 %s -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O3 %s -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s // -// RUN: %clangxx_asan -O0 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -O1 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -O2 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -O3 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O0 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O1 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O2 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -O3 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s #include <dirent.h> #include <memory.h> diff --git a/test/asan/TestCases/Linux/local_alias.cc b/test/asan/TestCases/Linux/local_alias.cc index 8c80f878594d..266d3fe6bc8f 100644 --- a/test/asan/TestCases/Linux/local_alias.cc +++ b/test/asan/TestCases/Linux/local_alias.cc @@ -7,10 +7,6 @@ // FIXME: https://github.com/google/sanitizers/issues/316 // XFAIL: android // -// This test requires the integrated assembler to be the default. -// XFAIL: target-is-mips64 -// XFAIL: target-is-mips64el -// // RUN: %clangxx_asan -DBUILD_INSTRUMENTED_DSO=1 -fPIC -shared -mllvm -asan-use-private-alias %s -o %t-INSTRUMENTED-SO.so // RUN: %clangxx -DBUILD_UNINSTRUMENTED_DSO=1 -fPIC -shared %s -o %t-UNINSTRUMENTED-SO.so // RUN: %clangxx %s -c -mllvm -asan-use-private-alias -o %t.o diff --git a/test/asan/TestCases/Linux/long-object-path.cc b/test/asan/TestCases/Linux/long-object-path.cc new file mode 100644 index 000000000000..592b0abb07d7 --- /dev/null +++ b/test/asan/TestCases/Linux/long-object-path.cc @@ -0,0 +1,7 @@ +// RUN: mkdir -p %T/a-long-directory-name-to-test-allocations-for-exceptions-in-_dl_lookup_symbol_x-since-glibc-2.27 +// RUN: %clangxx_asan -g %s -o %T/long-object-path +// RUN: %run %T/a-*/../a-*/../a-*/../a-*/../a-*/../a-*/../a-*/../a-*/../long-object-path + +int main(void) { + return 0; +} diff --git a/test/asan/TestCases/Linux/odr-violation.cc b/test/asan/TestCases/Linux/odr-violation.cc index d909143a86a1..70437a8321b9 100644 --- a/test/asan/TestCases/Linux/odr-violation.cc +++ b/test/asan/TestCases/Linux/odr-violation.cc @@ -1,10 +1,6 @@ // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 // XFAIL: android // -// This test requires the integrated assembler to be the default. -// XFAIL: target-is-mips64 -// XFAIL: target-is-mips64el -// // We use fast_unwind_on_malloc=0 to have full unwinding even w/o frame // pointers. This setting is not on by default because it's too expensive. // diff --git a/test/asan/TestCases/Linux/pvalloc-overflow.cc b/test/asan/TestCases/Linux/pvalloc-overflow.cc deleted file mode 100644 index b47c6266b93b..000000000000 --- a/test/asan/TestCases/Linux/pvalloc-overflow.cc +++ /dev/null @@ -1,41 +0,0 @@ -// RUN: %clangxx_asan %s -o %t -// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %run %t m1 2>&1 | FileCheck %s -// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %run %t m1 2>&1 -// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %run %t psm1 2>&1 | FileCheck %s -// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %run %t psm1 2>&1 - -// UNSUPPORTED: freebsd, android - -// Checks that pvalloc overflows are caught. If the allocator is allowed to -// return null, the errno should be set to ENOMEM. - -#include <assert.h> -#include <errno.h> -#include <malloc.h> -#include <stdint.h> -#include <string.h> -#include <unistd.h> - -int main(int argc, char *argv[]) { - void *p; - size_t page_size; - - assert(argc == 2); - - page_size = sysconf(_SC_PAGESIZE); - - if (!strcmp(argv[1], "m1")) { - p = pvalloc((uintptr_t)-1); - assert(!p); - assert(errno == ENOMEM); - } - if (!strcmp(argv[1], "psm1")) { - p = pvalloc((uintptr_t)-(page_size - 1)); - assert(!p); - assert(errno == ENOMEM); - } - - return 0; -} - -// CHECK: AddressSanitizer's allocator is terminating the process diff --git a/test/asan/TestCases/Linux/quarantine_size_mb.cc b/test/asan/TestCases/Linux/quarantine_size_mb.cc index 239eeabee170..f7bccbfbe8db 100644 --- a/test/asan/TestCases/Linux/quarantine_size_mb.cc +++ b/test/asan/TestCases/Linux/quarantine_size_mb.cc @@ -5,6 +5,10 @@ // RUN: %env_asan_opts=quarantine_size_mb=10:quarantine_size=20:verbosity=1 not %run %t 2>&1 | FileCheck %s --check-prefix=BOTH // RUN: %env_asan_opts=quarantine_size_mb=1000:hard_rss_limit_mb=50 not %run %t 2>&1 | FileCheck %s --check-prefix=RSS_LIMIT // RUN: %env_asan_opts=hard_rss_limit_mb=20 not %run %t 2>&1 | FileCheck %s --check-prefix=RSS_LIMIT + +// https://github.com/google/sanitizers/issues/981 +// UNSUPPORTED: android-26 + #include <string.h> char *g; diff --git a/test/asan/TestCases/Linux/stack-trace-dlclose.cc b/test/asan/TestCases/Linux/stack-trace-dlclose.cc index e604f1e4f73f..899e0dfc6bda 100644 --- a/test/asan/TestCases/Linux/stack-trace-dlclose.cc +++ b/test/asan/TestCases/Linux/stack-trace-dlclose.cc @@ -1,8 +1,10 @@ // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 // XFAIL: android // -// RUN: %clangxx_asan -DSHARED %s -shared -o %T/stack_trace_dlclose.so -fPIC -// RUN: %clangxx_asan -DSO_DIR=\"%T\" %s %libdl -o %t +// RUN: rm -rf %t-dir +// RUN: mkdir -p %t-dir +// RUN: %clangxx_asan -DSHARED %s -shared -o %t-dir/stack_trace_dlclose.so -fPIC +// RUN: %clangxx_asan -DSO_DIR=\"%t-dir\" %s %libdl -o %t // RUN: %env_asan_opts=exitcode=0 %run %t 2>&1 | FileCheck %s // REQUIRES: stable-runtime diff --git a/test/asan/TestCases/Linux/syscalls.cc b/test/asan/TestCases/Linux/syscalls.cc index bcdd5bc82119..ec14bca76129 100644 --- a/test/asan/TestCases/Linux/syscalls.cc +++ b/test/asan/TestCases/Linux/syscalls.cc @@ -1,6 +1,3 @@ -// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 -// XFAIL: android -// // RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s diff --git a/test/asan/TestCases/Posix/asan-sigbus.cpp b/test/asan/TestCases/Posix/asan-sigbus.cpp index c91ecbd756f6..baf1e4266866 100644 --- a/test/asan/TestCases/Posix/asan-sigbus.cpp +++ b/test/asan/TestCases/Posix/asan-sigbus.cpp @@ -5,6 +5,8 @@ // RUN: %env_asan_opts=handle_sigbus=0 not --crash %run %t 2>&1 | FileCheck %s // UNSUPPORTED: ios +// Instead of getting a SIGBUS error, we get a SIGSEGV +// XFAIL: freebsd #include <assert.h> #include <fcntl.h> @@ -14,6 +16,10 @@ #include <unistd.h> #include <string> +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + char array[4096]; int main(int argc, char **argv) { int fd = open((std::string(argv[0]) + ".m").c_str(), O_RDWR | O_CREAT, 0700); diff --git a/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc b/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc index 22c03e8ddced..3f93122e9099 100644 --- a/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc +++ b/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc @@ -1,4 +1,4 @@ // Test that asan_symbolize does not hang when provided with an non-existing // path. -// RUN: echo '#0 0xabcdabcd (%T/bad/path+0x1234)' | %asan_symbolize | FileCheck %s +// RUN: echo '#0 0xabcdabcd (%t/bad/path+0x1234)' | %asan_symbolize | FileCheck %s // CHECK: #0 0xabcdabcd diff --git a/test/asan/TestCases/Posix/concurrent_overflow.cc b/test/asan/TestCases/Posix/concurrent_overflow.cc index e9b9899c31a2..345b546851ba 100644 --- a/test/asan/TestCases/Posix/concurrent_overflow.cc +++ b/test/asan/TestCases/Posix/concurrent_overflow.cc @@ -20,11 +20,12 @@ static void *start_routine(void *arg) { int main(void) { const int n_threads = 8; int i, counter = n_threads; - pthread_t thread; + pthread_t thread[n_threads]; for (i = 0; i < n_threads; ++i) - pthread_create(&thread, NULL, &start_routine, (void *)&counter); - sleep(5); + pthread_create(&thread[i], NULL, &start_routine, (void *)&counter); + for (i = 0; i < n_threads; ++i) + pthread_join(thread[i], NULL); return 0; } diff --git a/test/asan/TestCases/Posix/coverage-fork.cc b/test/asan/TestCases/Posix/coverage-fork.cc index da6e3c2c1b38..22d2e35842a8 100644 --- a/test/asan/TestCases/Posix/coverage-fork.cc +++ b/test/asan/TestCases/Posix/coverage-fork.cc @@ -1,6 +1,6 @@ // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %t -// RUN: rm -rf %T/coverage-fork -// RUN: mkdir -p %T/coverage-fork && cd %T/coverage-fork +// RUN: rm -rf %t-dir +// RUN: mkdir -p %t-dir && cd %t-dir // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s // // UNSUPPORTED: android diff --git a/test/asan/TestCases/Posix/coverage-reset.cc b/test/asan/TestCases/Posix/coverage-reset.cc index 201bf8e53252..6d76a309b76f 100644 --- a/test/asan/TestCases/Posix/coverage-reset.cc +++ b/test/asan/TestCases/Posix/coverage-reset.cc @@ -1,6 +1,6 @@ // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %ld_flags_rpath_exe -o %t -// RUN: rm -rf %T/coverage-reset && mkdir -p %T/coverage-reset && cd %T/coverage-reset +// RUN: rm -rf %t-dir && mkdir -p %t-dir && cd %t-dir // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s // // UNSUPPORTED: ios diff --git a/test/asan/TestCases/Posix/coverage.cc b/test/asan/TestCases/Posix/coverage.cc index a78560a72a00..12a88402eb5a 100644 --- a/test/asan/TestCases/Posix/coverage.cc +++ b/test/asan/TestCases/Posix/coverage.cc @@ -1,6 +1,6 @@ // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %ld_flags_rpath_exe -o %t -// RUN: rm -rf %T/coverage && mkdir -p %T/coverage && cd %T/coverage +// RUN: rm -rf %t-dir && mkdir -p %t-dir && cd %t-dir // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-main // RUN: %sancov print coverage.*sancov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV1 // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-foo @@ -14,7 +14,7 @@ // RUN: %sancov print merged-cov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2 // RUN: %env_asan_opts=coverage=1:verbosity=1 not %run %t foo bar 4 2>&1 | FileCheck %s --check-prefix=CHECK-report // RUN: %env_asan_opts=coverage=1:verbosity=1 not %run %t foo bar 4 5 2>&1 | FileCheck %s --check-prefix=CHECK-segv -// RUN: rm -r %T/coverage +// RUN: cd .. && rm -rf %t-dir // // https://code.google.com/p/address-sanitizer/issues/detail?id=263 // XFAIL: android diff --git a/test/asan/TestCases/Posix/fgets_fputs.cc b/test/asan/TestCases/Posix/fgets_fputs.cc new file mode 100644 index 000000000000..34c952f2e02e --- /dev/null +++ b/test/asan/TestCases/Posix/fgets_fputs.cc @@ -0,0 +1,54 @@ +// RUN: %clangxx_asan -g %s -o %t +// RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-FGETS +// RUN: not %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-FPUTS +// RUN: not %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK-PUTS + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int test_fgets(const char *testfile) { + char buf[2]; + FILE *fp = fopen(testfile, "r"); + assert(fp); + fgets(buf, sizeof(buf) + 1, fp); // BOOM + fclose(fp); + return 0; +} + +int test_fputs() { + char buf[1] = {'x'}; // Note: not nul-terminated + FILE *fp = fopen("/dev/null", "w"); + assert(fp); + fputs(buf, fp); // BOOM + fclose(fp); + return 0; +} + +int test_puts() { + char *p = strdup("x"); + free(p); + puts(p); // BOOM + return 0; +} + +int main(int argc, char *argv[]) { + assert(argc >= 2); + int testno = argv[1][0] - '0'; + if (testno == 1) { + return test_fgets(argv[0]); + } + if (testno == 2) + return test_fputs(); + if (testno == 3) + return test_puts(); + return 1; +} + +// CHECK-FGETS: {{.*ERROR: AddressSanitizer: stack-buffer-overflow}} +// CHECK-FGETS: #{{.*}} in {{(wrap_|__interceptor_)?}}fgets +// CHECK-FPUTS: {{.*ERROR: AddressSanitizer: stack-buffer-overflow}} +// CHECK-FPUTS: #{{.*}} in {{(wrap_|__interceptor_)?}}fputs +// CHECK-PUTS: {{.*ERROR: AddressSanitizer: heap-use-after-free}} +// CHECK-PUTS: #{{.*}} in {{(wrap_|__interceptor_)?}}puts diff --git a/test/asan/TestCases/Posix/fread_fwrite.cc b/test/asan/TestCases/Posix/fread_fwrite.cc index c0629260418a..640248860179 100644 --- a/test/asan/TestCases/Posix/fread_fwrite.cc +++ b/test/asan/TestCases/Posix/fread_fwrite.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_asan -g %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-FWRITE // RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-FREAD +// +// On FreeBSD stack overflow error instead +// XFAIL: freebsd #include <stdio.h> #include <stdlib.h> diff --git a/test/asan/TestCases/Posix/glob.cc b/test/asan/TestCases/Posix/glob.cc index 46d4a0d8d43d..16b4ace8efc5 100644 --- a/test/asan/TestCases/Posix/glob.cc +++ b/test/asan/TestCases/Posix/glob.cc @@ -4,7 +4,6 @@ // // RUN: %clangxx_asan -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s // RUN: %clangxx_asan -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s -// XFAIL: arm-linux-gnueabi #include <assert.h> #include <glob.h> diff --git a/test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc b/test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc index 28be9b59117b..ee8a1c70cf03 100644 --- a/test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc +++ b/test/asan/TestCases/Posix/invalid-pointer-pairs-threads.cc @@ -1,7 +1,7 @@ // RUN: %clangxx_asan -O0 %s -pthread -o %t -mllvm -asan-detect-invalid-pointer-pair -// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t a 2>&1 | FileCheck %s -check-prefix=OK -allow-empty -// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 not %run %t b 2>&1 | FileCheck %s -check-prefix=B +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=2 %run %t a 2>&1 | FileCheck %s -check-prefix=OK -allow-empty +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=2 not %run %t b 2>&1 | FileCheck %s -check-prefix=B // pthread barriers are not available on OS X // UNSUPPORTED: darwin diff --git a/test/asan/TestCases/Posix/ioctl.cc b/test/asan/TestCases/Posix/ioctl.cc index 6cf9fa8e3cd3..7269dfddb9b3 100644 --- a/test/asan/TestCases/Posix/ioctl.cc +++ b/test/asan/TestCases/Posix/ioctl.cc @@ -10,6 +10,10 @@ #include <sys/socket.h> #include <unistd.h> +#if defined(__sun__) && defined(__svr4__) +#include <sys/filio.h> +#endif + int main(int argc, char **argv) { int fd = socket(AF_INET, SOCK_DGRAM, 0); diff --git a/test/asan/TestCases/Posix/lto-constmerge-odr.cc b/test/asan/TestCases/Posix/lto-constmerge-odr.cc new file mode 100644 index 000000000000..9dc1397f6f0e --- /dev/null +++ b/test/asan/TestCases/Posix/lto-constmerge-odr.cc @@ -0,0 +1,14 @@ +// RUN: %clangxx_asan -O3 -flto %s -o %t +// RUN: %run %t 2>&1 + +// REQUIRES: lto + +int main(int argc, const char * argv[]) { + struct { long width, height; } a = {16, 16}; + struct { long width, height; } b = {16, 16}; + + // Just to make sure 'a' and 'b' don't get optimized out. + asm volatile("" : : "r" (&a), "r" (&b)); + + return 0; +} diff --git a/test/asan/TestCases/Posix/mmap_limit_mb.cc b/test/asan/TestCases/Posix/mmap_limit_mb.cc index 379524121a88..508c03fbcb16 100644 --- a/test/asan/TestCases/Posix/mmap_limit_mb.cc +++ b/test/asan/TestCases/Posix/mmap_limit_mb.cc @@ -9,7 +9,7 @@ // RUN: %env_asan_opts=mmap_limit_mb=300 not %run %t 500 1000000 2>&1 | FileCheck %s // // FIXME: Windows doesn't implement mmap_limit_mb. -// XFAIL: arm-linux-gnueabi,win32 +// XFAIL: win32 #include <assert.h> #include <stdlib.h> diff --git a/test/asan/TestCases/Posix/no_asan_gen_globals.c b/test/asan/TestCases/Posix/no_asan_gen_globals.c index c686f83ac4a8..994f827974be 100644 --- a/test/asan/TestCases/Posix/no_asan_gen_globals.c +++ b/test/asan/TestCases/Posix/no_asan_gen_globals.c @@ -1,12 +1,10 @@ // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 // XFAIL: android -// FIXME: http://llvm.org/bugs/show_bug.cgi?id=22682 -// REQUIRES: asan-64-bits -// Make sure __asan_gen_* strings do not end up in the symbol table. +// Make sure ___asan_gen_* strings do not end up in the symbol table. // RUN: %clang_asan %s -o %t.exe // RUN: nm %t.exe | FileCheck %s int x, y, z; int main() { return 0; } -// CHECK-NOT: __asan_gen_ +// CHECK-NOT: ___asan_gen_ diff --git a/test/asan/TestCases/Posix/shared-lib-test.cc b/test/asan/TestCases/Posix/shared-lib-test.cc index 305942a0792d..6de6d9fdfe5b 100644 --- a/test/asan/TestCases/Posix/shared-lib-test.cc +++ b/test/asan/TestCases/Posix/shared-lib-test.cc @@ -6,7 +6,6 @@ // RUN: %clangxx_asan -O2 %s %libdl -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -O3 -DSHARED_LIB %s -fPIC -shared -o %t-so.so // RUN: %clangxx_asan -O3 %s %libdl -o %t && not %run %t 2>&1 | FileCheck %s -// XFAIL: arm-linux-gnueabi #if !defined(SHARED_LIB) #include <dlfcn.h> diff --git a/test/asan/TestCases/Posix/stack-use-after-return.cc b/test/asan/TestCases/Posix/stack-use-after-return.cc index 2da1a0590db7..237c880f8e61 100644 --- a/test/asan/TestCases/Posix/stack-use-after-return.cc +++ b/test/asan/TestCases/Posix/stack-use-after-return.cc @@ -16,9 +16,11 @@ // This test runs out of stack on AArch64. // UNSUPPORTED: aarch64 +// stack size log lower than expected +// XFAIL: freebsd -// FIXME: Fix this test for dynamic runtime on armhf-linux. -// UNSUPPORTED: armhf-linux && asan-dynamic-runtime +// FIXME: Fix this test for dynamic runtime on arm linux. +// UNSUPPORTED: (arm-linux || armhf-linux) && asan-dynamic-runtime #include <limits.h> #include <pthread.h> @@ -95,7 +97,7 @@ int main(int argc, char **argv) { if (stacksize_check != desired_stack_size) { fprintf(stderr, "Unable to set stack size to %d, the stack size is %d.\n", - desired_stack_size, stacksize_check); + (int)desired_stack_size, (int)stacksize_check); abort(); } } diff --git a/test/asan/TestCases/Posix/start-deactivated.cc b/test/asan/TestCases/Posix/start-deactivated.cc index 2870ffb2f454..736d7f698b17 100644 --- a/test/asan/TestCases/Posix/start-deactivated.cc +++ b/test/asan/TestCases/Posix/start-deactivated.cc @@ -18,7 +18,6 @@ // RUN: %env_asan_opts=start_deactivated=1 \ // RUN: ASAN_ACTIVATION_OPTIONS=help=1,handle_segv=0,verbosity=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORTED -// XFAIL: arm-linux-gnueabi // UNSUPPORTED: ios // END. diff --git a/test/asan/TestCases/Posix/strndup_oob_test.cc b/test/asan/TestCases/Posix/strndup_oob_test.cc index 7ea0b7a33400..326ddcfd6b06 100644 --- a/test/asan/TestCases/Posix/strndup_oob_test.cc +++ b/test/asan/TestCases/Posix/strndup_oob_test.cc @@ -7,7 +7,7 @@ // RUN: %clangxx_asan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck %s // Unwind problem on arm: "main" is missing from the allocation stack trace. -// UNSUPPORTED: win32,s390,armv7l-unknown-linux-gnueabihf +// UNSUPPORTED: win32,s390,arm && !fast-unwinder-works #include <string.h> diff --git a/test/asan/TestCases/Posix/strndup_oob_test2.cc b/test/asan/TestCases/Posix/strndup_oob_test2.cc index 903f5e65f98f..44df6bda9c83 100644 --- a/test/asan/TestCases/Posix/strndup_oob_test2.cc +++ b/test/asan/TestCases/Posix/strndup_oob_test2.cc @@ -7,7 +7,7 @@ // RUN: %clang_asan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck %s // Unwind problem on arm: "main" is missing from the allocation stack trace. -// UNSUPPORTED: win32,s390,armv7l-unknown-linux-gnueabihf +// UNSUPPORTED: win32,s390,arm && !fast-unwinder-works #include <string.h> @@ -19,4 +19,4 @@ int main(int argc, char **argv) { // CHECK: AddressSanitizer: global-buffer-overflow // CHECK: {{.*}}main {{.*}}.cc:[[@LINE-2]] return *copy; -}
\ No newline at end of file +} diff --git a/test/asan/TestCases/Windows/coverage-basic.cc b/test/asan/TestCases/Windows/coverage-basic.cc index 918872f18f91..1469e1c30ae3 100644 --- a/test/asan/TestCases/Windows/coverage-basic.cc +++ b/test/asan/TestCases/Windows/coverage-basic.cc @@ -1,5 +1,5 @@ -// RUN: rm -rf %T/coverage-basic -// RUN: mkdir %T/coverage-basic && cd %T/coverage-basic +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir && cd %t-dir // RUN: %clangxx_asan -fsanitize-coverage=func %s -o test.exe // RUN: %env_asan_opts=coverage=1 %run ./test.exe // diff --git a/test/asan/TestCases/Windows/fuse-lld-globals.cc b/test/asan/TestCases/Windows/fuse-lld-globals.cc new file mode 100644 index 000000000000..4148d562fb40 --- /dev/null +++ b/test/asan/TestCases/Windows/fuse-lld-globals.cc @@ -0,0 +1,18 @@ +// RUN: %clangxx_asan -fuse-ld=lld -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s + +#include <string.h> +int main(int argc, char **argv) { + static char XXX[10]; + static char YYY[10]; + static char ZZZ[10]; + memset(XXX, 0, 10); + memset(YYY, 0, 10); + memset(ZZZ, 0, 10); + int res = YYY[argc * 10]; // BOOOM + // CHECK: {{READ of size 1 at 0x.* thread T0}} + // CHECK: {{ #0 0x.* in main .*fuse-lld-globals.cc:}}[[@LINE-2]] + // CHECK: {{0x.* is located 0 bytes to the right of global variable}} + // CHECK: {{.*YYY.* of size 10}} + res += XXX[argc] + ZZZ[argc]; + return res; +} diff --git a/test/asan/TestCases/Windows/oom.cc b/test/asan/TestCases/Windows/oom.cc index 71a9c2a759a9..4d68c145eca7 100644 --- a/test/asan/TestCases/Windows/oom.cc +++ b/test/asan/TestCases/Windows/oom.cc @@ -8,5 +8,5 @@ int main() { while (true) { void *ptr = malloc(200 * 1024 * 1024); // 200MB } -// CHECK: allocator is terminating the process instead of returning 0 +// CHECK: SUMMARY: AddressSanitizer: out-of-memory } diff --git a/test/asan/TestCases/Windows/user-exception.cc b/test/asan/TestCases/Windows/user-exception.cc new file mode 100644 index 000000000000..4cff23fbc02f --- /dev/null +++ b/test/asan/TestCases/Windows/user-exception.cc @@ -0,0 +1,36 @@ +// RUN: %clang_cl_asan -O0 %s -Fe%t +// RUN: env ASAN_OPTIONS=handle_segv=0 %run %t 2>&1 | FileCheck %s --check-prefix=USER +// RUN: env ASAN_OPTIONS=handle_segv=1 not %run %t 2>&1 | FileCheck %s --check-prefix=ASAN +// Test the default. +// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=ASAN + +// This test exits zero when its unhandled exception filter is set. ASan should +// not disturb it when handle_segv=0. + +// USER: in main +// USER: in SEHHandler + +// ASAN: in main +// ASAN: ERROR: AddressSanitizer: access-violation + +#include <windows.h> +#include <stdio.h> + +static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) { + DWORD exception_code = info->ExceptionRecord->ExceptionCode; + if (exception_code == EXCEPTION_ACCESS_VIOLATION) { + fprintf(stderr, "in SEHHandler\n"); + fflush(stderr); + TerminateProcess(GetCurrentProcess(), 0); + } + return EXCEPTION_CONTINUE_SEARCH; +} + +int main() { + SetUnhandledExceptionFilter(SEHHandler); + fprintf(stderr, "in main\n"); + fflush(stderr); + + volatile int *p = nullptr; + *p = 42; +} diff --git a/test/asan/TestCases/alloca_constant_size.cc b/test/asan/TestCases/alloca_constant_size.cc index 57aa315705f9..8910ea9f8d8e 100644 --- a/test/asan/TestCases/alloca_constant_size.cc +++ b/test/asan/TestCases/alloca_constant_size.cc @@ -6,13 +6,14 @@ #include <stdio.h> #include <string.h> +#include <stdlib.h> // MSVC provides _alloca instead of alloca. #if defined(_MSC_VER) && !defined(alloca) # define alloca _alloca -#elif defined(__FreeBSD__) || defined(__NetBSD__) -#include <stdlib.h> -#else +#endif + +#if defined(__sun__) && defined(__svr4__) #include <alloca.h> #endif diff --git a/test/asan/TestCases/alloca_loop_unpoisoning.cc b/test/asan/TestCases/alloca_loop_unpoisoning.cc index 1efada10979a..f9d32aafdc8f 100644 --- a/test/asan/TestCases/alloca_loop_unpoisoning.cc +++ b/test/asan/TestCases/alloca_loop_unpoisoning.cc @@ -15,6 +15,10 @@ # define alloca _alloca #endif +#if defined(__sun__) && defined(__svr4__) +#include <alloca.h> +#endif + void *top, *bot; __attribute__((noinline)) void foo(int len) { diff --git a/test/asan/TestCases/alloca_vla_interact.cc b/test/asan/TestCases/alloca_vla_interact.cc index 4717c9d977ed..92b0afafc8db 100644 --- a/test/asan/TestCases/alloca_vla_interact.cc +++ b/test/asan/TestCases/alloca_vla_interact.cc @@ -15,6 +15,10 @@ # define alloca _alloca #endif +#if defined(__sun__) && defined(__svr4__) +#include <alloca.h> +#endif + #define RZ 32 __attribute__((noinline)) void foo(int len) { diff --git a/test/asan/TestCases/allocator_returns_null.cc b/test/asan/TestCases/allocator_returns_null.cc deleted file mode 100644 index 8ce002f04d61..000000000000 --- a/test/asan/TestCases/allocator_returns_null.cc +++ /dev/null @@ -1,131 +0,0 @@ -// Test the behavior of malloc/calloc/realloc/new when the allocation size is -// more than ASan allocator's max allowed one. -// By default (allocator_may_return_null=0) the process should crash. -// With allocator_may_return_null=1 the allocator should return 0, except the -// operator new(), which should crash anyway (operator new(std::nothrow) should -// return nullptr, indeed). -// -// RUN: %clangxx_asan -O0 %s -o %t -// RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mNULL -// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-cCRASH -// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t calloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-cNULL -// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-coCRASH -// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t calloc-overflow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-coNULL -// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-rCRASH -// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t realloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-rNULL -// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mrCRASH -// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t realloc-after-malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mrNULL -// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t new 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH -// RUN: %env_asan_opts=allocator_may_return_null=1 not %run %t new 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH -// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH -// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nnNULL - -// UNSUPPORTED: win32 - -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <limits> -#include <new> - -int main(int argc, char **argv) { - // Disable stderr buffering. Needed on Windows. - setvbuf(stderr, NULL, _IONBF, 0); - - assert(argc == 2); - const char *action = argv[1]; - fprintf(stderr, "%s:\n", action); - - static const size_t kMaxAllowedMallocSizePlusOne = -#if __LP64__ || defined(_WIN64) - (1ULL << 40) + 1; -#else - (3UL << 30) + 1; -#endif - - void *x = 0; - if (!strcmp(action, "malloc")) { - x = malloc(kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "calloc")) { - x = calloc((kMaxAllowedMallocSizePlusOne / 4) + 1, 4); - } else if (!strcmp(action, "calloc-overflow")) { - volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max(); - size_t kArraySize = 4096; - volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10; - x = calloc(kArraySize, kArraySize2); - } else if (!strcmp(action, "realloc")) { - x = realloc(0, kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "realloc-after-malloc")) { - char *t = (char*)malloc(100); - *t = 42; - x = realloc(t, kMaxAllowedMallocSizePlusOne); - assert(*t == 42); - free(t); - } else if (!strcmp(action, "new")) { - x = operator new(kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "new-nothrow")) { - x = operator new(kMaxAllowedMallocSizePlusOne, std::nothrow); - } else { - assert(0); - } - - fprintf(stderr, "errno: %d\n", errno); - - // The NULL pointer is printed differently on different systems, while (long)0 - // is always the same. - fprintf(stderr, "x: %lx\n", (long)x); - free(x); - - return x != 0; -} - -// CHECK-mCRASH: malloc: -// CHECK-mCRASH: AddressSanitizer's allocator is terminating the process -// CHECK-cCRASH: calloc: -// CHECK-cCRASH: AddressSanitizer's allocator is terminating the process -// CHECK-coCRASH: calloc-overflow: -// CHECK-coCRASH: AddressSanitizer's allocator is terminating the process -// CHECK-rCRASH: realloc: -// CHECK-rCRASH: AddressSanitizer's allocator is terminating the process -// CHECK-mrCRASH: realloc-after-malloc: -// CHECK-mrCRASH: AddressSanitizer's allocator is terminating the process -// CHECK-nCRASH: new: -// CHECK-nCRASH: AddressSanitizer's allocator is terminating the process -// CHECK-nnCRASH: new-nothrow: -// CHECK-nnCRASH: AddressSanitizer's allocator is terminating the process - -// CHECK-mNULL: malloc: -// CHECK-mNULL: errno: 12 -// CHECK-mNULL: x: 0 -// CHECK-cNULL: calloc: -// CHECK-cNULL: errno: 12 -// CHECK-cNULL: x: 0 -// CHECK-coNULL: calloc-overflow: -// CHECK-coNULL: errno: 12 -// CHECK-coNULL: x: 0 -// CHECK-rNULL: realloc: -// CHECK-rNULL: errno: 12 -// CHECK-rNULL: x: 0 -// CHECK-mrNULL: realloc-after-malloc: -// CHECK-mrNULL: errno: 12 -// CHECK-mrNULL: x: 0 -// CHECK-nnNULL: new-nothrow: -// CHECK-nnNULL: x: 0 diff --git a/test/asan/TestCases/calloc-overflow.cc b/test/asan/TestCases/calloc-overflow.cc new file mode 100644 index 000000000000..74582378fd2f --- /dev/null +++ b/test/asan/TestCases/calloc-overflow.cc @@ -0,0 +1,21 @@ +// RUN: %clangxx_asan -O0 %s -o %t +// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL + +// REQUIRES: stable-runtime + +#include <stdio.h> +#include <stdlib.h> + +int main() { + void *p = calloc(-1, 1000); + // CHECK: {{ERROR: AddressSanitizer: calloc parameters overflow: count \* size \(.* \* 1000\) cannot be represented in type size_t}} + // CHECK: {{#0 0x.* in .*calloc}} + // CHECK: {{#1 0x.* in main .*calloc-overflow.cc:}}[[@LINE-3]] + // CHECK: SUMMARY: AddressSanitizer: calloc-overflow + + printf("calloc returned: %zu\n", (size_t)p); + // CHECK-NULL: calloc returned: 0 + + return 0; +} diff --git a/test/asan/TestCases/coverage-and-lsan.cc b/test/asan/TestCases/coverage-and-lsan.cc index 591b4e93fac7..60851dabb6b7 100644 --- a/test/asan/TestCases/coverage-and-lsan.cc +++ b/test/asan/TestCases/coverage-and-lsan.cc @@ -2,11 +2,11 @@ // // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s -o %t // -// RUN: rm -rf %T/coverage-and-lsan +// RUN: rm -rf %t-dir // -// RUN: mkdir -p %T/coverage-and-lsan/normal -// RUN: %env_asan_opts=coverage=1:coverage_dir=%T/coverage-and-lsan:verbosity=1 not %run %t 2>&1 | FileCheck %s -// RUN: %sancov print %T/coverage-and-lsan/*.sancov 2>&1 +// RUN: mkdir -p %t-dir +// RUN: %env_asan_opts=coverage=1:coverage_dir=%t-dir:verbosity=1 not %run %t 2>&1 | FileCheck %s +// RUN: %sancov print %t-dir/*.sancov 2>&1 // // REQUIRES: leak-detection diff --git a/test/asan/TestCases/coverage-disabled.cc b/test/asan/TestCases/coverage-disabled.cc index b225035ee4ca..46a822dff08c 100644 --- a/test/asan/TestCases/coverage-disabled.cc +++ b/test/asan/TestCases/coverage-disabled.cc @@ -1,12 +1,12 @@ // Test that no data is collected without a runtime flag. // -// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t +// RUN: rm -rf %t-dir +// RUN: mkdir -p %t-dir // -// RUN: rm -rf %T/coverage-disabled +// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t // -// RUN: mkdir -p %T/coverage-disabled/normal -// RUN: %env_asan_opts=coverage_direct=0:coverage_dir='"%T/coverage-disabled/normal"':verbosity=1 %run %t -// RUN: not %sancov print %T/coverage-disabled/normal/*.sancov 2>&1 +// RUN: %env_asan_opts=coverage_direct=0:coverage_dir='"%t-dir"':verbosity=1 %run %t +// RUN: not %sancov print %t-dir/*.sancov 2>&1 // // UNSUPPORTED: android diff --git a/test/asan/TestCases/debug_double_free.cc b/test/asan/TestCases/debug_double_free.cc index c3699b9762d8..44c820b638d6 100644 --- a/test/asan/TestCases/debug_double_free.cc +++ b/test/asan/TestCases/debug_double_free.cc @@ -15,6 +15,9 @@ # else # define PTR_FMT "0x%08x" # endif +// Solaris libc omits the leading 0x. +#elif defined(__sun__) && defined(__svr4__) +# define PTR_FMT "0x%p" #else # define PTR_FMT "%p" #endif diff --git a/test/asan/TestCases/debug_ppc64_mapping.cc b/test/asan/TestCases/debug_ppc64_mapping.cc index 0db7956693c5..a67804023c0c 100644 --- a/test/asan/TestCases/debug_ppc64_mapping.cc +++ b/test/asan/TestCases/debug_ppc64_mapping.cc @@ -6,9 +6,9 @@ #include <stdio.h> int main() { -// CHECK-PPC64: || `[{{0x180|0x0a0|0x040}}000000000, {{0x3ff|0x0ff}}fffffffff]` || HighMem || -// CHECK-PPC64: || `[{{0x130|0x034|0x028}}000000000, {{0x17f|0x09f|0x03f}}fffffffff]` || HighShadow || -// CHECK-PPC64: || `[{{0x120|0x024|0x024}}000000000, {{0x12f|0x033|0x027}}fffffffff]` || ShadowGap || +// CHECK-PPC64: || `[{{0x200|0x180|0x0a0|0x040}}000000000, {{0x7ff|0x3ff|0x0ff}}fffffffff]` || HighMem || +// CHECK-PPC64: || `[{{0x140|0x130|0x034|0x028}}000000000, {{0x1ff|0x17f|0x09f|0x03f}}fffffffff]` || HighShadow || +// CHECK-PPC64: || `[{{0x120|0x024|0x024}}000000000, {{0x12f|0x13f|0x033|0x027}}fffffffff]` || ShadowGap || // CHECK-PPC64: || `[{{0x100|0x020}}000000000, {{0x11f|0x023}}fffffffff]` || LowShadow || // CHECK-PPC64: || `[0x000000000000, {{0x0ff|0x01f}}fffffffff]` || LowMem || // @@ -19,8 +19,16 @@ int main() { } /* - * Three different signatures noted. -Newer kernel: (starting with kernel version 4.?) + * Several different signatures noted. + +Newer kernel: (Fedora starting with kernel version 4.?) +|| `[0x200000000000, 0x7fffffffffff]` || HighMem || +|| `[0x140000000000, 0x1fffffffffff]` || HighShadow || +|| `[0x120000000000, 0x13ffffffffff]` || ShadowGap || +|| `[0x100000000000, 0x11ffffffffff]` || LowShadow || +|| `[0x000000000000, 0x0fffffffffff]` || LowMem || + +Newer kernel: (Ubuntu starting with kernel version 4.?) || `[0x180000000000, 0x3fffffffffff]` || HighMem || || `[0x130000000000, 0x17ffffffffff]` || HighShadow || || `[0x120000000000, 0x12ffffffffff]` || ShadowGap || diff --git a/test/asan/TestCases/debug_report.cc b/test/asan/TestCases/debug_report.cc index 34bc06eba62c..14bb70e9f593 100644 --- a/test/asan/TestCases/debug_report.cc +++ b/test/asan/TestCases/debug_report.cc @@ -30,6 +30,9 @@ int main() { # else # define PTR_FMT "0x%08x" # endif +// Solaris libc omits the leading 0x. +#elif defined(__sun__) && defined(__svr4__) +# define PTR_FMT "0x%p" #else # define PTR_FMT "%p" #endif diff --git a/test/asan/TestCases/handle_noreturn_bug.cc b/test/asan/TestCases/handle_noreturn_bug.cc new file mode 100644 index 000000000000..8c3c66a423d5 --- /dev/null +++ b/test/asan/TestCases/handle_noreturn_bug.cc @@ -0,0 +1,13 @@ +// Regression test: __asan_handle_no_return should unpoison stack even with poison_heap=0. +// RUN: %clangxx_asan -O0 %s -o %t && \ +// RUN: %env_asan_opts=poison_heap=1 %run %t && \ +// RUN: %env_asan_opts=poison_heap=0 %run %t + +#include <sanitizer/asan_interface.h> + +int main(int argc, char **argv) { + int x[2]; + int * volatile p = &x[0]; + __asan_handle_no_return(); + int volatile z = p[2]; +} diff --git a/test/asan/TestCases/heavy_uar_test.cc b/test/asan/TestCases/heavy_uar_test.cc index 9ad29f079d92..94df0cefc73b 100644 --- a/test/asan/TestCases/heavy_uar_test.cc +++ b/test/asan/TestCases/heavy_uar_test.cc @@ -1,12 +1,12 @@ // RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s -// XFAIL: arm-linux-gnueabi,win32 +// XFAIL: win32 // FIXME: Fix this test under GCC. // REQUIRES: Clang -// FIXME: Fix this test for dynamic runtime on armhf-linux. -// UNSUPPORTED: armhf-linux && asan-dynamic-runtime +// FIXME: Fix this test for dynamic runtime on arm linux. +// UNSUPPORTED: (arm-linux || armhf-linux) && asan-dynamic-runtime // UNSUPPORTED: ios diff --git a/test/asan/TestCases/intercept-rethrow-exception.cc b/test/asan/TestCases/intercept-rethrow-exception.cc new file mode 100644 index 000000000000..fa9ea7d3b09e --- /dev/null +++ b/test/asan/TestCases/intercept-rethrow-exception.cc @@ -0,0 +1,64 @@ +// Regression test for +// https://bugs.llvm.org/show_bug.cgi?id=32434 + +// RUN: %clangxx_asan -O0 %s -o %t +// RUN: %run %t + +#include <assert.h> +#include <exception> +#include <sanitizer/asan_interface.h> + +namespace { + +// Not instrumented because std::rethrow_exception is a [[noreturn]] function, +// for which the compiler would emit a call to __asan_handle_no_return which +// unpoisons the stack. +// We emulate here some code not compiled with asan. This function is not +// [[noreturn]] because the scenario we're emulating doesn't always throw. If it +// were [[noreturn]], the calling code would emit a call to +// __asan_handle_no_return. +void __attribute__((no_sanitize("address"))) +uninstrumented_rethrow_exception(std::exception_ptr const &exc_ptr) { + std::rethrow_exception(exc_ptr); +} + +char *poisoned1; +char *poisoned2; + +// Create redzones for stack variables in shadow memory and call +// std::rethrow_exception which should unpoison the entire stack. +void create_redzones_and_throw(std::exception_ptr const &exc_ptr) { + char a[100]; + poisoned1 = a - 1; + poisoned2 = a + sizeof(a); + assert(__asan_address_is_poisoned(poisoned1)); + assert(__asan_address_is_poisoned(poisoned2)); + uninstrumented_rethrow_exception(exc_ptr); +} + +} // namespace + +// Check that std::rethrow_exception is intercepted by asan and the interception +// unpoisons the stack. +// If std::rethrow_exception is NOT intercepted, then calls to this function +// from instrumented code will still unpoison the stack because +// std::rethrow_exception is a [[noreturn]] function and any [[noreturn]] +// function call will be instrumented with __asan_handle_no_return. +// However, calls to std::rethrow_exception from UNinstrumented code will not +// unpoison the stack, so we need to intercept std::rethrow_exception to +// unpoison the stack. +int main() { + // In some implementations of std::make_exception_ptr, e.g. libstdc++ prior to + // gcc 7, this function calls __cxa_throw. The __cxa_throw is intercepted by + // asan to unpoison the entire stack; since this test essentially tests that + // the stack is unpoisoned by a call to std::rethrow_exception, we need to + // generate the exception_ptr BEFORE we have the local variables poison the + // stack. + std::exception_ptr my_exception_ptr = std::make_exception_ptr("up"); + + try { + create_redzones_and_throw(my_exception_ptr); + } catch(char const *) { + assert(!__asan_region_is_poisoned(poisoned1, poisoned2 - poisoned1 + 1)); + } +} diff --git a/test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc b/test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc index 82f63359ead7..0690d40d2261 100644 --- a/test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc +++ b/test/asan/TestCases/invalid-pointer-pairs-compare-errors.cc @@ -1,6 +1,6 @@ // RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair -// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1:halt_on_error=0 %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=2:halt_on_error=0 %run %t 2>&1 | FileCheck %s #include <assert.h> #include <stdlib.h> @@ -10,8 +10,12 @@ int foo(char *p, char *q) { } char global1[100] = {}, global2[100] = {}; +char __attribute__((used)) smallest_global[5] = {}; char small_global[7] = {}; +char __attribute__((used)) little_global[10] = {}; +char __attribute__((used)) medium_global[4000] = {}; char large_global[5000] = {}; +char __attribute__((used)) largest_global[6000] = {}; int main() { // Heap allocated memory. diff --git a/test/asan/TestCases/invalid-pointer-pairs-compare-null.cc b/test/asan/TestCases/invalid-pointer-pairs-compare-null.cc new file mode 100644 index 000000000000..9f7f7b6f439d --- /dev/null +++ b/test/asan/TestCases/invalid-pointer-pairs-compare-null.cc @@ -0,0 +1,42 @@ +// RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair + +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t + +#include <assert.h> +#include <stdlib.h> + +int foo(char *p, char *q) { + return p <= q; +} + +char global[8192] = {}; +char small_global[7] = {}; + +int main() { + // Heap allocated memory. + char *p = (char *)malloc(42); + int r = foo(p, NULL); + free(p); + + p = (char *)malloc(1024); + foo(NULL, p); + free(p); + + p = (char *)malloc(4096); + foo(p, NULL); + free(p); + + // Global variable. + foo(&global[0], NULL); + foo(&global[1000], NULL); + + p = &small_global[0]; + foo(p, NULL); + + // Stack variable. + char stack[10000]; + foo(&stack[0], NULL); + foo(NULL, &stack[9000]); + + return 0; +} diff --git a/test/asan/TestCases/invalid-pointer-pairs-compare-success.cc b/test/asan/TestCases/invalid-pointer-pairs-compare-success.cc index 565d39088340..d0d92265f002 100644 --- a/test/asan/TestCases/invalid-pointer-pairs-compare-success.cc +++ b/test/asan/TestCases/invalid-pointer-pairs-compare-success.cc @@ -1,6 +1,6 @@ // RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair -// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=2 %run %t #include <assert.h> #include <stdlib.h> diff --git a/test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc b/test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc index 546f61f8184d..20aaebeb48e0 100644 --- a/test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc +++ b/test/asan/TestCases/invalid-pointer-pairs-subtract-errors.cc @@ -1,6 +1,6 @@ // RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair -// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1:halt_on_error=0 %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=2:halt_on_error=0 %run %t 2>&1 | FileCheck %s #include <assert.h> #include <stdlib.h> diff --git a/test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc b/test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc index 4ce48424899d..7ea120ed5c70 100644 --- a/test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc +++ b/test/asan/TestCases/invalid-pointer-pairs-subtract-success.cc @@ -1,12 +1,12 @@ // RUN: %clangxx_asan -O0 %s -o %t -mllvm -asan-detect-invalid-pointer-pair -// RUN: %env_asan_opts=detect_invalid_pointer_pairs=1 %run %t +// RUN: %env_asan_opts=detect_invalid_pointer_pairs=2 %run %t #include <assert.h> #include <stdlib.h> int bar(char *p, char *q) { - return p <= q; + return p - q; } char global[10000] = {}; diff --git a/test/asan/TestCases/malloc-no-intercept.c b/test/asan/TestCases/malloc-no-intercept.c index c1442e6cfa90..ca98febed0fb 100644 --- a/test/asan/TestCases/malloc-no-intercept.c +++ b/test/asan/TestCases/malloc-no-intercept.c @@ -10,6 +10,11 @@ // Conflicts with BIONIC declarations. // UNSUPPORTED: android +// Inhibit conflicting declaration of memalign on Solaris. +#if defined(__sun__) && defined(__svr4__) +#undef __EXTENSIONS__ +#endif + #include <stdlib.h> // For glibc, cause link failures by referencing a nonexistent function. diff --git a/test/asan/TestCases/malloc-size-too-big.cc b/test/asan/TestCases/malloc-size-too-big.cc new file mode 100644 index 000000000000..f41b7ef75d71 --- /dev/null +++ b/test/asan/TestCases/malloc-size-too-big.cc @@ -0,0 +1,28 @@ +// RUN: %clangxx_asan -O0 %s -o %t +// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL + +// REQUIRES: stable-runtime + +#include <stdio.h> +#include <stdlib.h> + +static const size_t kMaxAllowedMallocSizePlusOne = +#if __LP64__ || defined(_WIN64) + (1ULL << 40) + 1; +#else + (3UL << 30) + 1; +#endif + +int main() { + void *p = malloc(kMaxAllowedMallocSizePlusOne); + // CHECK: {{ERROR: AddressSanitizer: requested allocation size .* \(.* after adjustments for alignment, red zones etc\.\) exceeds maximum supported size}} + // CHECK: {{#0 0x.* in .*malloc}} + // CHECK: {{#1 0x.* in main .*malloc-size-too-big.cc:}}[[@LINE-3]] + // CHECK: SUMMARY: AddressSanitizer: allocation-size-too-big + + printf("malloc returned: %zu\n", (size_t)p); + // CHECK-NULL: malloc returned: 0 + + return 0; +} diff --git a/test/asan/TestCases/non-executable-pc.cpp b/test/asan/TestCases/non-executable-pc.cpp index 6ef40540b0ac..60e900b87160 100644 --- a/test/asan/TestCases/non-executable-pc.cpp +++ b/test/asan/TestCases/non-executable-pc.cpp @@ -3,7 +3,10 @@ // RUN: not %run %t n 2>&1 | FileCheck %s -check-prefix=CHECK -check-prefix=NON_EXEC // Not every OS lists every memory region in MemoryMappingLayout. -// REQUIRES: linux || freebsd || netbsd +// This is limited to x86_64 because some architectures (e.g. the s390 before +// the z14) don't support NX mappings and others like PowerPC use function +// descriptors. +// REQUIRES: x86-target-arch && (linux || freebsd || netbsd) #include <assert.h> @@ -20,12 +23,6 @@ int main(int argc, char **argv) { } func(); - // x86 reports the SEGV with both address=X and pc=X. - // On PowerPC64 ELFv1, the pointer is taken to be a function-descriptor - // pointer out of which three 64-bit quantities are read. This will SEGV, but - // the compiler is free to choose the order. As a result, the address is - // either X, X+0x8 or X+0x10. The pc is still in main() because it has not - // actually made the call when the faulting access occurs. // CHECK: DEADLYSIGNAL // CHECK: {{AddressSanitizer: (SEGV|access-violation).*(address|pc) }} // NON_EXEC: PC is at a non-executable region. Maybe a wild jump? diff --git a/test/asan/TestCases/null_deref.cc b/test/asan/TestCases/null_deref.cc index 04576b40eb24..222c526fdc13 100644 --- a/test/asan/TestCases/null_deref.cc +++ b/test/asan/TestCases/null_deref.cc @@ -15,10 +15,10 @@ void NullDeref(int *ptr) { ptr[10]++; // BOOM // atos on Mac cannot extract the symbol name correctly. Also, on FreeBSD 9.2 // the demangling function rejects local names with 'L' in front of them. - // CHECK: {{ #0 0x.* in .*NullDeref.*null_deref.cc:}}[[@LINE-3]] + // CHECK: {{ #0 0x.* in .*NullDeref.*null_deref.cc}} } int main() { NullDeref((int*)0); - // CHECK: {{ #1 0x.* in main.*null_deref.cc:}}[[@LINE-1]] + // CHECK: {{ #1 0x.* in main.*null_deref.cc}} // CHECK: AddressSanitizer can not provide additional info. } diff --git a/test/asan/TestCases/printf-4.c b/test/asan/TestCases/printf-4.c index 5a883fe99efd..70f4073cc496 100644 --- a/test/asan/TestCases/printf-4.c +++ b/test/asan/TestCases/printf-4.c @@ -2,8 +2,9 @@ // RUN: %env_asan_opts=check_printf=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-ON %s // RUN: not %run %t 2>&1 | FileCheck --check-prefix=CHECK-ON %s -// FIXME: sprintf is not intercepted on Windows yet. -// XFAIL: win32 +// FIXME: sprintf is not intercepted on Windows yet. But this test can +// pass if sprintf calls memmove, which is intercepted, so we can't XFAIL it. +// UNSUPPORTED: win32 #include <stdio.h> int main() { diff --git a/test/asan/TestCases/scariness_score_test.cc b/test/asan/TestCases/scariness_score_test.cc index 171bea9ee191..fb174eb52b2b 100644 --- a/test/asan/TestCases/scariness_score_test.cc +++ b/test/asan/TestCases/scariness_score_test.cc @@ -115,7 +115,7 @@ void DoubleFree() { } void StackOverflow(int Idx) { - int some_stack[10000]; + int some_stack[256]; static volatile int *x; x = &some_stack[0]; if (Idx > 0) diff --git a/test/asan/TestCases/strcat-overlap.cc b/test/asan/TestCases/strcat-overlap.cc new file mode 100644 index 000000000000..89991fbd7881 --- /dev/null +++ b/test/asan/TestCases/strcat-overlap.cc @@ -0,0 +1,54 @@ +// RUN: %clangxx_asan -O0 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strcat" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O1 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strcat" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O2 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strcat" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O3 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strcat" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t + +// This test when run with suppressions invokes undefined +// behavior which can cause all sorts of bad things to happen +// depending on how strcat() is implemented. For now only run +// on platforms where we know the test passes. +// REQUIRES: x86_64h-darwin || x86_64-darwin || i386-darwin || x86_64-linux || i386-linux +// UNSUPPORTED: win32 +// UNSUPPORTED: android + +#include <string.h> + + +// Don't inline function otherwise stacktrace changes. +__attribute__((noinline)) void bad_function() { + char buffer[] = "hello\0XXX"; + // CHECK: strcat-param-overlap: memory ranges + // CHECK: [{{0x.*,[ ]*0x.*}}) and [{{0x.*,[ ]*0x.*}}) overlap + // CHECK: {{#0 0x.* in .*strcat}} + // CHECK: {{#1 0x.* in bad_function.*strcat-overlap.cc:}}[[@LINE+2]] + // CHECK: {{#2 0x.* in main .*strcat-overlap.cc:}}[[@LINE+5]] + strcat(buffer, buffer + 1); // BOOM +} + +int main(int argc, char **argv) { + bad_function(); + return 0; +} diff --git a/test/asan/TestCases/strcpy-overlap.cc b/test/asan/TestCases/strcpy-overlap.cc new file mode 100644 index 000000000000..53b77e13d91e --- /dev/null +++ b/test/asan/TestCases/strcpy-overlap.cc @@ -0,0 +1,48 @@ +// RUN: %clangxx_asan -O0 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strcpy" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O1 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strcpy" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O2 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strcpy" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O3 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strcpy" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t + +// UNSUPPORTED: android + +#include <string.h> + + +// Don't inline function otherwise stacktrace changes. +__attribute__((noinline)) void bad_function() { + char buffer[] = "hello"; + // CHECK: strcpy-param-overlap: memory ranges + // CHECK: [{{0x.*,[ ]*0x.*}}) and [{{0x.*,[ ]*0x.*}}) overlap + // CHECK: {{#0 0x.* in .*strcpy}} + // CHECK: {{#1 0x.* in bad_function.*strcpy-overlap.cc:}}[[@LINE+2]] + // CHECK: {{#2 0x.* in main .*strcpy-overlap.cc:}}[[@LINE+5]] + strcpy(buffer, buffer + 1); // BOOM +} + +int main(int argc, char **argv) { + bad_function(); + return 0; +} diff --git a/test/asan/TestCases/strdup_oob_test.cc b/test/asan/TestCases/strdup_oob_test.cc index 60c5ef12a473..e251dfcb4361 100644 --- a/test/asan/TestCases/strdup_oob_test.cc +++ b/test/asan/TestCases/strdup_oob_test.cc @@ -7,7 +7,7 @@ // RUN: %clangxx_asan -O3 -xc %s -o %t && not %run %t 2>&1 | FileCheck %s // Unwind problem on arm: "main" is missing from the allocation stack trace. -// UNSUPPORTED: armv7l-unknown-linux-gnueabihf +// REQUIRES: (arm-target-arch || armhf-target-arch), fast-unwinder-works // FIXME: We fail to intercept strdup with the dynamic WinASan RTL, so it's not // in the stack trace. diff --git a/test/asan/TestCases/strncat-overlap.cc b/test/asan/TestCases/strncat-overlap.cc new file mode 100644 index 000000000000..959b783d263f --- /dev/null +++ b/test/asan/TestCases/strncat-overlap.cc @@ -0,0 +1,48 @@ +// RUN: %clangxx_asan -O0 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strncat" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O1 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strncat" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O2 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strncat" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O3 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strncat" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t + +// UNSUPPORTED: android + +#include <string.h> + + +// Don't inline function otherwise stacktrace changes. +__attribute__((noinline)) void bad_function() { + char buffer[] = "hello\0XXX"; + // CHECK: strncat-param-overlap: memory ranges + // CHECK: [{{0x.*,[ ]*0x.*}}) and [{{0x.*,[ ]*0x.*}}) overlap + // CHECK: {{#0 0x.* in .*strncat}} + // CHECK: {{#1 0x.* in bad_function.*strncat-overlap.cc:}}[[@LINE+2]] + // CHECK: {{#2 0x.* in main .*strncat-overlap.cc:}}[[@LINE+5]] + strncat(buffer, buffer + 1, 3); // BOOM +} + +int main(int argc, char **argv) { + bad_function(); + return 0; +} diff --git a/test/asan/TestCases/strncpy-overlap.cc b/test/asan/TestCases/strncpy-overlap.cc new file mode 100644 index 000000000000..d7052cb49dc9 --- /dev/null +++ b/test/asan/TestCases/strncpy-overlap.cc @@ -0,0 +1,48 @@ +// RUN: %clangxx_asan -O0 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strncpy" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O1 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strncpy" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O2 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strncpy" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// +// RUN: %clangxx_asan -O3 %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: echo "interceptor_via_fun:bad_function" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t +// RUN: echo "interceptor_name:strncpy" > %t.supp +// RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t + +// UNSUPPORTED: android + +#include <string.h> + + +// Don't inline function otherwise stacktrace changes. +__attribute__((noinline)) void bad_function() { + char buffer[] = "hello"; + // CHECK: strncpy-param-overlap: memory ranges + // CHECK: [{{0x.*,[ ]*0x.*}}) and [{{0x.*,[ ]*0x.*}}) overlap + // CHECK: {{#0 0x.* in .*strncpy}} + // CHECK: {{#1 0x.* in bad_function.*strncpy-overlap.cc:}}[[@LINE+2]] + // CHECK: {{#2 0x.* in main .*strncpy-overlap.cc:}}[[@LINE+5]] + strncpy(buffer, buffer + 1, 5); // BOOM +} + +int main(int argc, char **argv) { + bad_function(); + return 0; +} diff --git a/test/asan/TestCases/suppressions-exec-relative-location.cc b/test/asan/TestCases/suppressions-exec-relative-location.cc index d4e214d35a0e..d7497566a8c3 100644 --- a/test/asan/TestCases/suppressions-exec-relative-location.cc +++ b/test/asan/TestCases/suppressions-exec-relative-location.cc @@ -4,15 +4,15 @@ // If the executable is started from a different location, we should still // find the suppression file located relative to the location of the executable. -// RUN: rm -rf %T/suppressions-exec-relative-location -// RUN: mkdir -p %T/suppressions-exec-relative-location -// RUN: %clangxx_asan -O0 %s -o %T/suppressions-exec-relative-location/exec +// RUN: rm -rf %t-dir +// RUN: mkdir -p %t-dir +// RUN: %clangxx_asan -O0 %s -o %t-dir/exec // RUN: echo "interceptor_via_fun:crash_function" > \ -// RUN: %T/suppressions-exec-relative-location/supp.txt +// RUN: %t-dir/supp.txt // RUN: %env_asan_opts=suppressions='"supp.txt"' \ -// RUN: %run %T/suppressions-exec-relative-location/exec 2>&1 | \ +// RUN: %run %t-dir/exec 2>&1 | \ // RUN: FileCheck --check-prefix=CHECK-IGNORE %s -// RUN: rm -rf %T/suppressions-exec-relative-location +// RUN: rm -rf %t-dir // If the wrong absolute path is given, we don't try to construct // a relative path with it. diff --git a/test/asan/TestCases/suppressions-library.cc b/test/asan/TestCases/suppressions-library.cc index e95d339168ed..39ede0840105 100644 --- a/test/asan/TestCases/suppressions-library.cc +++ b/test/asan/TestCases/suppressions-library.cc @@ -7,7 +7,7 @@ // FIXME: Remove usage of backticks around basename below. // REQUIRES: shell -// RUN: echo "interceptor_via_lib:"`basename %dynamiclib` > %t.supp +// RUN: echo "interceptor_via_lib:"%xdynamiclib_filename > %t.supp // RUN: %env_asan_opts=suppressions='"%t.supp"' %run %t 2>&1 | FileCheck --check-prefix=CHECK-IGNORE %s // XFAIL: android diff --git a/test/asan/TestCases/throw_invoke_test.cc b/test/asan/TestCases/throw_invoke_test.cc index e6e91d1879cb..bbfa1c7b95ca 100644 --- a/test/asan/TestCases/throw_invoke_test.cc +++ b/test/asan/TestCases/throw_invoke_test.cc @@ -1,5 +1,5 @@ // RUN: %clangxx_asan %s -o %t && %run %t -// RUN: %clangxx_asan %s -o %t -stdlib=libstdc++ -static-libstdc++ && %run %t +// RUN: %clangxx_asan %s -o %t %linux_static_libstdcplusplus && %run %t #include <stdio.h> static volatile int zero = 0; diff --git a/test/asan/TestCases/verbose-log-path_test.cc b/test/asan/TestCases/verbose-log-path_test.cc index 3c3db0883f61..8088ff924761 100644 --- a/test/asan/TestCases/verbose-log-path_test.cc +++ b/test/asan/TestCases/verbose-log-path_test.cc @@ -1,12 +1,13 @@ -// RUN: %clangxx_asan %s -o %T/verbose-log-path_test-binary +// RUN: rm -rf %t-dir && mkdir -p %t-dir +// RUN: %clangxx_asan %s -o %t-dir/verbose-log-path_test-binary // The glob below requires bash. // REQUIRES: shell // Good log_path. -// RUN: rm -f %T/asan.log.* -// RUN: %env_asan_opts=log_path=%T/asan.log:log_exe_name=1 not %run %T/verbose-log-path_test-binary 2> %t.out -// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %T/asan.log.verbose-log-path_test-binary.* +// RUN: rm -f %t-dir/asan.log.* +// RUN: %env_asan_opts=log_path=%t-dir/asan.log:log_exe_name=1 not %run %t-dir/verbose-log-path_test-binary 2> %t.out +// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %t-dir/asan.log.verbose-log-path_test-binary.* // FIXME: only FreeBSD, NetBSD and Linux have verbose log paths now. // XFAIL: win32,android diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg index 4a08a7b475a2..f8994d069ad8 100644 --- a/test/asan/lit.cfg +++ b/test/asan/lit.cfg @@ -48,8 +48,7 @@ config.substitutions.append(('%env_asan_opts=', # Setup source root. config.test_source_root = os.path.dirname(__file__) -# There is no libdl on FreeBSD. -if config.host_os != 'FreeBSD': +if config.host_os not in ['FreeBSD', 'NetBSD']: libdl_flag = "-ldl" else: libdl_flag = "" @@ -102,7 +101,7 @@ config.substitutions.append( ("%clang ", build_invocation(target_cflags)) ) config.substitutions.append( ("%clangxx ", build_invocation(target_cxxflags)) ) config.substitutions.append( ("%clang_asan ", build_invocation(clang_asan_cflags)) ) config.substitutions.append( ("%clangxx_asan ", build_invocation(clang_asan_cxxflags)) ) -config.substitutions.append( ("%shared_libasan", "libclang_rt.asan-%s.so" % config.target_arch)) +config.substitutions.append( ("%shared_libasan", "libclang_rt.asan%s.so" % config.target_suffix)) if config.asan_dynamic: config.substitutions.append( ("%clang_asan_static ", build_invocation(clang_asan_static_cflags)) ) config.substitutions.append( ("%clangxx_asan_static ", build_invocation(clang_asan_static_cxxflags)) ) @@ -125,7 +124,7 @@ if platform.system() == 'Windows': clang_cl_asan_invocation = clang_cl_asan_invocation.replace("clang.exe","clang-cl.exe") config.substitutions.append( ("%clang_cl_asan ", clang_cl_asan_invocation) ) - base_lib = os.path.join(config.compiler_rt_libdir, "clang_rt.asan%%s-%s.lib" % config.target_arch) + base_lib = os.path.join(config.compiler_rt_libdir, "clang_rt.asan%%s%s.lib" % config.target_suffix) config.substitutions.append( ("%asan_lib", base_lib % "") ) config.substitutions.append( ("%asan_cxx_lib", base_lib % "_cxx") ) config.substitutions.append( ("%asan_dll_thunk", base_lib % "_dll_thunk") ) @@ -169,7 +168,7 @@ config.substitutions.append( ("%libdl", libdl_flag) ) config.available_features.add("asan-" + config.bits + "-bits") # Fast unwinder doesn't work with Thumb -if re.search('mthumb', config.target_cflags) is not None: +if re.search('mthumb', config.target_cflags) is None: config.available_features.add('fast-unwinder-works') # Turn on leak detection on 64-bit Linux. @@ -209,8 +208,11 @@ else: config.substitutions.append(('%pie', '-pie')) # Only run the tests on supported OSs. -if config.host_os not in ['Linux', 'Darwin', 'FreeBSD', 'Windows']: +if config.host_os not in ['Linux', 'Darwin', 'FreeBSD', 'SunOS', 'Windows', 'NetBSD']: config.unsupported = True -if config.host_os == 'Darwin' and config.target_arch in ["x86_64", "x86_64h"]: - config.parallelism_group = "darwin-64bit-sanitizer" +if config.host_os == 'Darwin': + if config.target_arch in ["x86_64", "x86_64h"]: + config.parallelism_group = "darwin-64bit-sanitizer" + elif config.apple_platform != "osx" and not config.apple_platform.endswith("sim"): + config.parallelism_group = "darwin-ios-device-sanitizer" diff --git a/test/asan/lit.site.cfg.in b/test/asan/lit.site.cfg.in index 6c8f882bcc2c..6282fd881e5d 100644 --- a/test/asan/lit.site.cfg.in +++ b/test/asan/lit.site.cfg.in @@ -5,8 +5,7 @@ config.name_suffix = "@ASAN_TEST_CONFIG_SUFFIX@" config.target_cflags = "@ASAN_TEST_TARGET_CFLAGS@" config.clang = "@ASAN_TEST_TARGET_CC@" config.bits = "@ASAN_TEST_BITS@" -config.ios = @ASAN_TEST_IOS_PYBOOL@ -config.iossim = @ASAN_TEST_IOSSIM_PYBOOL@ +config.apple_platform = "@ASAN_TEST_APPLE_PLATFORM@" config.asan_dynamic = @ASAN_TEST_DYNAMIC@ config.target_arch = "@ASAN_TEST_TARGET_ARCH@" diff --git a/test/builtins/CMakeLists.txt b/test/builtins/CMakeLists.txt index cabf767223cc..a9199ebf10df 100644 --- a/test/builtins/CMakeLists.txt +++ b/test/builtins/CMakeLists.txt @@ -26,6 +26,11 @@ foreach(arch ${BUILTIN_SUPPORTED_ARCH}) string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}") endif() + if (${arch} STREQUAL "riscv32") + list(APPEND BUILTINS_TEST_TARGET_CFLAGS -fforce-enable-int128) + string(REPLACE ";" " " BUILTINS_TEST_TARGET_CFLAGS "${BUILTINS_TEST_TARGET_CFLAGS}") + endif() + string(TOUPPER ${arch} ARCH_UPPER_CASE) set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) configure_lit_site_cfg( diff --git a/test/builtins/TestCases/Darwin/os_version_check_test.c b/test/builtins/TestCases/Darwin/os_version_check_test.c index 2692cd37edce..bae1f3255065 100644 --- a/test/builtins/TestCases/Darwin/os_version_check_test.c +++ b/test/builtins/TestCases/Darwin/os_version_check_test.c @@ -1,4 +1,4 @@ -// RUN: %clang %s -o %t -mmacosx-version-min=10.5 -framework CoreFoundation -DMAJOR=%macos_version_major -DMINOR=%macos_version_minor -DSUBMINOR=%macos_version_subminor +// RUN: %clang %s -o %t -mmacosx-version-min=10.6 -framework CoreFoundation -DMAJOR=%macos_version_major -DMINOR=%macos_version_minor -DSUBMINOR=%macos_version_subminor // RUN: %run %t int __isOSVersionAtLeast(int Major, int Minor, int Subminor); diff --git a/test/builtins/TestCases/Darwin/os_version_check_test_no_core_foundation.c b/test/builtins/TestCases/Darwin/os_version_check_test_no_core_foundation.c index 4e0da35cd12d..90c798f6c55f 100644 --- a/test/builtins/TestCases/Darwin/os_version_check_test_no_core_foundation.c +++ b/test/builtins/TestCases/Darwin/os_version_check_test_no_core_foundation.c @@ -1,4 +1,4 @@ -// RUN: %clang %s -o %t -mmacosx-version-min=10.5 +// RUN: %clang %s -o %t -mmacosx-version-min=10.6 // RUN: %run %t int __isOSVersionAtLeast(int Major, int Minor, int Subminor); diff --git a/test/builtins/Unit/lit.cfg b/test/builtins/Unit/lit.cfg index 0e17e479e6b6..4b63948b5ef6 100644 --- a/test/builtins/Unit/lit.cfg +++ b/test/builtins/Unit/lit.cfg @@ -26,12 +26,12 @@ config.test_source_root = os.path.dirname(__file__) # Path to the static library is_msvc = get_required_attr(config, "builtins_is_msvc") if is_msvc: - base_lib = os.path.join(config.compiler_rt_libdir, "clang_rt.builtins-%s.lib " - % config.target_arch) + base_lib = os.path.join(config.compiler_rt_libdir, "clang_rt.builtins%s.lib " + % config.target_suffix) config.substitutions.append( ("%librt ", base_lib) ) else: - base_lib = os.path.join(config.compiler_rt_libdir, "libclang_rt.builtins-%s.a" - % config.target_arch) + base_lib = os.path.join(config.compiler_rt_libdir, "libclang_rt.builtins%s.a" + % config.target_suffix) config.substitutions.append( ("%librt ", base_lib + ' -lc -lm ') ) builtins_source_dir = os.path.join( diff --git a/test/builtins/Unit/riscv/mulsi3_test.c b/test/builtins/Unit/riscv/mulsi3_test.c new file mode 100644 index 000000000000..9033004f11dd --- /dev/null +++ b/test/builtins/Unit/riscv/mulsi3_test.c @@ -0,0 +1,119 @@ +// REQUIRES-ANY: riscv32-target-arch +// RUN: %clang_builtins %s %librt -o %t && %run %t +//===-- mulsi3_test.c - Test __mulsi3 -------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests __mulsi3 for the compiler_rt library. +// +//===----------------------------------------------------------------------===// + +#include "int_lib.h" +#include <stdio.h> +#include <limits.h> + +#if !defined(__riscv_mul) && __riscv_xlen == 32 +// Based on mulsi3_test.c + +COMPILER_RT_ABI si_int __mulsi3(si_int a, si_int b); + +int test__mulsi3(si_int a, si_int b, si_int expected) +{ + si_int x = __mulsi3(a, b); + if (x != expected) + printf("error in __mulsi3: %d * %d = %d, expected %d\n", + a, b, __mulsi3(a, b), expected); + return x != expected; +} +#endif + +int main() +{ +#if !defined(__riscv_mul) && __riscv_xlen == 32 + if (test__mulsi3(0, 0, 0)) + return 1; + if (test__mulsi3(0, 1, 0)) + return 1; + if (test__mulsi3(1, 0, 0)) + return 1; + if (test__mulsi3(0, 10, 0)) + return 1; + if (test__mulsi3(10, 0, 0)) + return 1; + if (test__mulsi3(0, INT_MAX, 0)) + return 1; + if (test__mulsi3(INT_MAX, 0, 0)) + return 1; + + if (test__mulsi3(0, -1, 0)) + return 1; + if (test__mulsi3(-1, 0, 0)) + return 1; + if (test__mulsi3(0, -10, 0)) + return 1; + if (test__mulsi3(-10, 0, 0)) + return 1; + if (test__mulsi3(0, INT_MIN, 0)) + return 1; + if (test__mulsi3(INT_MIN, 0, 0)) + return 1; + + if (test__mulsi3(1, 1, 1)) + return 1; + if (test__mulsi3(1, 10, 10)) + return 1; + if (test__mulsi3(10, 1, 10)) + return 1; + if (test__mulsi3(1, INT_MAX, INT_MAX)) + return 1; + if (test__mulsi3(INT_MAX, 1, INT_MAX)) + return 1; + + if (test__mulsi3(1, -1, -1)) + return 1; + if (test__mulsi3(1, -10, -10)) + return 1; + if (test__mulsi3(-10, 1, -10)) + return 1; + if (test__mulsi3(1, INT_MIN, INT_MIN)) + return 1; + if (test__mulsi3(INT_MIN, 1, INT_MIN)) + return 1; + + if (test__mulsi3(46340, 46340, 2147395600)) + return 1; + if (test__mulsi3(-46340, 46340, -2147395600)) + return 1; + if (test__mulsi3(46340, -46340, -2147395600)) + return 1; + if (test__mulsi3(-46340, -46340, 2147395600)) + return 1; + + if (test__mulsi3(4194303, 8192, 34359730176)) + return 1; + if (test__mulsi3(-4194303, 8192, -34359730176)) + return 1; + if (test__mulsi3(4194303, -8192, -34359730176)) + return 1; + if (test__mulsi3(-4194303, -8192, 34359730176)) + return 1; + + if (test__mulsi3(8192, 4194303, 34359730176)) + return 1; + if (test__mulsi3(-8192, 4194303, -34359730176)) + return 1; + if (test__mulsi3(8192, -4194303, -34359730176)) + return 1; + if (test__mulsi3(-8192, -4194303, 34359730176)) + return 1; +#else + printf("skipped\n"); +#endif + + return 0; +} diff --git a/test/cfi/CMakeLists.txt b/test/cfi/CMakeLists.txt index c7fadde53095..4dbbf1759fcc 100644 --- a/test/cfi/CMakeLists.txt +++ b/test/cfi/CMakeLists.txt @@ -1,6 +1,6 @@ set(CFI_TESTSUITES) -macro (add_cfi_test_suites lld thinlto) +macro (add_cfi_test_suites lld thinlto newpm) set(suffix) if (${lld}) set(suffix ${suffix}-lld) @@ -8,10 +8,14 @@ macro (add_cfi_test_suites lld thinlto) if (${thinlto}) set(suffix ${suffix}-thinlto) endif() + if (${newpm}) + set(suffix ${suffix}-newpm) + endif() set(suffix ${suffix}-${CFI_TEST_TARGET_ARCH}) set(CFI_TEST_USE_LLD ${lld}) set(CFI_TEST_USE_THINLTO ${thinlto}) + set(CFI_TEST_USE_NEWPM ${newpm}) set(CFI_LIT_TEST_MODE Standalone) set(CFI_TEST_CONFIG_SUFFIX -standalone${suffix}) @@ -40,16 +44,18 @@ foreach(arch ${CFI_TEST_ARCH}) get_test_cc_for_arch(${arch} CFI_TEST_TARGET_CC CFI_TEST_TARGET_CFLAGS) if (APPLE) # FIXME: enable ThinLTO tests after fixing http://llvm.org/pr32741 - add_cfi_test_suites(False False) + add_cfi_test_suites(False False False) elseif(WIN32) - add_cfi_test_suites(True False) - add_cfi_test_suites(True True) + add_cfi_test_suites(True False False) + add_cfi_test_suites(True True False) else() - add_cfi_test_suites(False False) - add_cfi_test_suites(False True) + add_cfi_test_suites(False False False) + add_cfi_test_suites(False True False) + add_cfi_test_suites(False False True) + add_cfi_test_suites(False True True) if (COMPILER_RT_HAS_LLD AND NOT arch STREQUAL "i386") - add_cfi_test_suites(True False) - add_cfi_test_suites(True True) + add_cfi_test_suites(True False False) + add_cfi_test_suites(True True False) endif() endif() endforeach() diff --git a/test/cfi/create-derivers.test b/test/cfi/create-derivers.test index 8b569d001d89..b651d9be6bd9 100644 --- a/test/cfi/create-derivers.test +++ b/test/cfi/create-derivers.test @@ -7,15 +7,15 @@ B0: {{1B|B@@}}: {{.*}} size 1 RUN: %clangxx_cfi -DB32 -flto -c -o %t2.o %S/simple-fail.cpp RUN: opt -lowertypetests -debug-only=lowertypetests -o /dev/null %t2.o 2>&1 | FileCheck --check-prefix=B32 %s -B32: {{1B|B@@}}: {{.*}} size 24 +B32: {{1B|B@@}}: {{.*}} size 2{{3|4}} B32-NOT: all-ones RUN: %clangxx_cfi -DB64 -flto -c -o %t3.o %S/simple-fail.cpp RUN: opt -lowertypetests -debug-only=lowertypetests -o /dev/null %t3.o 2>&1 | FileCheck --check-prefix=B64 %s -B64: {{1B|B@@}}: {{.*}} size 54 +B64: {{1B|B@@}}: {{.*}} size 5{{3|4}} B64-NOT: all-ones RUN: %clangxx_cfi -DBM -flto -c -o %t4.o %S/simple-fail.cpp RUN: opt -lowertypetests -debug-only=lowertypetests -o /dev/null %t4.o 2>&1 | FileCheck --check-prefix=BM %s -BM: {{1B|B@@}}: {{.*}} size 84 +BM: {{1B|B@@}}: {{.*}} size 8{{3|4}} BM-NOT: all-ones diff --git a/test/cfi/cross-dso-diagnostic.cpp b/test/cfi/cross-dso-diagnostic.cpp new file mode 100644 index 000000000000..f3782dae0272 --- /dev/null +++ b/test/cfi/cross-dso-diagnostic.cpp @@ -0,0 +1,47 @@ +// Check that cross-DSO diagnostics print the names of both modules + +// RUN: %clangxx_cfi_diag -g -DSHARED_LIB -fPIC -shared -o %dynamiclib %s %ld_flags_rpath_so +// RUN: %clangxx_cfi_diag -g -o %t_exe_suffix %s %ld_flags_rpath_exe +// RUN: %t_exe_suffix 2>&1 | FileCheck -DDSONAME=%xdynamiclib_namespec %s + +// UNSUPPORTED: win32 +// REQUIRES: cxxabi + +#include <dlfcn.h> +#include <stdio.h> + +struct S1 { + virtual void f1(); +}; + +#ifdef SHARED_LIB + +void S1::f1() {} + +__attribute__((visibility("default"))) extern "C" +void* dso_symbol() { return new S1(); } + +#else + +int main() { + void* (*fp)(void) = + reinterpret_cast<void*(*)(void)>(dlsym(RTLD_DEFAULT, "dso_symbol")); + if (!fp) { + perror("failed to resolve dso_symbol"); + return 1; + } + + // CHECK: runtime error: control flow integrity check for type 'void *()' failed during indirect function call + // CHECK: dso_symbol defined here + // CHECK: check failed in {{.*}}_exe_suffix, destination function located in {{.*}}[[DSONAME]] + void *S = fp(); // trigger cfi-icall failure + + // CHECK: runtime error: control flow integrity check for type 'S1' failed during cast to unrelated type + // CHECK: invalid vtable + // CHECK: check failed in {{.*}}_exe_suffix, vtable located in {{.*}}[[DSONAME]] + S1 *Scast = reinterpret_cast<S1*>(S); // trigger cfi-unrelated-cast failure + + return 0; +} + +#endif // SHARED_LIB diff --git a/test/cfi/cross-dso/icall/dlopen.cpp b/test/cfi/cross-dso/icall/dlopen.cpp index d238a7acec89..c9674c3fb412 100644 --- a/test/cfi/cross-dso/icall/dlopen.cpp +++ b/test/cfi/cross-dso/icall/dlopen.cpp @@ -83,10 +83,12 @@ static void save_code(char *p) { } static void restore_code() { - char *code = (char *)mmap(real_start, kCodeSize, PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0); + char *code = + (char *)mmap(real_start, kCodeSize, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0); assert(code == real_start); memcpy(code, saved_code, kCodeSize); + __builtin___clear_cache(code, code + kCodeSize); } int main(int argc, char *argv[]) { diff --git a/test/cfi/lit.site.cfg.in b/test/cfi/lit.site.cfg.in index eb9b44137fdf..a735e8812acd 100644 --- a/test/cfi/lit.site.cfg.in +++ b/test/cfi/lit.site.cfg.in @@ -7,6 +7,7 @@ config.target_cflags = "@CFI_TEST_TARGET_CFLAGS@" config.use_lld = @CFI_TEST_USE_LLD@ config.use_lto = True # CFI *requires* LTO. config.use_thinlto = @CFI_TEST_USE_THINLTO@ +config.use_newpm = @CFI_TEST_USE_NEWPM@ lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") diff --git a/test/cfi/mfcall.cpp b/test/cfi/mfcall.cpp new file mode 100644 index 000000000000..6e22e3f3d711 --- /dev/null +++ b/test/cfi/mfcall.cpp @@ -0,0 +1,96 @@ +// UNSUPPORTED: win32 + +// RUN: %clangxx_cfi -o %t %s +// RUN: %expect_crash %run %t a +// RUN: %expect_crash %run %t b +// RUN: %expect_crash %run %t c +// RUN: %expect_crash %run %t d +// RUN: %expect_crash %run %t e +// RUN: %run %t f +// RUN: %run %t g + +// RUN: %clangxx_cfi_diag -o %t2 %s +// RUN: %run %t2 a 2>&1 | FileCheck --check-prefix=A %s +// RUN: %run %t2 b 2>&1 | FileCheck --check-prefix=B %s +// RUN: %run %t2 c 2>&1 | FileCheck --check-prefix=C %s +// RUN: %run %t2 d 2>&1 | FileCheck --check-prefix=D %s +// RUN: %run %t2 e 2>&1 | FileCheck --check-prefix=E %s + +#include <assert.h> +#include <string.h> + +struct SBase1 { + void b1() {} +}; + +struct SBase2 { + void b2() {} +}; + +struct S : SBase1, SBase2 { + void f1() {} + int f2() { return 1; } + virtual void g1() {} + virtual int g2() { return 1; } + virtual int g3() { return 1; } +}; + +struct T { + void f1() {} + int f2() { return 2; } + virtual void g1() {} + virtual int g2() { return 2; } + virtual void g3() {} +}; + +typedef void (S::*S_void)(); + +typedef int (S::*S_int)(); +typedef int (T::*T_int)(); + +template <typename To, typename From> +To bitcast(From f) { + assert(sizeof(To) == sizeof(From)); + To t; + memcpy(&t, &f, sizeof(f)); + return t; +} + +int main(int argc, char **argv) { + S s; + T t; + + switch (argv[1][0]) { + case 'a': + // A: runtime error: control flow integrity check for type 'int (S::*)()' failed during non-virtual pointer to member function call + // A: note: S::f1() defined here + (s.*bitcast<S_int>(&S::f1))(); + break; + case 'b': + // B: runtime error: control flow integrity check for type 'int (T::*)()' failed during non-virtual pointer to member function call + // B: note: S::f2() defined here + (t.*bitcast<T_int>(&S::f2))(); + break; + case 'c': + // C: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual pointer to member function call + // C: note: vtable is of type 'S' + (s.*bitcast<S_int>(&S::g1))(); + break; + case 'd': + // D: runtime error: control flow integrity check for type 'int (S::*)()' failed during virtual pointer to member function call + // D: note: vtable is of type 'T' + (reinterpret_cast<S &>(t).*&S::g2)(); + break; + case 'e': + // E: runtime error: control flow integrity check for type 'void (S::*)()' failed during virtual pointer to member function call + // E: note: vtable is of type 'S' + (s.*bitcast<S_void>(&T::g3))(); + break; + case 'f': + (s.*&SBase1::b1)(); + break; + case 'g': + (s.*&SBase2::b2)(); + break; + } +} diff --git a/test/cfi/simple-pass.cpp b/test/cfi/simple-pass.cpp index aba09be2d816..de791fc1073f 100644 --- a/test/cfi/simple-pass.cpp +++ b/test/cfi/simple-pass.cpp @@ -1,5 +1,10 @@ +// -mretpoline does not work yet on Darwin. +// XFAIL: darwin + // RUN: %clangxx_cfi -o %t %s // RUN: %run %t +// RUN: %clangxx_cfi -mretpoline -o %t2 %s +// RUN: %run %t2 // Tests that the CFI mechanism does not crash the program when making various // kinds of valid calls involving classes with various different linkages and diff --git a/test/cfi/target_uninstrumented.cpp b/test/cfi/target_uninstrumented.cpp index 5df0738c078b..6379b7e12f44 100644 --- a/test/cfi/target_uninstrumented.cpp +++ b/test/cfi/target_uninstrumented.cpp @@ -32,12 +32,14 @@ void A::f() {} int main(int argc, char *argv[]) { void *p = create_B(); // CHECK: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type - // CHECK: invalid vtable in module {{.*}}libtarget_uninstrumented.cpp.dynamic.so + // CHECK: invalid vtable + // CHECK: check failed in {{.*}}, vtable located in {{.*}}libtarget_uninstrumented.cpp.dynamic.so A *a = (A *)p; memset(p, 0, sizeof(A)); + // CHECK: runtime error: control flow integrity check for type 'A' failed during cast to unrelated type - // CHECK-NOT: invalid vtable in module // CHECK: invalid vtable + // CHECK: check failed in {{.*}}, vtable located in (unknown) a = (A *)p; // CHECK: done fprintf(stderr, "done %p\n", a); diff --git a/test/dfsan/custom.cc b/test/dfsan/custom.cc index b36db01bc48c..71422f7ce834 100644 --- a/test/dfsan/custom.cc +++ b/test/dfsan/custom.cc @@ -3,8 +3,6 @@ // RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES %s -o %t && %run %t // RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -mllvm -dfsan-args-abi %s -o %t && %run %t -// XFAIL: target-is-mips64,target-is-mips64el - // Tests custom implementations of various glibc functions. #include <sanitizer/dfsan_interface.h> diff --git a/test/dfsan/trace-cmp.c b/test/dfsan/trace-cmp.c new file mode 100644 index 000000000000..0645363b2605 --- /dev/null +++ b/test/dfsan/trace-cmp.c @@ -0,0 +1,50 @@ +// Checks that dfsan works with trace-cmp instrumentation, even if some hooks +// are not defined (relies on week hooks implemented in dfsan). +// +// RUN: %clang_dfsan -fsanitize-coverage=trace-pc-guard,pc-table,func,trace-cmp %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +#include <sanitizer/dfsan_interface.h> + +uint32_t a4, b4; +uint64_t a8, b8; + +// Define just two hooks, and leave others undefined. +void __dfsw___sanitizer_cov_trace_const_cmp4(uint8_t a, uint8_t b, + dfsan_label l1, dfsan_label l2) { + printf("const_cmp4 %d %d\n", a, b); +} +void __dfsw___sanitizer_cov_trace_cmp8(uint8_t a, uint8_t b, dfsan_label l1, + dfsan_label l2) { + printf("cmp8 %d %d\n", a, b); +} + +int main(int argc, char **argv) { + printf("MAIN\n"); + // CHECK: MAIN + + if (a4 != b4) abort(); + if (a4 == 42) abort(); + // CHECK: const_cmp4 42 0 + if (a8 != b8) abort(); + // CHECK: cmp8 0 0 + if (a8 == 66) abort(); + + switch (10 / (a4 + 2)) { + case 1: abort(); + case 2: exit(1); + case 5: + printf("SWITCH OK\n"); + break; + } + // CHECK: SWITCH OK + + + printf("DONE\n"); + // CHECK: DONE + return 0; +} diff --git a/test/fuzzer/AbsNegAndConstant64Test.cpp b/test/fuzzer/AbsNegAndConstant64Test.cpp index abeb784e9a11..0ba80b61d033 100644 --- a/test/fuzzer/AbsNegAndConstant64Test.cpp +++ b/test/fuzzer/AbsNegAndConstant64Test.cpp @@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { uint64_t y; memcpy(&x, Data, sizeof(x)); memcpy(&y, Data + sizeof(x), sizeof(y)); - if (llabs(x) < 0 && y == 0xbaddcafedeadbeefULL) { + volatile int64_t abs_x = llabs(x); + if (abs_x < 0 && y == 0xbaddcafedeadbeefULL) { printf("BINGO; Found the target, exiting; x = 0x%lx y 0x%lx\n", x, y); fflush(stdout); exit(1); diff --git a/test/fuzzer/AbsNegAndConstantTest.cpp b/test/fuzzer/AbsNegAndConstantTest.cpp index 049db0a60c3d..a3f534980010 100644 --- a/test/fuzzer/AbsNegAndConstantTest.cpp +++ b/test/fuzzer/AbsNegAndConstantTest.cpp @@ -14,7 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { unsigned y; memcpy(&x, Data, sizeof(x)); memcpy(&y, Data + sizeof(x), sizeof(y)); - if (abs(x) < 0 && y == 0xbaddcafe) { + volatile int abs_x = abs(x); + if (abs_x < 0 && y == 0xbaddcafe) { printf("BINGO; Found the target, exiting; x = 0x%x y 0x%x\n", x, y); fflush(stdout); exit(1); diff --git a/test/fuzzer/AcquireCrashStateTest.cpp b/test/fuzzer/AcquireCrashStateTest.cpp new file mode 100644 index 000000000000..0fe71fd46bf4 --- /dev/null +++ b/test/fuzzer/AcquireCrashStateTest.cpp @@ -0,0 +1,18 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Ensures that error reports are suppressed after +// __sanitizer_acquire_crash_state() has been called the first time. +#include "sanitizer/common_interface_defs.h" + +#include <cassert> +#include <cstdint> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size == 0) return 0; + __sanitizer_acquire_crash_state(); + exit(0); // No report should be generated here. +} + diff --git a/test/fuzzer/Bingo.h b/test/fuzzer/Bingo.h new file mode 100644 index 000000000000..09fc61e2a0cb --- /dev/null +++ b/test/fuzzer/Bingo.h @@ -0,0 +1 @@ +#define BINGO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/test/fuzzer/CMakeLists.txt b/test/fuzzer/CMakeLists.txt index bd511123255b..ef46ec4a9061 100644 --- a/test/fuzzer/CMakeLists.txt +++ b/test/fuzzer/CMakeLists.txt @@ -1,43 +1,109 @@ set(LIBFUZZER_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -list(REMOVE_ITEM LIBFUZZER_TEST_DEPS SanitizerLintCheck) if (NOT COMPILER_RT_STANDALONE_BUILD) list(APPEND LIBFUZZER_TEST_DEPS fuzzer asan ubsan) + if (COMPILER_RT_HAS_MSAN) + list(APPEND LIBFUZZER_TEST_DEPS msan) + endif() + if (COMPILER_RT_HAS_DFSAN) + list(APPEND LIBFUZZER_TEST_DEPS dfsan) + endif() + if(NOT APPLE AND COMPILER_RT_HAS_LLD) + list(APPEND LIBFUZZER_TEST_DEPS lld) + endif() +endif() + +if (APPLE) + darwin_filter_host_archs(FUZZER_SUPPORTED_ARCH FUZZER_SUPPORTED_ARCH) endif() if(COMPILER_RT_INCLUDE_TESTS) list(APPEND LIBFUZZER_TEST_DEPS FuzzerUnitTests) endif() -set(LIBFUZZER_TESTSUITES) - +add_custom_target(check-fuzzer) if(COMPILER_RT_INCLUDE_TESTS) # libFuzzer unit tests. configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg) - list(APPEND LIBFUZZER_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit) + add_lit_testsuite(check-fuzzer-unit "Running Fuzzer unit tests" + ${CMAKE_CURRENT_BINARY_DIR}/unit + DEPENDS ${LIBFUZZER_TEST_DEPS}) + set_target_properties(check-fuzzer-unit PROPERTIES FOLDER "Compiler-RT Tests") + add_dependencies(check-fuzzer check-fuzzer-unit) endif() -foreach(arch ${FUZZER_SUPPORTED_ARCH}) - set(LIBFUZZER_TEST_COMPILER ${COMPILER_RT_TEST_COMPILER}) - get_test_cc_for_arch(${arch} LIBFUZZER_TEST_COMPILER LIBFUZZER_TEST_FLAGS) +macro(test_fuzzer stdlib) + cmake_parse_arguments(TEST "" "" "DEPS" ${ARGN}) + string(REPLACE "+" "x" stdlib_name ${stdlib}) + string(REPLACE "-" ";" stdlib_list ${stdlib_name}) + set(STDLIB_CAPITALIZED "") + foreach(part IN LISTS stdlib_list) + string(SUBSTRING ${part} 0 1 first_letter) + string(TOUPPER ${first_letter} first_letter) + string(REGEX REPLACE "^.(.*)" "${first_letter}\\1" part "${part}") + set(STDLIB_CAPITALIZED "${STDLIB_CAPITALIZED}${part}") + endforeach() + foreach(arch ${FUZZER_SUPPORTED_ARCH}) + set(LIBFUZZER_TEST_COMPILER ${COMPILER_RT_TEST_COMPILER}) + get_test_cc_for_arch(${arch} LIBFUZZER_TEST_COMPILER LIBFUZZER_TEST_FLAGS) - string(TOUPPER ${arch} ARCH_UPPER_CASE) - set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) + set(LIBFUZZER_TEST_APPLE_PLATFORM "osx") - # LIT-based libFuzzer tests. - configure_lit_site_cfg( - ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg - ) - list(APPEND LIBFUZZER_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) + set(LIBFUZZER_TEST_STDLIB ${stdlib}) + + string(TOUPPER ${arch} ARCH_UPPER_CASE) + set(CONFIG_NAME ${ARCH_UPPER_CASE}${STDLIB_CAPITALIZED}${OS_NAME}Config) -endforeach() + # LIT-based libFuzzer tests. + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg + ) -set(EXCLUDE_FROM_ALL ON) + add_lit_testsuite(check-fuzzer-${stdlib_name}-${arch} + "Running libFuzzer ${stdlib} tests for arch ${arch}" + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/ + DEPENDS ${LIBFUZZER_TEST_DEPS}) + if(TEST_DEPS) + add_dependencies(check-fuzzer-${stdlib_name}-${arch} ${TEST_DEPS}) + endif() + set_target_properties(check-fuzzer-${stdlib_name}-${arch} + PROPERTIES FOLDER "Compiler-RT Tests") + add_dependencies(check-fuzzer check-fuzzer-${stdlib_name}-${arch}) + endforeach() +endmacro() -add_lit_testsuite(check-fuzzer "Running Fuzzer tests" - ${LIBFUZZER_TESTSUITES} - DEPENDS ${LIBFUZZER_TEST_DEPS}) -set_target_properties(check-fuzzer PROPERTIES FOLDER "Compiler-RT Tests") +test_fuzzer("default") +if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") + if(TARGET cxx_shared) + test_fuzzer("libc++" DEPS cxx_shared) + endif() + if(TARGET cxx_static) + test_fuzzer("static-libc++" DEPS cxx_static) + endif() +endif() + +if (APPLE) + set(EXCLUDE_FROM_ALL ON) + + foreach(arch ${DARWIN_ios_ARCHS}) + set(LIBFUZZER_TEST_APPLE_PLATFORM "ios") + set(LIBFUZZER_TEST_TARGET_ARCH ${arch}) + set(LIBFUZZER_TEST_FLAGS "-arch ${arch} -isysroot ${DARWIN_ios_SYSROOT} ${COMPILER_RT_TEST_COMPILER_CFLAGS}") + set(LIBFUZZER_TEST_CONFIG_SUFFIX "-${arch}-${LIBFUZZER_TEST_APPLE_PLATFORM}") + string(TOUPPER ${arch} ARCH_UPPER_CASE) + set(CONFIG_NAME "IOS${ARCH_UPPER_CASE}Config") + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg + ) + add_lit_testsuite(check-fuzzer-ios-${arch} "libFuzzer iOS ${arch} tests" + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/ + DEPENDS ${LIBFUZZER_TEST_DEPS}) + + endforeach() + + set(EXCLUDE_FROM_ALL OFF) +endif() diff --git a/test/fuzzer/CleanseTest.cpp b/test/fuzzer/CleanseTest.cpp index ee1845701269..d4efa12bb207 100644 --- a/test/fuzzer/CleanseTest.cpp +++ b/test/fuzzer/CleanseTest.cpp @@ -1,7 +1,7 @@ // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// Test the the fuzzer is able to 'cleanse' the reproducer +// Test the fuzzer is able to 'cleanse' the reproducer // by replacing all irrelevant bytes with garbage. #include <cstddef> #include <cstdint> diff --git a/test/fuzzer/ExplodeDFSanLabelsTest.cpp b/test/fuzzer/ExplodeDFSanLabelsTest.cpp new file mode 100644 index 000000000000..0decff8ff086 --- /dev/null +++ b/test/fuzzer/ExplodeDFSanLabelsTest.cpp @@ -0,0 +1,23 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// When tracing data flow, explode the number of DFSan labels. +#include <cstddef> +#include <cstdint> + +static volatile int sink; + +__attribute__((noinline)) +void f(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + if (a == b + 1 && c == d + 2) + sink++; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + for (size_t a = 0; a < Size; a++) + for (size_t b = 0; b < Size; b++) + for (size_t c = 0; c < Size; c++) + for (size_t d = 0; d < Size; d++) + f(Data[a], Data[b], Data[c], Data[d]); + return 0; +} diff --git a/test/fuzzer/LeakTest.cpp b/test/fuzzer/LeakTest.cpp index ea89e3901057..f259e9d359f4 100644 --- a/test/fuzzer/LeakTest.cpp +++ b/test/fuzzer/LeakTest.cpp @@ -5,7 +5,7 @@ #include <cstddef> #include <cstdint> -static volatile void *Sink; +static void * volatile Sink; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size > 0 && *Data == 'H') { diff --git a/test/fuzzer/MultipleConstraintsOnSmallInputTest.cpp b/test/fuzzer/MultipleConstraintsOnSmallInputTest.cpp new file mode 100644 index 000000000000..8e24acbcf2d9 --- /dev/null +++ b/test/fuzzer/MultipleConstraintsOnSmallInputTest.cpp @@ -0,0 +1,4129 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// echo -en 'Im_so_cute&pretty_:)' > crash +// +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> + +// Force noinline, as this test might be interesting for experimenting with +// data flow tracing approach started in https://reviews.llvm.org/D46666. +__attribute__((noinline)) +int func1(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 15 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func2(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 80 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func3(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 48 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func4(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = ((a1 & a2)) ^ a3; + if ( v > 44 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func5(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 72 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func6(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 72 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func7(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 43 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func8(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 66 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func9(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func10(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 83 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func11(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 117 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func12(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func13(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 80 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func14(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func15(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 116 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func16(uint8_t a1) { + char v = a1 >> 5; + if ( v <= 0 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func17(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func18(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 28 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func19(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 18 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func20(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 47 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func21(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = (((a1 ^ a2))) & a3; + if ( v > 108 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func22(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func23(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 7 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func24(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v <= 25 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func25(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func26(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 41 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func27(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v <= 14 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func28(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func29(uint8_t a1) { + char v = a1 >> 5; + if ( v > 48 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func30(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func31(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 45 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func32(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 0 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func33(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func34(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 95 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func35(uint8_t a1) { + char v = a1 >> 5; + if ( v > 12 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func36(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 121 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func37(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func38(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 61 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func39(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func40(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 125 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func41(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 0 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func42(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = (((a1 ^ a2))) & a3; + if ( v > 66 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func43(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func44(uint8_t a1) { + char v = a1 >> 5; + if ( v <= 0 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func45(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func46(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 106 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func47(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 33 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func48(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 118 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func49(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 58 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func50(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 42 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func51(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 46 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func52(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func53(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 66 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func54(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 23 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func55(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 17 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func56(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 90 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func57(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 63 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func58(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 102 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func59(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 49 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func60(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 26 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func61(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 55 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func62(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 103 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func63(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 0 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func64(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 34 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func65(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 90 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func66(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 4 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func67(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 50 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func68(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 37 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func69(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 48 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func70(uint8_t a1) { + char v = a1 << 6; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func71(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 85 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func72(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 66 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func73(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 30 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func74(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 118 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func75(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = ((a1 & a2)) | a3; + if ( v <= 59 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func76(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func77(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 30 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func78(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 32 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func79(uint8_t a1) { + char v = 16 * a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func80(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = ((a1 ^ a2)) | a3; + if ( v <= 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func81(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v > 120 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func82(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 81 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func83(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v > 119 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func84(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func85(uint8_t a1) { + char v = 2 * a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func86(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 66 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func87(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 84 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func88(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 118 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func89(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 47 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func90(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 60 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func91(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 13 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func92(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 38 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func93(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 67 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func94(uint8_t a1) { + char v = 16 * a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func95(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func96(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 67 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func97(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 48 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func98(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 102 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func99(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 96 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func100(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = ((a1 ^ a2)) | a3; + if ( v != 127 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func101(uint8_t a1) { + char v = 4 * a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func102(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 43 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func103(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 95 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func104(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = (((a1 ^ a2))) & a3; + if ( v <= 2 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func105(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 65 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func106(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 24 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func107(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func108(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 67 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func109(uint8_t a1) { + char v = 2 * a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func110(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 101 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func111(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = ((a1 & a2)) | a3; + if ( v <= 121 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func112(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 40 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func113(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 50 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func114(uint8_t a1) { + char v = a1 << 6; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func115(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 12 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func116(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func117(uint8_t a1) { + char v = a1 >> 5; + if ( v > 79 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func118(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func119(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 44 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func120(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = ((a1 & a2)) | a3; + if ( v <= 28 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func121(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 93 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func122(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 40 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func123(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func124(uint8_t a1) { + char v = a1 >> 5; + if ( v <= 0 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func125(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func126(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func127(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 8 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func128(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func129(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 3 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func130(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 102 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func131(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 68 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func132(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 73 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func133(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 68 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func134(uint8_t a1) { + char v = 16 * a1; + if ( v > 125 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func135(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 79 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func136(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 6 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func137(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func138(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func139(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func140(uint8_t a1) { + char v = a1 >> 5; + if ( v > 74 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func141(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func142(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 89 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func143(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 46 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func144(uint8_t a1) { + char v = 16 * a1; + if ( v <= 29 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func145(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 77 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func146(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 12 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func147(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func148(uint8_t a1) { + char v = a1 >> 5; + if ( v > 27 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func149(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func150(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v > 122 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func151(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 3 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func152(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 56 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func153(uint8_t a1) { + char v = 16 * a1; + if ( v <= 3 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func154(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 43 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func155(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func156(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func157(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func158(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func159(uint8_t a1) { + char v = a1 >> 5; + if ( v > 88 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func160(uint8_t a1) { + char v = ~a1; + if ( v > 33 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func161(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 46 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func162(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func163(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = ((a1 & a2)) | a3; + if ( v <= 9 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func164(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 96 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func165(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func166(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func167(uint8_t a1) { + char v = a1 >> 5; + if ( v > 91 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func168(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func169(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 32 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func170(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 32 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func171(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func172(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func173(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func174(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 90 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func175(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 32 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func176(uint8_t a1) { + char v = 16 * a1; + if ( v <= 61 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func177(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 33 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func178(uint8_t a1) { + char v = a1 >> 5; + if ( v > 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func179(uint8_t a1) { + char v = ~a1; + if ( v > 64 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func180(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 95 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func181(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 48 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func182(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 113 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func183(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 41 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func184(uint8_t a1) { + char v = 16 * a1; + if ( v <= 63 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func185(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func186(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func187(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 43 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func188(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v <= 57 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func189(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func190(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 103 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func191(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v > 92 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func192(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func193(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = ((a1 & a2)) | a3; + if ( v <= 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func194(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 20 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func195(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 82 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func196(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v > 117 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func197(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 50 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func198(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 118 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func199(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v == 127 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func200(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func201(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 67 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func202(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 56 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func203(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v > 95 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func204(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func205(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = ((a1 ^ a2)) | a3; + if ( v > 95 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func206(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 78 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func207(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v <= 7 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func208(uint8_t a1) { + char v = a1 >> 5; + if ( v > 123 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func209(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func210(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 101 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func211(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 61 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func212(uint8_t a1) { + char v = 16 * a1; + if ( v <= 73 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func213(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 34 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func214(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func215(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 5 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func216(uint8_t a1) { + char v = ~a1; + if ( v > 85 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func217(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 113 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func218(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v > 61 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func219(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v > 90 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func220(uint8_t a1) { + char v = a1 >> 5; + if ( v > 106 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func221(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func222(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 84 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func223(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 81 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func224(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func225(uint8_t a1) { + char v = a1 >> 5; + if ( v > 49 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func226(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func227(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 66 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func228(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 81 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func229(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 41 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func230(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 82 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func231(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 84 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func232(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 34 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func233(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 66 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func234(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 90 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func235(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 73 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func236(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 12 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func237(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 9 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func238(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 42 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func239(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 44 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func240(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 14 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func241(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func242(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 74 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func243(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 102 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func244(uint8_t a1) { + char v = 4 * a1; + if ( v <= 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func245(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 87 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func246(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 29 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func247(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 51 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func248(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 74 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func249(uint8_t a1) { + char v = 4 * a1; + if ( v <= 103 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func250(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 56 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func251(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 11 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func252(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func253(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 22 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func254(uint8_t a1, uint8_t a2, uint8_t a3) { + char v = ((a1 & a2)) | a3; + if ( v > 122 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func255(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 74 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func256(uint8_t a1) { + char v = 4 * a1; + if ( v <= 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func257(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 67 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func258(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 102 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func259(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 74 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func260(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 27 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func261(uint8_t a1) { + char v = 4 * a1; + if ( v <= 58 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func262(uint8_t a1) { + char v = 4 * a1; + if ( v <= 77 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func263(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 3 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func264(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 13 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func265(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 47 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func266(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 39 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func267(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v == 127 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func268(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 66 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func269(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 47 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func270(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 63 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func271(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 122 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func272(uint8_t a1) { + char v = 4 * a1; + if ( v <= 65 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func273(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 120 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func274(uint8_t a1) { + char v = 4 * a1; + if ( v <= 83 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func275(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 99 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func276(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func277(uint8_t a1) { + char v = a1 >> 5; + if ( v > 42 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func278(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func279(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 110 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func280(uint8_t a1) { + char v = 4 * a1; + if ( v <= 92 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func281(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 59 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func282(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func283(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func284(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func285(uint8_t a1) { + char v = ~a1; + if ( v > 17 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func286(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func287(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 78 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func288(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 47 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func289(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 90 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func290(uint8_t a1) { + char v = 16 * a1; + if ( v <= 78 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func291(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 30 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func292(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func293(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func294(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func295(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 17 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func296(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 86 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func297(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 120 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func298(uint8_t a1) { + char v = 16 * a1; + if ( v <= 46 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func299(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 63 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func300(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 5 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func301(uint8_t a1) { + char v = ~a1; + if ( v > 17 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func302(uint8_t a1) { + char v = ~a1; + if ( v > 113 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func303(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func304(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 73 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func305(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 60 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func306(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 119 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func307(uint8_t a1) { + char v = ~a1; + if ( v > 21 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func308(uint8_t a1) { + char v = ~a1; + if ( v > 107 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func309(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 44 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func310(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 57 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func311(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 59 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func312(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func313(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func314(uint8_t a1) { + char v = a1 >> 5; + if ( v > 58 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func315(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func316(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 101 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func317(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 99 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func318(uint8_t a1) { + char v = 16 * a1; + if ( v <= 78 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func319(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 16 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func320(uint8_t a1) { + char v = ~a1; + if ( v > 10 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func321(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func322(uint8_t a1) { + char v = a1 >> 5; + if ( v > 3 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func323(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func324(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v > 118 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func325(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func326(uint8_t a1) { + char v = 16 * a1; + if ( v <= 0 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func327(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 101 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func328(uint8_t a1) { + char v = a1 >> 5; + if ( v > 18 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func329(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func330(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 0 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func331(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 67 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func332(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 103 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func333(uint8_t a1) { + char v = 16 * a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func334(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 38 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func335(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func336(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func337(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v > 63 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func338(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func339(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v <= 47 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func340(uint8_t a1) { + char v = a1 >> 5; + if ( v <= 0 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func341(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func342(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v > 118 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func343(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 58 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func344(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 91 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func345(uint8_t a1) { + char v = 16 * a1; + if ( v <= 72 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func346(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 63 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func347(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func348(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func349(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v <= 57 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func350(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func351(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 99 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func352(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v > 63 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func353(uint8_t a1) { + char v = a1 >> 5; + if ( v > 81 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func354(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func355(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v > 118 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func356(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func357(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 72 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func358(uint8_t a1) { + char v = 16 * a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func359(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 110 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func360(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func361(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 68 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func362(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v > 91 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func363(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func364(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 99 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func365(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v <= 40 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func366(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v <= 31 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func367(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func368(uint8_t a1) { + char v = a1 >> 5; + if ( v > 96 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func369(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func370(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 42 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func371(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 118 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func372(uint8_t a1) { + char v = (char)a1 >> 1; + if ( v > 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func373(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func374(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func375(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 64 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func376(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 110 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func377(uint8_t a1) { + char v = 4 * a1; + if ( v <= 104 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func378(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v > 112 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func379(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 62 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func380(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 48 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func381(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 58 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func382(uint8_t a1) { + char v = 4 * a1; + if ( v <= 104 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func383(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 50 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func384(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 38 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func385(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 85 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func386(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 18 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func387(uint8_t a1) { + char v = 4 * a1; + if ( v <= 97 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func388(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func389(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 26 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func390(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 67 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func391(uint8_t a1) { + char v = 4 * a1; + if ( v <= 103 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func392(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v > 50 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func393(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v <= 22 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func394(uint8_t a1) { + char v = 4 * a1; + if ( v <= 103 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func395(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 38 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func396(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 52 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func397(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 17 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func398(uint8_t a1) { + char v = 4 * a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func399(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 92 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func400(uint8_t a1, uint8_t a2) { + char v = (a1 & a2); + if ( v <= 55 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func401(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 81 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func402(uint8_t a1) { + char v = 4 * a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func403(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 94 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func404(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func405(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func406(uint8_t a1, uint8_t a2) { + char v = (a1 ^ a2); + if ( v > 101 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func407(uint8_t a1) { + char v = 4 * a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func408(uint8_t a1, uint8_t a2) { + char v = a1 | a2; + if ( v <= 44 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func409(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +__attribute__((noinline)) +int func410(uint8_t a1) { + char v = ~a1; + if ( v > 1 ) + return 0; + return 1; +} + +int api(const uint8_t *data, size_t size) { + if (size != 20) return 0; + + if (func1(data[0], data[1]) == 0) + return 0; + if (func2(data[0], data[1]) == 0) + return 0; + if (func3(data[18], data[1]) == 0) + return 0; + if (func4(data[7], data[4], data[0]) == 0) + return 0; + if (func5(data[0], data[2]) == 0) + return 0; + if (func6(data[11], data[17]) == 0) + return 0; + if (func7(data[0], data[13]) == 0) + return 0; + if (func8(data[13], data[10]) == 0) + return 0; + if (func9(data[11], data[16]) == 0) + return 0; + if (func10(data[10], data[8]) == 0) + return 0; + if (func11(data[19], data[5]) == 0) + return 0; + if (func12(data[0], data[1]) == 0) + return 0; + if (func13(data[17], data[3]) == 0) + return 0; + if (func14(data[14]) == 0) + return 0; + if (func15(data[13], data[15]) == 0) + return 0; + if (func16(data[0]) == 0) + return 0; + if (func17(data[19]) == 0) + return 0; + if (func18(data[1], data[11]) == 0) + return 0; + if (func19(data[12], data[15]) == 0) + return 0; + if (func20(data[13], data[1]) == 0) + return 0; + if (func21(data[10], data[19], data[12]) == 0) + return 0; + if (func22(data[6]) == 0) + return 0; + if (func23(data[1], data[9]) == 0) + return 0; + if (func24(data[16]) == 0) + return 0; + if (func25(data[6]) == 0) + return 0; + if (func26(data[4], data[12]) == 0) + return 0; + if (func27(data[16]) == 0) + return 0; + if (func28(data[14]) == 0) + return 0; + if (func29(data[0]) == 0) + return 0; + if (func30(data[19]) == 0) + return 0; + if (func31(data[0], data[1]) == 0) + return 0; + if (func32(data[0], data[1]) == 0) + return 0; + if (func33(data[14]) == 0) + return 0; + if (func34(data[0], data[19]) == 0) + return 0; + if (func35(data[0]) == 0) + return 0; + if (func36(data[16], data[7]) == 0) + return 0; + if (func37(data[19]) == 0) + return 0; + if (func38(data[15], data[3]) == 0) + return 0; + if (func39(data[19], data[15]) == 0) + return 0; + if (func40(data[0], data[1]) == 0) + return 0; + if (func41(data[18], data[1]) == 0) + return 0; + if (func42(data[16], data[5], data[1]) == 0) + return 0; + if (func43(data[14]) == 0) + return 0; + if (func44(data[0]) == 0) + return 0; + if (func45(data[19]) == 0) + return 0; + if (func46(data[4], data[19]) == 0) + return 0; + if (func47(data[8], data[7]) == 0) + return 0; + if (func48(data[6], data[7]) == 0) + return 0; + if (func49(data[18], data[1]) == 0) + return 0; + if (func50(data[2], data[8]) == 0) + return 0; + if (func51(data[2], data[13]) == 0) + return 0; + if (func52(data[3], data[8]) == 0) + return 0; + if (func53(data[16], data[18]) == 0) + return 0; + if (func54(data[10], data[9]) == 0) + return 0; + if (func55(data[18], data[1]) == 0) + return 0; + if (func56(data[0], data[1]) == 0) + return 0; + if (func57(data[16], data[1]) == 0) + return 0; + if (func58(data[18], data[1]) == 0) + return 0; + if (func59(data[18], data[3]) == 0) + return 0; + if (func60(data[9], data[1]) == 0) + return 0; + if (func61(data[0], data[1]) == 0) + return 0; + if (func62(data[13], data[1]) == 0) + return 0; + if (func63(data[18], data[1]) == 0) + return 0; + if (func64(data[0], data[1]) == 0) + return 0; + if (func65(data[0], data[1]) == 0) + return 0; + if (func66(data[11], data[14]) == 0) + return 0; + if (func67(data[5], data[11]) == 0) + return 0; + if (func68(data[18], data[1]) == 0) + return 0; + if (func69(data[0], data[6]) == 0) + return 0; + if (func70(data[2]) == 0) + return 0; + if (func71(data[0], data[1]) == 0) + return 0; + if (func72(data[9], data[10]) == 0) + return 0; + if (func73(data[10], data[8]) == 0) + return 0; + if (func74(data[19], data[17]) == 0) + return 0; + if (func75(data[0], data[17], data[8]) == 0) + return 0; + if (func76(data[17], data[18]) == 0) + return 0; + if (func77(data[18], data[9]) == 0) + return 0; + if (func78(data[3], data[6]) == 0) + return 0; + if (func79(data[16]) == 0) + return 0; + if (func80(data[7], data[3], data[17]) == 0) + return 0; + if (func81(data[0], data[1]) == 0) + return 0; + if (func82(data[10], data[18]) == 0) + return 0; + if (func83(data[6], data[7]) == 0) + return 0; + if (func84(data[0], data[6]) == 0) + return 0; + if (func85(data[12]) == 0) + return 0; + if (func86(data[0], data[1]) == 0) + return 0; + if (func87(data[6], data[1]) == 0) + return 0; + if (func88(data[18], data[1]) == 0) + return 0; + if (func89(data[0], data[6]) == 0) + return 0; + if (func90(data[0], data[1]) == 0) + return 0; + if (func91(data[18], data[1]) == 0) + return 0; + if (func92(data[0], data[6]) == 0) + return 0; + if (func93(data[13], data[10]) == 0) + return 0; + if (func94(data[2]) == 0) + return 0; + if (func95(data[0], data[1]) == 0) + return 0; + if (func96(data[0], data[11]) == 0) + return 0; + if (func97(data[18], data[1]) == 0) + return 0; + if (func98(data[0], data[6]) == 0) + return 0; + if (func99(data[0], data[19]) == 0) + return 0; + if (func100(data[14], data[18], data[3]) == 0) + return 0; + if (func101(data[14]) == 0) + return 0; + if (func102(data[6], data[1]) == 0) + return 0; + if (func103(data[5], data[1]) == 0) + return 0; + if (func104(data[14], data[3], data[10]) == 0) + return 0; + if (func105(data[18], data[1]) == 0) + return 0; + if (func106(data[0], data[6]) == 0) + return 0; + if (func107(data[6]) == 0) + return 0; + if (func108(data[9], data[10]) == 0) + return 0; + if (func109(data[7]) == 0) + return 0; + if (func110(data[9], data[17]) == 0) + return 0; + if (func111(data[16], data[15], data[18]) == 0) + return 0; + if (func112(data[0], data[16]) == 0) + return 0; + if (func113(data[18], data[3]) == 0) + return 0; + if (func114(data[3]) == 0) + return 0; + if (func115(data[0], data[1]) == 0) + return 0; + if (func116(data[14]) == 0) + return 0; + if (func117(data[0]) == 0) + return 0; + if (func118(data[19]) == 0) + return 0; + if (func119(data[0], data[6]) == 0) + return 0; + if (func120(data[9], data[5], data[0]) == 0) + return 0; + if (func121(data[0], data[1]) == 0) + return 0; + if (func122(data[12], data[4]) == 0) + return 0; + if (func123(data[14]) == 0) + return 0; + if (func124(data[0]) == 0) + return 0; + if (func125(data[19]) == 0) + return 0; + if (func126(data[14]) == 0) + return 0; + if (func127(data[1], data[9]) == 0) + return 0; + if (func128(data[19]) == 0) + return 0; + if (func129(data[11], data[14]) == 0) + return 0; + if (func130(data[11], data[9]) == 0) + return 0; + if (func131(data[12], data[15]) == 0) + return 0; + if (func132(data[0], data[2]) == 0) + return 0; + if (func133(data[13], data[1]) == 0) + return 0; + if (func134(data[7]) == 0) + return 0; + if (func135(data[13], data[5]) == 0) + return 0; + if (func136(data[12], data[14]) == 0) + return 0; + if (func137(data[9], data[4]) == 0) + return 0; + if (func138(data[6]) == 0) + return 0; + if (func139(data[14]) == 0) + return 0; + if (func140(data[0]) == 0) + return 0; + if (func141(data[19]) == 0) + return 0; + if (func142(data[11], data[9]) == 0) + return 0; + if (func143(data[12], data[15]) == 0) + return 0; + if (func144(data[7]) == 0) + return 0; + if (func145(data[19], data[7]) == 0) + return 0; + if (func146(data[4], data[6]) == 0) + return 0; + if (func147(data[6]) == 0) + return 0; + if (func148(data[0]) == 0) + return 0; + if (func149(data[19]) == 0) + return 0; + if (func150(data[11], data[9]) == 0) + return 0; + if (func151(data[12], data[15]) == 0) + return 0; + if (func152(data[13], data[1]) == 0) + return 0; + if (func153(data[7]) == 0) + return 0; + if (func154(data[2], data[8]) == 0) + return 0; + if (func155(data[13], data[5]) == 0) + return 0; + if (func156(data[6]) == 0) + return 0; + if (func157(data[6]) == 0) + return 0; + if (func158(data[14]) == 0) + return 0; + if (func159(data[0]) == 0) + return 0; + if (func160(data[19]) == 0) + return 0; + if (func161(data[12], data[15]) == 0) + return 0; + if (func162(data[5]) == 0) + return 0; + if (func163(data[6], data[7], data[3]) == 0) + return 0; + if (func164(data[13], data[5]) == 0) + return 0; + if (func165(data[6]) == 0) + return 0; + if (func166(data[14]) == 0) + return 0; + if (func167(data[0]) == 0) + return 0; + if (func168(data[19]) == 0) + return 0; + if (func169(data[11], data[9]) == 0) + return 0; + if (func170(data[9], data[11]) == 0) + return 0; + if (func171(data[6]) == 0) + return 0; + if (func172(data[14]) == 0) + return 0; + if (func173(data[19]) == 0) + return 0; + if (func174(data[11], data[9]) == 0) + return 0; + if (func175(data[12], data[15]) == 0) + return 0; + if (func176(data[7]) == 0) + return 0; + if (func177(data[13], data[5]) == 0) + return 0; + if (func178(data[0]) == 0) + return 0; + if (func179(data[19]) == 0) + return 0; + if (func180(data[11], data[9]) == 0) + return 0; + if (func181(data[12], data[15]) == 0) + return 0; + if (func182(data[13], data[1]) == 0) + return 0; + if (func183(data[7], data[17]) == 0) + return 0; + if (func184(data[7]) == 0) + return 0; + if (func185(data[6]) == 0) + return 0; + if (func186(data[4], data[12]) == 0) + return 0; + if (func187(data[2], data[8]) == 0) + return 0; + if (func188(data[16]) == 0) + return 0; + if (func189(data[6]) == 0) + return 0; + if (func190(data[4], data[12]) == 0) + return 0; + if (func191(data[16]) == 0) + return 0; + if (func192(data[19]) == 0) + return 0; + if (func193(data[19], data[4], data[2]) == 0) + return 0; + if (func194(data[11], data[9]) == 0) + return 0; + if (func195(data[12], data[15]) == 0) + return 0; + if (func196(data[13], data[15]) == 0) + return 0; + if (func197(data[13], data[1]) == 0) + return 0; + if (func198(data[19], data[5]) == 0) + return 0; + if (func199(data[13], data[5]) == 0) + return 0; + if (func200(data[6]) == 0) + return 0; + if (func201(data[4], data[12]) == 0) + return 0; + if (func202(data[5], data[17]) == 0) + return 0; + if (func203(data[16]) == 0) + return 0; + if (func204(data[6]) == 0) + return 0; + if (func205(data[7], data[3], data[17]) == 0) + return 0; + if (func206(data[4], data[12]) == 0) + return 0; + if (func207(data[16]) == 0) + return 0; + if (func208(data[0]) == 0) + return 0; + if (func209(data[19]) == 0) + return 0; + if (func210(data[11], data[9]) == 0) + return 0; + if (func211(data[13], data[1]) == 0) + return 0; + if (func212(data[7]) == 0) + return 0; + if (func213(data[13], data[5]) == 0) + return 0; + if (func214(data[6]) == 0) + return 0; + if (func215(data[4], data[12]) == 0) + return 0; + if (func216(data[6]) == 0) + return 0; + if (func217(data[4], data[12]) == 0) + return 0; + if (func218(data[16]) == 0) + return 0; + if (func219(data[16]) == 0) + return 0; + if (func220(data[0]) == 0) + return 0; + if (func221(data[19]) == 0) + return 0; + if (func222(data[0], data[1]) == 0) + return 0; + if (func223(data[0], data[1]) == 0) + return 0; + if (func224(data[14]) == 0) + return 0; + if (func225(data[0]) == 0) + return 0; + if (func226(data[19]) == 0) + return 0; + if (func227(data[0], data[1]) == 0) + return 0; + if (func228(data[0], data[1]) == 0) + return 0; + if (func229(data[18], data[1]) == 0) + return 0; + if (func230(data[0], data[1]) == 0) + return 0; + if (func231(data[17], data[3]) == 0) + return 0; + if (func232(data[0], data[1]) == 0) + return 0; + if (func233(data[18], data[1]) == 0) + return 0; + if (func234(data[0], data[1]) == 0) + return 0; + if (func235(data[18], data[4]) == 0) + return 0; + if (func236(data[18], data[1]) == 0) + return 0; + if (func237(data[0], data[1]) == 0) + return 0; + if (func238(data[2], data[8]) == 0) + return 0; + if (func239(data[13], data[0]) == 0) + return 0; + if (func240(data[0], data[1]) == 0) + return 0; + if (func241(data[0], data[1]) == 0) + return 0; + if (func242(data[18], data[1]) == 0) + return 0; + if (func243(data[0], data[6]) == 0) + return 0; + if (func244(data[2]) == 0) + return 0; + if (func245(data[0], data[1]) == 0) + return 0; + if (func246(data[1], data[11]) == 0) + return 0; + if (func247(data[18], data[1]) == 0) + return 0; + if (func248(data[0], data[6]) == 0) + return 0; + if (func249(data[2]) == 0) + return 0; + if (func250(data[0], data[1]) == 0) + return 0; + if (func251(data[4], data[6]) == 0) + return 0; + if (func252(data[0], data[1]) == 0) + return 0; + if (func253(data[18], data[1]) == 0) + return 0; + if (func254(data[16], data[15], data[18]) == 0) + return 0; + if (func255(data[0], data[6]) == 0) + return 0; + if (func256(data[2]) == 0) + return 0; + if (func257(data[16], data[18]) == 0) + return 0; + if (func258(data[0], data[1]) == 0) + return 0; + if (func259(data[0], data[6]) == 0) + return 0; + if (func260(data[9], data[13]) == 0) + return 0; + if (func261(data[2]) == 0) + return 0; + if (func262(data[2]) == 0) + return 0; + if (func263(data[0], data[1]) == 0) + return 0; + if (func264(data[0], data[1]) == 0) + return 0; + if (func265(data[0], data[6]) == 0) + return 0; + if (func266(data[7], data[4]) == 0) + return 0; + if (func267(data[16], data[7]) == 0) + return 0; + if (func268(data[0], data[1]) == 0) + return 0; + if (func269(data[0], data[1]) == 0) + return 0; + if (func270(data[18], data[1]) == 0) + return 0; + if (func271(data[13], data[3]) == 0) + return 0; + if (func272(data[2]) == 0) + return 0; + if (func273(data[0], data[1]) == 0) + return 0; + if (func274(data[2]) == 0) + return 0; + if (func275(data[0], data[1]) == 0) + return 0; + if (func276(data[14]) == 0) + return 0; + if (func277(data[0]) == 0) + return 0; + if (func278(data[19]) == 0) + return 0; + if (func279(data[0], data[6]) == 0) + return 0; + if (func280(data[2]) == 0) + return 0; + if (func281(data[0], data[1]) == 0) + return 0; + if (func282(data[8], data[0]) == 0) + return 0; + if (func283(data[14]) == 0) + return 0; + if (func284(data[19]) == 0) + return 0; + if (func285(data[14]) == 0) + return 0; + if (func286(data[19]) == 0) + return 0; + if (func287(data[11], data[9]) == 0) + return 0; + if (func288(data[12], data[15]) == 0) + return 0; + if (func289(data[13], data[1]) == 0) + return 0; + if (func290(data[7]) == 0) + return 0; + if (func291(data[13], data[5]) == 0) + return 0; + if (func292(data[6]) == 0) + return 0; + if (func293(data[14]) == 0) + return 0; + if (func294(data[19]) == 0) + return 0; + if (func295(data[11], data[9]) == 0) + return 0; + if (func296(data[12], data[15]) == 0) + return 0; + if (func297(data[12], data[4]) == 0) + return 0; + if (func298(data[7]) == 0) + return 0; + if (func299(data[13], data[5]) == 0) + return 0; + if (func300(data[12], data[14]) == 0) + return 0; + if (func301(data[6]) == 0) + return 0; + if (func302(data[14]) == 0) + return 0; + if (func303(data[19]) == 0) + return 0; + if (func304(data[11], data[9]) == 0) + return 0; + if (func305(data[12], data[15]) == 0) + return 0; + if (func306(data[13], data[1]) == 0) + return 0; + if (func307(data[6]) == 0) + return 0; + if (func308(data[19]) == 0) + return 0; + if (func309(data[12], data[15]) == 0) + return 0; + if (func310(data[13], data[1]) == 0) + return 0; + if (func311(data[13], data[5]) == 0) + return 0; + if (func312(data[6]) == 0) + return 0; + if (func313(data[14]) == 0) + return 0; + if (func314(data[0]) == 0) + return 0; + if (func315(data[9]) == 0) + return 0; + if (func316(data[11], data[9]) == 0) + return 0; + if (func317(data[13], data[1]) == 0) + return 0; + if (func318(data[7]) == 0) + return 0; + if (func319(data[13], data[4]) == 0) + return 0; + if (func320(data[16]) == 0) + return 0; + if (func321(data[4]) == 0) + return 0; + if (func322(data[0]) == 0) + return 0; + if (func323(data[19]) == 0) + return 0; + if (func324(data[11], data[9]) == 0) + return 0; + if (func325(data[12], data[15]) == 0) + return 0; + if (func326(data[7]) == 0) + return 0; + if (func327(data[13], data[5]) == 0) + return 0; + if (func328(data[0]) == 0) + return 0; + if (func329(data[19]) == 0) + return 0; + if (func330(data[11], data[9]) == 0) + return 0; + if (func331(data[12], data[15]) == 0) + return 0; + if (func332(data[13], data[1]) == 0) + return 0; + if (func333(data[4]) == 0) + return 0; + if (func334(data[13], data[5]) == 0) + return 0; + if (func335(data[6]) == 0) + return 0; + if (func336(data[4], data[12]) == 0) + return 0; + if (func337(data[16]) == 0) + return 0; + if (func338(data[6]) == 0) + return 0; + if (func339(data[16]) == 0) + return 0; + if (func340(data[0]) == 0) + return 0; + if (func341(data[19]) == 0) + return 0; + if (func342(data[11], data[9]) == 0) + return 0; + if (func343(data[12], data[15]) == 0) + return 0; + if (func344(data[13], data[1]) == 0) + return 0; + if (func345(data[7]) == 0) + return 0; + if (func346(data[13], data[5]) == 0) + return 0; + if (func347(data[6]) == 0) + return 0; + if (func348(data[4], data[12]) == 0) + return 0; + if (func349(data[16]) == 0) + return 0; + if (func350(data[6]) == 0) + return 0; + if (func351(data[4], data[12]) == 0) + return 0; + if (func352(data[16]) == 0) + return 0; + if (func353(data[0]) == 0) + return 0; + if (func354(data[19]) == 0) + return 0; + if (func355(data[11], data[9]) == 0) + return 0; + if (func356(data[8], data[15]) == 0) + return 0; + if (func357(data[7], data[1]) == 0) + return 0; + if (func358(data[17]) == 0) + return 0; + if (func359(data[3], data[5]) == 0) + return 0; + if (func360(data[6]) == 0) + return 0; + if (func361(data[4], data[12]) == 0) + return 0; + if (func362(data[16]) == 0) + return 0; + if (func363(data[6]) == 0) + return 0; + if (func364(data[4], data[12]) == 0) + return 0; + if (func365(data[16]) == 0) + return 0; + if (func366(data[16]) == 0) + return 0; + if (func367(data[14]) == 0) + return 0; + if (func368(data[0]) == 0) + return 0; + if (func369(data[19]) == 0) + return 0; + if (func370(data[3], data[1]) == 0) + return 0; + if (func371(data[4], data[1]) == 0) + return 0; + if (func372(data[16]) == 0) + return 0; + if (func373(data[14]) == 0) + return 0; + if (func374(data[19]) == 0) + return 0; + if (func375(data[0], data[1]) == 0) + return 0; + if (func376(data[0], data[1]) == 0) + return 0; + if (func377(data[2]) == 0) + return 0; + if (func378(data[0], data[1]) == 0) + return 0; + if (func379(data[0], data[1]) == 0) + return 0; + if (func380(data[18], data[1]) == 0) + return 0; + if (func381(data[0], data[6]) == 0) + return 0; + if (func382(data[2]) == 0) + return 0; + if (func383(data[8], data[1]) == 0) + return 0; + if (func384(data[5], data[1]) == 0) + return 0; + if (func385(data[18], data[1]) == 0) + return 0; + if (func386(data[0], data[6]) == 0) + return 0; + if (func387(data[2]) == 0) + return 0; + if (func388(data[0], data[1]) == 0) + return 0; + if (func389(data[18], data[1]) == 0) + return 0; + if (func390(data[0], data[6]) == 0) + return 0; + if (func391(data[2]) == 0) + return 0; + if (func392(data[18], data[1]) == 0) + return 0; + if (func393(data[0], data[6]) == 0) + return 0; + if (func394(data[2]) == 0) + return 0; + if (func395(data[0], data[1]) == 0) + return 0; + if (func396(data[0], data[1]) == 0) + return 0; + if (func397(data[18], data[1]) == 0) + return 0; + if (func398(data[9]) == 0) + return 0; + if (func399(data[0], data[1]) == 0) + return 0; + if (func400(data[0], data[1]) == 0) + return 0; + if (func401(data[8], data[6]) == 0) + return 0; + if (func402(data[12]) == 0) + return 0; + if (func403(data[0], data[1]) == 0) + return 0; + if (func404(data[12]) == 0) + return 0; + if (func405(data[1]) == 0) + return 0; + if (func406(data[0], data[6]) == 0) + return 0; + if (func407(data[4]) == 0) + return 0; + if (func408(data[0], data[1]) == 0) + return 0; + if (func409(data[14]) == 0) + return 0; + if (func410(data[14]) == 0) + return 0; + + fprintf(stderr, "BINGO\n"); + abort(); + return 1; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (api(Data, Size)) { + // Should've crashed before getting here. + return 0; + } + return 0; +} + diff --git a/test/fuzzer/NullDerefTest.cpp b/test/fuzzer/NullDerefTest.cpp index 1b44b682ace6..48df0f54cfe0 100644 --- a/test/fuzzer/NullDerefTest.cpp +++ b/test/fuzzer/NullDerefTest.cpp @@ -5,7 +5,7 @@ #include <cstddef> #include <cstdint> #include <cstdlib> -#include <iostream> +#include <cstdio> static volatile int Sink; static volatile int *Null = 0; @@ -16,7 +16,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size > 1 && Data[1] == 'i') { Sink = 2; if (Size > 2 && Data[2] == '!') { - std::cout << "Found the target, dereferencing NULL\n"; + printf("Found the target, dereferencing NULL\n"); *Null = 1; } } diff --git a/test/fuzzer/OnlySomeBytesTest.cpp b/test/fuzzer/OnlySomeBytesTest.cpp new file mode 100644 index 000000000000..076cda063459 --- /dev/null +++ b/test/fuzzer/OnlySomeBytesTest.cpp @@ -0,0 +1,40 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Find ABCxxFxUxZxxx... (2048+ bytes, 'x' is any byte) +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <cstdio> + +const size_t N = 2048; +typedef const uint8_t *IN; + +static volatile int one = 1; + +extern "C" { +__attribute__((noinline)) void bad() { + fprintf(stderr, "BINGO\n"); + if (one) + abort(); +} + +__attribute__((noinline)) void f0(IN in) { + uint32_t x = in[5] + 251 * in[7] + 251 * 251 * in[9]; + if (x == 'F' + 251 * 'U' + 251 * 251 * 'Z') + bad(); +} + +__attribute__((noinline)) void fC(IN in) { if (in[2] == 'C') f0(in); } +__attribute__((noinline)) void fB(IN in) { if (in[1] == 'B') fC(in); } +__attribute__((noinline)) void fA(IN in) { if (in[0] == 'A') fB(in); } + +} // extern "C" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < N) return 0; + fA((IN)Data); + return 0; +} diff --git a/test/fuzzer/PrintUnstableStatsTest.cpp b/test/fuzzer/PrintUnstableStatsTest.cpp new file mode 100644 index 000000000000..078eb4c3d971 --- /dev/null +++ b/test/fuzzer/PrintUnstableStatsTest.cpp @@ -0,0 +1,69 @@ +#include <assert.h> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +int x = 0; +bool skip0 = false; +bool skip1 = false; +bool skip2 = false; + +__attribute__((noinline)) void det0() { x++; } +__attribute__((noinline)) void det1() { x++; } +__attribute__((noinline)) void det2() { x++; } +__attribute__((noinline)) void det3() { x++; } +__attribute__((noinline)) void det4() { x++; } + +__attribute__((noinline)) void ini0() { x++; } +__attribute__((noinline)) void ini1() { x++; } +__attribute__((noinline)) void ini2() { x++; } + +__attribute__((noinline)) void t0() { x++; } +__attribute__((noinline)) void t1() { x++; } +__attribute__((noinline)) void t2() { x++; } +__attribute__((noinline)) void t3() { x++; } +__attribute__((noinline)) void t4() { x++; } + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size == 1 && Data[0] == 'A' && !skip0) { + skip0 = true; + ini0(); + } + if (Size == 1 && Data[0] == 'B' && !skip1) { + skip1 = true; + ini1(); + } + if (Size == 1 && Data[0] == 'C' && !skip2) { + skip2 = true; + ini2(); + } + + det0(); + det1(); + int a = rand(); + det2(); + + switch (a % 5) { + case 0: + t0(); + break; + case 1: + t1(); + break; + case 2: + t2(); + break; + case 3: + t3(); + break; + case 4: + t4(); + break; + default: + assert(false); + } + + det3(); + det4(); + return 0; +} diff --git a/test/fuzzer/ShrinkValueProfileTest.cpp b/test/fuzzer/ShrinkValueProfileTest.cpp index 86e4e3cb0d9a..dddf493da697 100644 --- a/test/fuzzer/ShrinkValueProfileTest.cpp +++ b/test/fuzzer/ShrinkValueProfileTest.cpp @@ -1,7 +1,7 @@ // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// Test that we can find the minimal item in the corpus (3 bytes: "FUZ"). +// Test that we can find the minimal item in the corpus (4 bytes: "FUZZ"). #include <cstddef> #include <cstdint> #include <cstdio> diff --git a/test/fuzzer/SimpleCmpTest.cpp b/test/fuzzer/SimpleCmpTest.cpp index 8acad4ac77e8..3bb28c17318b 100644 --- a/test/fuzzer/SimpleCmpTest.cpp +++ b/test/fuzzer/SimpleCmpTest.cpp @@ -17,15 +17,15 @@ bool PrintOnce(int Line) { } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - if (Size != 22) return 0; + if (Size != 24) return 0; uint64_t x = 0; int64_t y = 0; int32_t z = 0; - uint16_t a = 0; + uint32_t a = 0; memcpy(&x, Data, 8); // 8 memcpy(&y, Data + 8, 8); // 16 memcpy(&z, Data + 16, sizeof(z)); // 20 - memcpy(&a, Data + 20, sizeof(a)); // 22 + memcpy(&a, Data + 20, sizeof(a)); // 24 const bool k32bit = sizeof(void*) == 4; if ((k32bit || x > 1234567890) && PrintOnce(__LINE__) && diff --git a/test/fuzzer/SimpleTestStdio.cpp b/test/fuzzer/SimpleTestStdio.cpp new file mode 100644 index 000000000000..ed7fe1cb3f67 --- /dev/null +++ b/test/fuzzer/SimpleTestStdio.cpp @@ -0,0 +1,26 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Simple test for a fuzzer. The fuzzer must find the string "Hi!". +#include <assert.h> +#include <cstdint> +#include <cstdio> +#include <cstdlib> + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + fprintf(stderr, "BINGO; Found the target, exiting\n"); + exit(0); + } + } + } + return 0; +} + diff --git a/test/fuzzer/SwapCmpTest.cpp b/test/fuzzer/SwapCmpTest.cpp index bbfbefe6ab71..5aa47beb22bb 100644 --- a/test/fuzzer/SwapCmpTest.cpp +++ b/test/fuzzer/SwapCmpTest.cpp @@ -11,14 +11,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size < 14) return 0; uint64_t x = 0; uint32_t y = 0; - uint16_t z = 0; + uint32_t z = 0; memcpy(&x, Data, sizeof(x)); memcpy(&y, Data + Size / 2, sizeof(y)); memcpy(&z, Data + Size - sizeof(z), sizeof(z)); x = __builtin_bswap64(x); y = __builtin_bswap32(y); - z = __builtin_bswap16(z); + z = __builtin_bswap32(z); const bool k32bit = sizeof(void*) == 4; if ((k32bit || x == 0x46555A5A5A5A5546ULL) && @@ -26,7 +26,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { y == 0x66757A7A && true ) { - if (Data[Size - 3] == 'z') { + if (Data[Size - 5] == 'z') { fprintf(stderr, "BINGO; Found the target\n"); exit(1); } diff --git a/test/fuzzer/SymbolizeDeadlock.cpp b/test/fuzzer/SymbolizeDeadlock.cpp new file mode 100644 index 000000000000..5be1be804bce --- /dev/null +++ b/test/fuzzer/SymbolizeDeadlock.cpp @@ -0,0 +1,35 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Tests that deadlocks do not occur when an OOM occurs during symbolization. + +#include <cassert> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <unistd.h> + +#include "Bingo.h" + +volatile unsigned Sink = 0; + +// Do not inline this function. We want to trigger NEW_FUNC symbolization when +// libFuzzer finds this function. We use a macro to make the name as long +// possible, hoping to increase the time spent in symbolization and increase the +// chances of triggering a deadlock. +__attribute__((noinline)) void BINGO() { + // Busy work. Inserts a delay here so the deadlock is more likely to trigger. + for (unsigned i = 0; i < 330000000; i++) Sink += i; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size < 3) return 0; + if (Data[0] == 'F' && + Data[1] == 'U' && + Data[2] == 'Z') + BINGO(); + return 0; +} + diff --git a/test/fuzzer/ThreadedLeakTest.cpp b/test/fuzzer/ThreadedLeakTest.cpp index 538d3b434808..59f3671fe9db 100644 --- a/test/fuzzer/ThreadedLeakTest.cpp +++ b/test/fuzzer/ThreadedLeakTest.cpp @@ -6,7 +6,7 @@ #include <cstdint> #include <thread> -static volatile int *Sink; +static int * volatile Sink; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size == 0) return 0; diff --git a/test/fuzzer/ThreeBytes.cpp b/test/fuzzer/ThreeBytes.cpp new file mode 100644 index 000000000000..754a5b0b56a1 --- /dev/null +++ b/test/fuzzer/ThreeBytes.cpp @@ -0,0 +1,14 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Find FUZ +#include <cstddef> +#include <cstdint> +#include <cstdlib> + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 3) return 0; + uint32_t x = Data[0] + 251 * Data[1] + 251 * 251 * Data[2]; + if (x == 'F' + 251 * 'U' + 251 * 251 * 'Z') abort(); + return 0; +} diff --git a/test/fuzzer/ThreeFunctionsTest.cpp b/test/fuzzer/ThreeFunctionsTest.cpp new file mode 100644 index 000000000000..1278cb05633d --- /dev/null +++ b/test/fuzzer/ThreeFunctionsTest.cpp @@ -0,0 +1,36 @@ +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// Find "FUZZME", the target has 3 different functions. +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> +#include <cstdio> + +extern "C" +__attribute__((noinline)) +bool Func1(const uint8_t *Data, size_t Size) { + // assumes Size >= 5, doesn't check it. + return Data[4] == 'M'; +} + +extern "C" +__attribute__((noinline)) +bool Func2(const uint8_t *Data, size_t Size) { + return Size >= 6 && Data[5] == 'E'; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size >= 5 + && Data[0] == 'F' + && Data[1] == 'U' + && Data[2] == 'Z' + && Data[3] == 'Z' + && Func1(Data, Size) + && Func2(Data, Size)) { + fprintf(stderr, "BINGO\n"); + abort(); + } + return 0; +} diff --git a/test/fuzzer/TraceMallocThreadedTest.cpp b/test/fuzzer/TraceMallocThreadedTest.cpp index 5603af344cb7..0183d939af51 100644 --- a/test/fuzzer/TraceMallocThreadedTest.cpp +++ b/test/fuzzer/TraceMallocThreadedTest.cpp @@ -7,11 +7,12 @@ #include <cstddef> #include <cstdint> #include <cstring> +#include <cstdlib> #include <thread> extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { auto C = [&] { - volatile void *a = malloc(5639); + void * volatile a = malloc(5639); free((void *)a); }; std::thread T[] = {std::thread(C), std::thread(C), std::thread(C), diff --git a/test/fuzzer/UninitializedStrlen.cpp b/test/fuzzer/UninitializedStrlen.cpp new file mode 100644 index 000000000000..5a4e778df94b --- /dev/null +++ b/test/fuzzer/UninitializedStrlen.cpp @@ -0,0 +1,14 @@ +#include <cstdint> +#include <cstring> + +volatile size_t Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 4) return 0; + if (Data[0] == 'F' && Data[1] == 'U' && Data[2] == 'Z' && Data[3] == 'Z') { + char uninit[7]; + Sink = strlen(uninit); + } + return 0; +} + diff --git a/test/fuzzer/UseAfterDtor.cpp b/test/fuzzer/UseAfterDtor.cpp new file mode 100644 index 000000000000..dcefca5cc7d5 --- /dev/null +++ b/test/fuzzer/UseAfterDtor.cpp @@ -0,0 +1,27 @@ +#include <cstdint> +#include <cstdio> + +struct Simple { + int x_; + Simple() { + x_ = 5; + } + ~Simple() { + x_ += 1; + } +}; + +Simple *volatile SimpleSink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 4) return 0; + if (Data[0] == 'F' && Data[1] == 'U' && Data[2] == 'Z' && Data[3] == 'Z') { + { + Simple S; + SimpleSink = &S; + } + if (SimpleSink->x_) fprintf(stderr, "Failed to catch use-after-dtor\n"); + } + return 0; +} + diff --git a/test/fuzzer/acquire-crash-state.test b/test/fuzzer/acquire-crash-state.test new file mode 100644 index 000000000000..952ec735be6f --- /dev/null +++ b/test/fuzzer/acquire-crash-state.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/AcquireCrashStateTest.cpp -o %t +RUN: %run %t 2>&1 | FileCheck %s +CHECK-NOT: fuzz target exited diff --git a/test/fuzzer/afl-driver-extra-stats.test b/test/fuzzer/afl-driver-extra-stats.test index a6de53302002..cddb683e6dec 100644 --- a/test/fuzzer/afl-driver-extra-stats.test +++ b/test/fuzzer/afl-driver-extra-stats.test @@ -1,8 +1,9 @@ -RUN: %no_fuzzer_cpp_compiler -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest +XFAIL: ios +RUN: %no_fuzzer_cpp_compiler %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest ; Test that not specifying an extra stats file isn't broken. RUN: unset AFL_DRIVER_EXTRA_STATS_FILENAME -RUN: %t-AFLDriverTest +RUN: %run %t-AFLDriverTest ; Test that specifying an invalid extra stats file causes a crash. RUN: ASAN_OPTIONS= AFL_DRIVER_EXTRA_STATS_FILENAME=%T not --crash %t-AFLDriverTest diff --git a/test/fuzzer/afl-driver-stderr.test b/test/fuzzer/afl-driver-stderr.test index be0efaa8f03e..d3d739d3b977 100644 --- a/test/fuzzer/afl-driver-stderr.test +++ b/test/fuzzer/afl-driver-stderr.test @@ -1,12 +1,14 @@ -RUN: %no_fuzzer_cpp_compiler -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest +XFAIL: ios +UNSUPPORTED: freebsd +RUN: %no_fuzzer_cpp_compiler %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest ; Test that not specifying a stderr file isn't broken. RUN: unset AFL_DRIVER_STDERR_DUPLICATE_FILENAME -RUN: %t-AFLDriverTest +RUN: %run %t-AFLDriverTest ; Test that specifying an invalid file causes a crash. -RUN: ASAN_OPTIONS= AFL_DRIVER_STDERR_DUPLICATE_FILENAME="%T" not --crash %t-AFLDriverTest +RUN: ASAN_OPTIONS= AFL_DRIVER_STDERR_DUPLICATE_FILENAME="%T" not --crash %run %t-AFLDriverTest ; Test that a file is created when specified as the duplicate stderr. -RUN: AFL_DRIVER_STDERR_DUPLICATE_FILENAME=%t %t-AFLDriverTest +RUN: AFL_DRIVER_STDERR_DUPLICATE_FILENAME=%t %run %t-AFLDriverTest RUN: stat %t diff --git a/test/fuzzer/afl-driver.test b/test/fuzzer/afl-driver.test index 32e7d03b43c0..552bafb0bf34 100644 --- a/test/fuzzer/afl-driver.test +++ b/test/fuzzer/afl-driver.test @@ -1,29 +1,29 @@ REQUIRES: linux -RUN: %no_fuzzer_cpp_compiler -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest +RUN: %no_fuzzer_cpp_compiler %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest RUN: echo -n "abc" > %t.file3 RUN: echo -n "abcd" > %t.file4 -RUN: %t-AFLDriverTest < %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK1 +RUN: %run %t-AFLDriverTest < %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK1 CHECK1: __afl_persistent_loop calle, Count = 1000 CHECK1: LLVMFuzzerTestOneInput called; Size = 3 -RUN: %t-AFLDriverTest < %t.file3 -42 2>&1 | FileCheck %s --check-prefix=CHECK2 +RUN: %run %t-AFLDriverTest < %t.file3 -42 2>&1 | FileCheck %s --check-prefix=CHECK2 CHECK2: __afl_persistent_loop calle, Count = 42 CHECK2: LLVMFuzzerTestOneInput called; Size = 3 -RUN: %t-AFLDriverTest < %t.file3 666 2>&1 | FileCheck %s --check-prefix=CHECK3 +RUN: %run %t-AFLDriverTest < %t.file3 666 2>&1 | FileCheck %s --check-prefix=CHECK3 CHECK3: WARNING: using the deprecated call style CHECK3: __afl_persistent_loop calle, Count = 666 CHECK3: LLVMFuzzerTestOneInput called; Size = 3 -RUN: %t-AFLDriverTest %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK4 +RUN: %run %t-AFLDriverTest %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK4 CHECK4: LLVMFuzzerTestOneInput called; Size = 3 -RUN: %t-AFLDriverTest %t.file3 %t.file4 2>&1 | FileCheck %s --check-prefix=CHECK5 +RUN: %run %t-AFLDriverTest %t.file3 %t.file4 2>&1 | FileCheck %s --check-prefix=CHECK5 CHECK5: LLVMFuzzerTestOneInput called; Size = 3 CHECK5: LLVMFuzzerTestOneInput called; Size = 4 diff --git a/test/fuzzer/bad-strcmp.test b/test/fuzzer/bad-strcmp.test index fd1621a4e1eb..7fb2a6f07353 100644 --- a/test/fuzzer/bad-strcmp.test +++ b/test/fuzzer/bad-strcmp.test @@ -1,2 +1,2 @@ RUN: %cpp_compiler %S/BadStrcmpTest.cpp -o %t-BadStrcmpTest -RUN: %t-BadStrcmpTest -runs=100000 +RUN: %run %t-BadStrcmpTest -runs=100000 diff --git a/test/fuzzer/bogus-initialize.test b/test/fuzzer/bogus-initialize.test new file mode 100644 index 000000000000..2dff2d5a2639 --- /dev/null +++ b/test/fuzzer/bogus-initialize.test @@ -0,0 +1,4 @@ +RUN: %cpp_compiler %S/BogusInitializeTest.cpp -o %t-BogusInitializeTest + +RUN: not %run %t-BogusInitializeTest 2>&1 | FileCheck %s --check-prefix=BOGUS_INITIALIZE +BOGUS_INITIALIZE: argv[0] has been modified in LLVMFuzzerInitialize diff --git a/test/fuzzer/buffer-overflow-on-input.test b/test/fuzzer/buffer-overflow-on-input.test new file mode 100644 index 000000000000..6e40b75d70bc --- /dev/null +++ b/test/fuzzer/buffer-overflow-on-input.test @@ -0,0 +1,5 @@ +RUN: %cpp_compiler %S/BufferOverflowOnInput.cpp -o %t-BufferOverflowOnInput + +RUN: not %run %t-BufferOverflowOnInput 2>&1 | FileCheck %s --check-prefix=OOB +OOB: AddressSanitizer: heap-buffer-overflow +OOB: is located 0 bytes to the right of 3-byte region diff --git a/test/fuzzer/caller-callee.test b/test/fuzzer/caller-callee.test index e4eccdc307ad..679e4a6f65a4 100644 --- a/test/fuzzer/caller-callee.test +++ b/test/fuzzer/caller-callee.test @@ -1,3 +1,4 @@ +UNSUPPORTED: freebsd RUN: %cpp_compiler %S/CallerCalleeTest.cpp -o %t-CallerCalleeTest CHECK: BINGO -RUN: not %t-CallerCalleeTest -use_value_profile=1 -cross_over=0 -seed=1 -runs=10000000 2>&1 | FileCheck %s +RUN: not %run %t-CallerCalleeTest -use_value_profile=1 -cross_over=0 -seed=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/cleanse.test b/test/fuzzer/cleanse.test index 8e45dc77d9ea..3447fcf0ff26 100644 --- a/test/fuzzer/cleanse.test +++ b/test/fuzzer/cleanse.test @@ -1,4 +1,4 @@ RUN: %cpp_compiler %S/CleanseTest.cpp -o %t-CleanseTest RUN: echo -n 0123456789ABCDEFGHIZ > %t-in -RUN: %t-CleanseTest -cleanse_crash=1 %t-in -exact_artifact_path=%t-out +RUN: %run %t-CleanseTest -cleanse_crash=1 %t-in -exact_artifact_path=%t-out RUN: echo -n ' 1 5 A Z' | diff - %t-out diff --git a/test/fuzzer/counters.test b/test/fuzzer/counters.test new file mode 100644 index 000000000000..f75d3a03783f --- /dev/null +++ b/test/fuzzer/counters.test @@ -0,0 +1,9 @@ +XFAIL: ios +UNSUPPORTED: aarch64 +RUN: %cpp_compiler %S/CounterTest.cpp -o %t-CounterTest +RUN: not %run %t-CounterTest -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s --check-prefix=COUNTERS + +COUNTERS: INITED {{.*}} {{bits:|ft:}} +COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}} +COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}} +COUNTERS: BINGO diff --git a/test/fuzzer/coverage.test b/test/fuzzer/coverage.test index 9a2179d91add..3b2341f21f69 100644 --- a/test/fuzzer/coverage.test +++ b/test/fuzzer/coverage.test @@ -1,21 +1,18 @@ +UNSUPPORTED: aarch64 RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/NullDerefTest.cpp -o %t-NullDerefTest -RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so -RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so -RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest +RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO1.cpp -fPIC %ld_flags_rpath_so1 -shared -o %dynamiclib1 +RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSO2.cpp -fPIC %ld_flags_rpath_so2 -shared -o %dynamiclib2 +RUN: %cpp_compiler -mllvm -use-unknown-locations=Disable %S/DSOTestMain.cpp %S/DSOTestExtra.cpp %ld_flags_rpath_exe1 %ld_flags_rpath_exe2 -o %t-DSOTest CHECK: COVERAGE: -CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:13 -CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:14 -CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:16 -RUN: not %t-NullDerefTest -print_coverage=1 2>&1 | FileCheck %s +CHECK: COVERED_FUNC: {{.*}}LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:13 +RUN: not %run %t-NullDerefTest -print_coverage=1 2>&1 | FileCheck %s -RUN: %t-DSOTest -print_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO +RUN: %run %t-DSOTest -print_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO DSO: COVERAGE: -DSO-DAG: COVERED:{{.*}}DSO1{{.*}}DSO1.cpp -DSO-DAG: COVERED:{{.*}}DSO2{{.*}}DSO2.cpp -DSO-DAG: COVERED:{{.*}}LLVMFuzzerTestOneInput{{.*}}DSOTestMain -DSO-DAG: UNCOVERED_LINE:{{.*}}DSO1{{.*}}DSO1.cpp -DSO-DAG: UNCOVERED_LINE:{{.*}}DSO2{{.*}}DSO2.cpp -DSO-DAG: UNCOVERED_FUNC: in Uncovered1 -DSO-DAG: UNCOVERED_FUNC: in Uncovered2 -DSO-DAG: UNCOVERED_LINE: in LLVMFuzzerTestOneInput +DSO-DAG: COVERED_FUNC:{{.*}}1{{.*}} +DSO-DAG: COVERED_FUNC:{{.*}}2{{.*}} +DSO-DAG: COVERED_FUNC:{{.*}}LLVMFuzzerTestOneInput{{.*}}DSOTestMain +DSO-DAG: UNCOVERED_PC:{{.*}}1 +DSO-DAG: UNCOVERED_PC:{{.*}}2 +DSO-DAG: UNCOVERED_PC:{{.*}}DSOTestMain diff --git a/test/fuzzer/cxxstring.test b/test/fuzzer/cxxstring.test index 7bb341ba22b4..65edeec1964a 100644 --- a/test/fuzzer/cxxstring.test +++ b/test/fuzzer/cxxstring.test @@ -1,6 +1,6 @@ -UNSUPPORTED: windows +UNSUPPORTED: windows,freebsd RUN: %cpp_compiler %S/CxxStringEqTest.cpp -o %t-CxxStringEqTest -RUN: not %t-CxxStringEqTest -seed=1 -runs=1000000 2>&1 | FileCheck %s +RUN: not %run %t-CxxStringEqTest -seed=1 -runs=1000000 2>&1 | FileCheck %s CHECK: BINGO diff --git a/test/fuzzer/dataflow.test b/test/fuzzer/dataflow.test new file mode 100644 index 000000000000..64f083735cb9 --- /dev/null +++ b/test/fuzzer/dataflow.test @@ -0,0 +1,84 @@ +# Tests the data flow tracer. +REQUIRES: linux +UNSUPPORTED: aarch64 + +# Build the tracer and the test. +RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o %t-DataFlow.o +RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,func,trace-cmp %S/ThreeFunctionsTest.cpp %t-DataFlow.o -o %t-ThreeFunctionsTestDF +RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,func,trace-cmp %S/ExplodeDFSanLabelsTest.cpp %t-DataFlow.o -o %t-ExplodeDFSanLabelsTestDF +RUN: %cpp_compiler %S/ThreeFunctionsTest.cpp -o %t-ThreeFunctionsTest + +# Dump the function list. +RUN: %t-ThreeFunctionsTestDF 2>&1 | FileCheck %s --check-prefix=FUNC_LIST +FUNC_LIST-DAG: LLVMFuzzerTestOneInput +FUNC_LIST-DAG: Func1 +FUNC_LIST-DAG: Func2 + +# Prepare the inputs. +RUN: rm -rf %t/IN +RUN: mkdir -p %t/IN +RUN: echo -n ABC > %t/IN/ABC +RUN: echo -n FUABC > %t/IN/FUABC +RUN: echo -n FUZZR > %t/IN/FUZZR +RUN: echo -n FUZZM > %t/IN/FUZZM +RUN: echo -n FUZZMU > %t/IN/FUZZMU +RUN: echo -n 1234567890123456 > %t/IN/1234567890123456 + +# ABC: No data is used, the only used label is 4 (corresponds to the size) +RUN:%t-ThreeFunctionsTestDF 0 3 %t/IN/ABC | FileCheck %s --check-prefix=IN_ABC +IN_ABC: F{{[012]}} 0001 +IN_ABC-NOT: F + +# FUABC: First 3 bytes are checked, Func1/Func2 are not called. +RUN:%t-ThreeFunctionsTestDF 0 5 %t/IN/FUABC | FileCheck %s --check-prefix=IN_FUABC +IN_FUABC: F{{[012]}} 111001 +IN_FUABC-NOT: F + +# FUZZR: 5 bytes are used (4 in one function, 5-th in the other), Func2 is not called. +RUN:%t-ThreeFunctionsTestDF 0 5 %t/IN/FUZZR | FileCheck %s --check-prefix=IN_FUZZR +IN_FUZZR-DAG: F{{[012]}} 111101 +IN_FUZZR-DAG: F{{[012]}} 000010 +IN_FUZZR-NOT: F + +# FUZZM: 5 bytes are used, both Func1 and Func2 are called, Func2 depends only on size (label 6). +RUN:%t-ThreeFunctionsTestDF 0 5 %t/IN/FUZZM | FileCheck %s --check-prefix=IN_FUZZM +IN_FUZZM-DAG: F{{[012]}} 000010 +IN_FUZZM-DAG: F{{[012]}} 111101 +IN_FUZZM-DAG: F{{[012]}} 000001 + +# FUZZMU: 6 bytes are used, both Func1 and Func2 are called, Func2 depends on byte 6 and size (label 7) +RUN:%t-ThreeFunctionsTestDF 0 6 %t/IN/FUZZMU | FileCheck %s --check-prefix=IN_FUZZMU + +# Test merge_data_flow +RUN:rm -f %t-merge-* +RUN:%t-ThreeFunctionsTestDF 0 2 %t/IN/FUZZMU > %t-merge-1 +RUN:%t-ThreeFunctionsTestDF 2 4 %t/IN/FUZZMU > %t-merge-2 +RUN:%t-ThreeFunctionsTestDF 4 6 %t/IN/FUZZMU > %t-merge-3 +RUN:%libfuzzer_src/scripts/merge_data_flow.py %t-merge-* | FileCheck %s --check-prefix=IN_FUZZMU + +# Test collect_data_flow +RUN: %libfuzzer_src/scripts/collect_data_flow.py %t-ThreeFunctionsTestDF %t/IN/FUZZMU | FileCheck %s --check-prefix=IN_FUZZMU + +IN_FUZZMU-DAG: F{{[012]}} 0000100 +IN_FUZZMU-DAG: F{{[012]}} 1111001 +IN_FUZZMU-DAG: F{{[012]}} 0000011 + +# A very simple test will cause DFSan to die with "out of labels" +RUN: not %t-ExplodeDFSanLabelsTestDF 0 16 %t/IN/1234567890123456 2>&1 | FileCheck %s --check-prefix=OUT_OF_LABELS +OUT_OF_LABELS: ==FATAL: DataFlowSanitizer: out of labels +# However we can run the same test piece by piece. +RUN: %t-ExplodeDFSanLabelsTestDF 0 2 %t/IN/1234567890123456 +RUN: %t-ExplodeDFSanLabelsTestDF 2 4 %t/IN/1234567890123456 +RUN: %t-ExplodeDFSanLabelsTestDF 4 6 %t/IN/1234567890123456 +# Or we can use collect_data_flow +RUN: %libfuzzer_src/scripts/collect_data_flow.py %t-ExplodeDFSanLabelsTestDF %t/IN/1234567890123456 + +# Test that we can run collect_data_flow on the entire corpus dir +RUN: rm -rf %t/OUT +RUN: %libfuzzer_src/scripts/collect_data_flow.py %t-ThreeFunctionsTestDF %t/IN %t/OUT +RUN: %t-ThreeFunctionsTest -data_flow_trace=%t/OUT -runs=0 -focus_function=Func2 2>&1 | FileCheck %s --check-prefix=USE_DATA_FLOW_TRACE +USE_DATA_FLOW_TRACE: INFO: Focus function is set to 'Func2' +USE_DATA_FLOW_TRACE: INFO: DataFlowTrace: reading from {{.*}}/OUT +USE_DATA_FLOW_TRACE-DAG: a8eefe2fd5d6b32028f355fafa3e739a6bf5edc => |000001| +USE_DATA_FLOW_TRACE-DGA: d28cb407e8e1a702c72d25473f0553d3ec172262 => |0000011| +USE_DATA_FLOW_TRACE: INFO: DataFlowTrace: 6 trace files, 3 functions, 2 traces with focus function diff --git a/test/fuzzer/deep-recursion.test b/test/fuzzer/deep-recursion.test index 22475f91263a..f65104004bf9 100644 --- a/test/fuzzer/deep-recursion.test +++ b/test/fuzzer/deep-recursion.test @@ -1,5 +1,5 @@ # Test that we can find a stack overflow REQUIRES: linux RUN: %cpp_compiler %S/DeepRecursionTest.cpp -o %t -RUN: not %t -seed=1 -runs=100000000 2>&1 | FileCheck %s +RUN: not %run %t -seed=1 -runs=100000000 2>&1 | FileCheck %s CHECK: ERROR: libFuzzer: deadly signal diff --git a/test/fuzzer/disable-leaks.test b/test/fuzzer/disable-leaks.test index bc120d98b38a..1c65884e3213 100644 --- a/test/fuzzer/disable-leaks.test +++ b/test/fuzzer/disable-leaks.test @@ -1,5 +1,6 @@ REQUIRES: lsan +UNSUPPORTED: aarch64 RUN: %cpp_compiler %S/AccumulateAllocationsTest.cpp -o %t-AccumulateAllocationsTest -RUN: %t-AccumulateAllocationsTest -detect_leaks=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=ACCUMULATE_ALLOCS +RUN: %run %t-AccumulateAllocationsTest -detect_leaks=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=ACCUMULATE_ALLOCS ACCUMULATE_ALLOCS: INFO: libFuzzer disabled leak detection after every mutation diff --git a/test/fuzzer/dso.test b/test/fuzzer/dso.test new file mode 100644 index 000000000000..fc1fe23818f0 --- /dev/null +++ b/test/fuzzer/dso.test @@ -0,0 +1,7 @@ +RUN: %cpp_compiler %S/DSO1.cpp -fPIC %ld_flags_rpath_so1 -shared -o %dynamiclib1 +RUN: %cpp_compiler %S/DSO2.cpp -fPIC %ld_flags_rpath_so2 -shared -o %dynamiclib2 +RUN: %cpp_compiler %S/DSOTestMain.cpp %S/DSOTestExtra.cpp %ld_flags_rpath_exe1 %ld_flags_rpath_exe2 -o %t-DSOTest + +RUN: not %run %t-DSOTest 2>&1 | FileCheck %s --check-prefix=DSO +DSO: INFO: Loaded 3 modules +DSO: BINGO diff --git a/test/fuzzer/dump_coverage.test b/test/fuzzer/dump_coverage.test index b240089ce239..41e193824de6 100644 --- a/test/fuzzer/dump_coverage.test +++ b/test/fuzzer/dump_coverage.test @@ -1,20 +1,21 @@ -RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so -RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so -RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest +UNSUPPORTED: freebsd +RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/DSO1.cpp -fPIC -shared -o %dynamiclib1 %ld_flags_rpath_so1 +RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/DSO2.cpp -fPIC -shared -o %dynamiclib2 %ld_flags_rpath_so2 +RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/DSOTestMain.cpp %S/DSOTestExtra.cpp %ld_flags_rpath_exe1 %ld_flags_rpath_exe2 -o %t-DSOTest RUN: %cpp_compiler -fsanitize-coverage=0 -fsanitize-coverage=trace-pc-guard %S/NullDerefTest.cpp -o %t-NullDerefTest RUN: rm -rf %t_workdir && mkdir -p %t_workdir -RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' not %t-NullDerefTest -dump_coverage=1 2>&1 | FileCheck %s +RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' not %run %t-NullDerefTest -dump_coverage=1 2>&1 | FileCheck %s RUN: sancov -covered-functions %t-NullDerefTest* %t_workdir/*.sancov | FileCheck %s --check-prefix=SANCOV -RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' %t-DSOTest -dump_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO -RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' not %t-NullDerefTest -dump_coverage=0 2>&1 | FileCheck %s --check-prefix=NOCOV +RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' %run %t-DSOTest -dump_coverage=1 -runs=0 2>&1 | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=DSO +RUN: env ASAN_OPTIONS=coverage_dir='"%t_workdir"' not %run %t-NullDerefTest -dump_coverage=0 2>&1 | FileCheck %s --check-prefix=NOCOV CHECK: SanitizerCoverage: {{.*}}NullDerefTest.{{.*}}.sancov: {{.*}} PCs written SANCOV: LLVMFuzzerTestOneInput DSO: SanitizerCoverage: {{.*}}DSOTest.{{.*}}.sancov: {{.*}} PCs written -DSO-DAG: SanitizerCoverage: {{.*}}DSO1.{{.*}}.sancov: {{.*}} PCs written -DSO-DAG: SanitizerCoverage: {{.*}}DSO2.{{.*}}.sancov: {{.*}} PCs written +DSO-DAG: SanitizerCoverage: {{.*}}.{{.*}}.sancov: {{.*}} PCs written +DSO-DAG: SanitizerCoverage: {{.*}}2.{{.*}}.sancov: {{.*}} PCs written NOCOV-NOT: SanitizerCoverage: {{.*}} PCs written diff --git a/test/fuzzer/equivalence-signals.test b/test/fuzzer/equivalence-signals.test index 7951636e85f8..1da66f1474f1 100644 --- a/test/fuzzer/equivalence-signals.test +++ b/test/fuzzer/equivalence-signals.test @@ -1,9 +1,14 @@ +REQUIRES: this-test-is-deprecated # Run EquivalenceATest against itself with a small timeout # to stress the signal handling and ensure that shmem doesn't mind # the signals. +UNSUPPORTED: freebsd + +# The test is not supported on Darwin +UNSUPPORTED: darwin RUN: %cpp_compiler %S/EquivalenceATest.cpp -o %t-EquivalenceATest -RUN: %t-EquivalenceATest -timeout=1 -run_equivalence_server=EQUIV_SIG_TEST & export APID=$! +RUN: %run %t-EquivalenceATest -timeout=1 -run_equivalence_server=EQ_SIG_TEST & export APID=$! RUN: sleep 3 -RUN: %t-EquivalenceATest -timeout=1 -use_equivalence_server=EQUIV_SIG_TEST -runs=500000 2>&1 +RUN: %run %t-EquivalenceATest -timeout=1 -use_equivalence_server=EQ_SIG_TEST -runs=500000 2>&1 RUN: kill -9 $APID diff --git a/test/fuzzer/equivalence.test b/test/fuzzer/equivalence.test index 12964f478a45..2438811f2809 100644 --- a/test/fuzzer/equivalence.test +++ b/test/fuzzer/equivalence.test @@ -1,9 +1,11 @@ +REQUIRES: this-test-is-deprecated +UNSUPPORTED: freebsd RUN: %cpp_compiler %S/EquivalenceATest.cpp -o %t-EquivalenceATest RUN: %cpp_compiler %S/EquivalenceBTest.cpp -o %t-EquivalenceBTest -RUN: %t-EquivalenceATest -run_equivalence_server=EQUIV_TEST & export APID=$! +RUN: %run %t-EquivalenceATest -run_equivalence_server=EQUIV_TEST & export APID=$! RUN: sleep 3 -RUN: not %t-EquivalenceBTest -use_equivalence_server=EQUIV_TEST -max_len=4096 2>&1 | FileCheck %s +RUN: not %run %t-EquivalenceBTest -use_equivalence_server=EQUIV_TEST -max_len=4096 2>&1 | FileCheck %s CHECK: ERROR: libFuzzer: equivalence-mismatch. Sizes: {{.*}}; offset 2 CHECK: SUMMARY: libFuzzer: equivalence-mismatch RUN: kill -9 $APID diff --git a/test/fuzzer/exit-report.test b/test/fuzzer/exit-report.test index f754c1376c43..65d91c5cd88a 100644 --- a/test/fuzzer/exit-report.test +++ b/test/fuzzer/exit-report.test @@ -1,5 +1,5 @@ RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest -RUN: not %t-SimpleTest 2>&1 | FileCheck %s +RUN: not %run %t-SimpleTest 2>&1 | FileCheck %s CHECK: ERROR: libFuzzer: fuzz target exited CHECK: SUMMARY: libFuzzer: fuzz target exited diff --git a/test/fuzzer/exit_on_src_pos.test b/test/fuzzer/exit_on_src_pos.test index 6a42c7ae9539..ad0fa0a7ce4e 100644 --- a/test/fuzzer/exit_on_src_pos.test +++ b/test/fuzzer/exit_on_src_pos.test @@ -1,8 +1,9 @@ # Temporary use -mllvm -use-unknown-locations=Disable so that # all instructions have debug info (file line numbers) attached. -RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest -mllvm -use-unknown-locations=Disable -RUN: %cpp_compiler %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest +# TODO: Find out why test fails on Darwin with -O2. +RUN: %cpp_compiler -O0 %S/SimpleTest.cpp -o %t-SimpleTest -mllvm -use-unknown-locations=Disable +RUN: %cpp_compiler -O0 %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest -RUN: %t-SimpleTest -exit_on_src_pos=SimpleTest.cpp:18 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS -RUN: %t-ShrinkControlFlowTest -exit_on_src_pos=Foo 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS +RUN: %run %t-SimpleTest -exit_on_src_pos=SimpleTest.cpp:18 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS +RUN: %run %t-ShrinkControlFlowTest -exit_on_src_pos=Foo 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS EXIT_ON_SRC_POS: INFO: found line matching '{{.*}}', exiting. diff --git a/test/fuzzer/extra-counters.test b/test/fuzzer/extra-counters.test index 230f74a1b0bb..a93f775dcfc5 100644 --- a/test/fuzzer/extra-counters.test +++ b/test/fuzzer/extra-counters.test @@ -1,7 +1,7 @@ REQUIRES: linux RUN: %cpp_compiler %S/TableLookupTest.cpp -o %t-TableLookupTest -RUN: not %t-TableLookupTest -print_final_stats=1 2>&1 | FileCheck %s -CHECK: BINGO +RUN: not %run %t-TableLookupTest -print_final_stats=1 2>&1 | FileCheck %s +CHECK: INFO: {{[0-9]+}} Extra Counters // Expecting >= 4096 new_units_added CHECK: stat::new_units_added:{{.*[4][0-9][0-9][0-9]}} diff --git a/test/fuzzer/fprofile-instr-generate.test b/test/fuzzer/fprofile-instr-generate.test deleted file mode 100644 index 2a3ec96f10f7..000000000000 --- a/test/fuzzer/fprofile-instr-generate.test +++ /dev/null @@ -1,7 +0,0 @@ -# Test libFuzzer + -fprofile-instr-generate -REQUIRES: linux -RUN: %cpp_compiler %S/SimpleTest.cpp -fsanitize-coverage=0 -fprofile-instr-generate -o %t-SimpleTest-fprofile-instr-generate -CHECK-NOT: INFO: Loaded 1 modules -CHECK: INFO: {{.*}} Clang Coverage Counters -CHECK: BINGO -RUN: not %t-SimpleTest-fprofile-instr-generate -runs=1000000 -seed=1 -use_clang_coverage=1 2>&1 | FileCheck %s diff --git a/test/fuzzer/full-coverage-set.test b/test/fuzzer/full-coverage-set.test new file mode 100644 index 000000000000..629873d4eb39 --- /dev/null +++ b/test/fuzzer/full-coverage-set.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest +#not %run %t-FullCoverageSetTest -timeout=15 -seed=1 -mutate_depth=2 -use_full_coverage_set=1 2>&1 | FileCheck %s diff --git a/test/fuzzer/fuzzer-customcrossover.test b/test/fuzzer/fuzzer-customcrossover.test index 5a78307c7a3b..0835081f289a 100644 --- a/test/fuzzer/fuzzer-customcrossover.test +++ b/test/fuzzer/fuzzer-customcrossover.test @@ -1,8 +1,8 @@ RUN: %cpp_compiler %S/CustomCrossOverTest.cpp -o %t-CustomCrossOverTest -RUN: not %t-CustomCrossOverTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=CHECK_CO +RUN: not %run %t-CustomCrossOverTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=CHECK_CO Disable cross_over, verify that we can't find the target w/o it. -RUN: %t-CustomCrossOverTest -seed=1 -runs=1000000 -cross_over=0 2>&1 | FileCheck %s --check-prefix=CHECK_NO_CO +RUN: %run %t-CustomCrossOverTest -seed=1 -runs=1000000 -cross_over=0 2>&1 | FileCheck %s --check-prefix=CHECK_NO_CO CHECK_CO: In LLVMFuzzerCustomCrossover CHECK_CO: BINGO diff --git a/test/fuzzer/fuzzer-customcrossoverandmutate.test b/test/fuzzer/fuzzer-customcrossoverandmutate.test index 4a7dfba2ab8b..e538d866ff2d 100644 --- a/test/fuzzer/fuzzer-customcrossoverandmutate.test +++ b/test/fuzzer/fuzzer-customcrossoverandmutate.test @@ -1,2 +1,2 @@ RUN: %cpp_compiler %S/CustomCrossOverAndMutateTest.cpp -o %t-CustomCrossOverAndMutateTest -RUN: %t-CustomCrossOverAndMutateTest -seed=1 -runs=100000 +RUN: %run %t-CustomCrossOverAndMutateTest -seed=1 -runs=100000 diff --git a/test/fuzzer/fuzzer-custommutator.test b/test/fuzzer/fuzzer-custommutator.test index 7a693cd47324..51aef2373cca 100644 --- a/test/fuzzer/fuzzer-custommutator.test +++ b/test/fuzzer/fuzzer-custommutator.test @@ -1,5 +1,5 @@ RUN: %cpp_compiler %S/CustomMutatorTest.cpp -o %t-CustomMutatorTest -RUN: not %t-CustomMutatorTest 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutator +RUN: not %run %t-CustomMutatorTest 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutator LLVMFuzzerCustomMutator: In LLVMFuzzerCustomMutator LLVMFuzzerCustomMutator: BINGO diff --git a/test/fuzzer/fuzzer-dict.test b/test/fuzzer/fuzzer-dict.test index 48c91dc1d6fe..d396f6950a13 100644 --- a/test/fuzzer/fuzzer-dict.test +++ b/test/fuzzer/fuzzer-dict.test @@ -3,6 +3,6 @@ RUN: %cpp_compiler %S/SimpleDictionaryTest.cpp -o %t-SimpleDictionaryTest CHECK: BINGO Done1000000: Done 1000000 runs in -RUN: not %t-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000003 2>&1 | FileCheck %s -RUN: %t-SimpleDictionaryTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 +RUN: not %run %t-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000003 2>&1 | FileCheck %s +RUN: %run %t-SimpleDictionaryTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000 diff --git a/test/fuzzer/fuzzer-dirs.test b/test/fuzzer/fuzzer-dirs.test index 9b6e4d1eedda..3c742b52da4c 100644 --- a/test/fuzzer/fuzzer-dirs.test +++ b/test/fuzzer/fuzzer-dirs.test @@ -5,17 +5,17 @@ RUN: mkdir -p %t/SUB1/SUB2/SUB3 RUN: echo a > %t/SUB1/a RUN: echo b > %t/SUB1/SUB2/b RUN: echo c > %t/SUB1/SUB2/SUB3/c -RUN: %t-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=SUBDIRS +RUN: %run %t-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=SUBDIRS SUBDIRS: INFO: seed corpus: files: 3 min: 2b max: 2b total: 6b RUN: echo -n zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz > %t/SUB1/f64 RUN: cat %t/SUB1/f64 %t/SUB1/f64 %t/SUB1/f64 %t/SUB1/f64 > %t/SUB1/f256 RUN: cat %t/SUB1/f256 %t/SUB1/f256 %t/SUB1/f256 %t/SUB1/f256 > %t/SUB1/f1024 RUN: cat %t/SUB1/f1024 %t/SUB1/f1024 %t/SUB1/f1024 %t/SUB1/f1024 > %t/SUB1/f4096 RUN: cat %t/SUB1/f4096 %t/SUB1/f4096 > %t/SUB1/f8192 -RUN: %t-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=LONG +RUN: %run %t-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=LONG LONG: INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 8192 bytes RUN: rm -rf %t/SUB1 -RUN: not %t-SimpleTest NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR -NONEXISTENT_DIR: No such directory: NONEXISTENT_DIR; exiting +RUN: not %run %t-SimpleTest NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR +NONEXISTENT_DIR: No such file or directory: NONEXISTENT_DIR; exiting diff --git a/test/fuzzer/fuzzer-fdmask.test b/test/fuzzer/fuzzer-fdmask.test index 3f04993b5d7e..09f29782b8a8 100644 --- a/test/fuzzer/fuzzer-fdmask.test +++ b/test/fuzzer/fuzzer-fdmask.test @@ -1,28 +1,28 @@ RUN: %cpp_compiler %S/SpamyTest.cpp -o %t-SpamyTest -RUN: %t-SpamyTest -runs=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_0 -RUN: %t-SpamyTest -runs=1 -close_fd_mask=0 2>&1 | FileCheck %s --check-prefix=FD_MASK_0 -RUN: %t-SpamyTest -runs=1 -close_fd_mask=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_1 -RUN: %t-SpamyTest -runs=1 -close_fd_mask=2 2>&1 | FileCheck %s --check-prefix=FD_MASK_2 -RUN: %t-SpamyTest -runs=1 -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=FD_MASK_3 +RUN: %run %t-SpamyTest -runs=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_0 +RUN: %run %t-SpamyTest -runs=1 -close_fd_mask=0 2>&1 | FileCheck %s --check-prefix=FD_MASK_0 +RUN: %run %t-SpamyTest -runs=1 -close_fd_mask=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_1 +RUN: %run %t-SpamyTest -runs=1 -close_fd_mask=2 2>&1 | FileCheck %s --check-prefix=FD_MASK_2 +RUN: %run %t-SpamyTest -runs=1 -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=FD_MASK_3 -FD_MASK_0: PRINTF_STDOUT -FD_MASK_0: PRINTF_STDERR -FD_MASK_0: STREAM_COUT -FD_MASK_0: STREAM_CERR -FD_MASK_0: INITED +FD_MASK_0-DAG: PRINTF_STDOUT +FD_MASK_0-DAG: PRINTF_STDERR +FD_MASK_0-DAG: STREAM_COUT +FD_MASK_0-DAG: STREAM_CERR +FD_MASK_0-DAG: INITED FD_MASK_1-NOT: PRINTF_STDOUT -FD_MASK_1: PRINTF_STDERR +FD_MASK_1-DAG: PRINTF_STDERR FD_MASK_1-NOT: STREAM_COUT -FD_MASK_1: STREAM_CERR -FD_MASK_1: INITED +FD_MASK_1-DAG: STREAM_CERR +FD_MASK_1-DAG: INITED -FD_MASK_2: PRINTF_STDOUT +FD_MASK_2-DAG: PRINTF_STDOUT +FD_MASK_2-DAG: STREAM_COUT +FD_MASK_2-DAG: INITED FD_MASK_2-NOT: PRINTF_STDERR -FD_MASK_2: STREAM_COUT -FD_MASK_2-NOTE: STREAM_CERR -FD_MASK_2: INITED +FD_MASK_2-NOT: STREAM_CERR FD_MASK_3-NOT: PRINTF_STDOUT FD_MASK_3-NOT: PRINTF_STDERR diff --git a/test/fuzzer/fuzzer-finalstats.test b/test/fuzzer/fuzzer-finalstats.test index 4f983bea825e..d8c991e30847 100644 --- a/test/fuzzer/fuzzer-finalstats.test +++ b/test/fuzzer/fuzzer-finalstats.test @@ -1,12 +1,12 @@ RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest -RUN: %t-SimpleTest -seed=1 -runs=77 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS +RUN: %run %t-SimpleTest -seed=1 -runs=77 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS FINAL_STATS: stat::number_of_executed_units: 77 FINAL_STATS: stat::average_exec_per_sec: 0 FINAL_STATS: stat::new_units_added: FINAL_STATS: stat::slowest_unit_time_sec: 0 FINAL_STATS: stat::peak_rss_mb: -RUN: %t-SimpleTest %S/dict1.txt -runs=33 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS1 +RUN: %run %t-SimpleTest %S/dict1.txt -runs=33 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS1 FINAL_STATS1: stat::number_of_executed_units: 33 FINAL_STATS1: stat::peak_rss_mb: diff --git a/test/fuzzer/fuzzer-flags.test b/test/fuzzer/fuzzer-flags.test index b812b01695d8..916c6eed889f 100644 --- a/test/fuzzer/fuzzer-flags.test +++ b/test/fuzzer/fuzzer-flags.test @@ -1,19 +1,19 @@ RUN: %cpp_compiler %S/FlagsTest.cpp -o %t-FlagsTest -RUN: %t-FlagsTest -runs=10 -foo_bar=1 2>&1 | FileCheck %s --check-prefix=FOO_BAR +RUN: %run %t-FlagsTest -runs=10 -foo_bar=1 2>&1 | FileCheck %s --check-prefix=FOO_BAR FOO_BAR: WARNING: unrecognized flag '-foo_bar=1'; use -help=1 to list all flags FOO_BAR: BINGO -RUN: %t-FlagsTest -runs=10 --max_len=100 2>&1 | FileCheck %s --check-prefix=DASH_DASH +RUN: %run %t-FlagsTest -runs=10 --max_len=100 2>&1 | FileCheck %s --check-prefix=DASH_DASH DASH_DASH: WARNING: did you mean '-max_len=100' (single dash)? DASH_DASH: INFO: A corpus is not provided, starting from an empty corpus -RUN: %t-FlagsTest -help=1 2>&1 | FileCheck %s --check-prefix=NO_INTERNAL +RUN: %run %t-FlagsTest -help=1 2>&1 | FileCheck %s --check-prefix=NO_INTERNAL NO_INTERNAL-NOT: internal flag -RUN: %t-FlagsTest --foo-bar -runs=10 -ignore_remaining_args=1 --baz -help=1 test 2>&1 | FileCheck %s --check-prefix=PASSTHRU +RUN: %run %t-FlagsTest --foo-bar -runs=10 -ignore_remaining_args=1 --baz -help=1 test 2>&1 | FileCheck %s --check-prefix=PASSTHRU PASSTHRU: BINGO --foo-bar --baz -help=1 test RUN: mkdir -p %t/T0 %t/T1 RUN: echo z > %t/T1/z -RUN: %t-FlagsTest -runs=10 --foo-bar -merge=1 %t/T0 %t/T1 -ignore_remaining_args=1 --baz -help=1 test 2>&1 | FileCheck %s --check-prefix=PASSTHRU-MERGE +RUN: %run %t-FlagsTest -runs=10 --foo-bar -merge=1 %t/T0 %t/T1 -ignore_remaining_args=1 --baz -help=1 test 2>&1 | FileCheck %s --check-prefix=PASSTHRU-MERGE PASSTHRU-MERGE: BINGO --foo-bar --baz -help=1 test diff --git a/test/fuzzer/fuzzer-leak.test b/test/fuzzer/fuzzer-leak.test index 0652a88f9d5d..2b61811d5d1b 100644 --- a/test/fuzzer/fuzzer-leak.test +++ b/test/fuzzer/fuzzer-leak.test @@ -1,10 +1,11 @@ REQUIRES: lsan + RUN: %cpp_compiler %S/LeakTest.cpp -o %t-LeakTest RUN: %cpp_compiler %S/ThreadedLeakTest.cpp -o %t-ThreadedLeakTest RUN: %cpp_compiler %S/LeakTimeoutTest.cpp -o %t-LeakTimeoutTest RUN: rm -rf %t-corpus && mkdir -p %t-corpus -RUN: not %t-LeakTest -runs=100000 -detect_leaks=1 %t-corpus 2>&1 | FileCheck %s --check-prefix=LEAK_DURING +RUN: not %run %t-LeakTest -runs=100000 -detect_leaks=1 %t-corpus 2>&1 | FileCheck %s --check-prefix=LEAK_DURING LEAK_DURING: ERROR: LeakSanitizer: detected memory leaks LEAK_DURING: Direct leak of 4 byte(s) in 1 object(s) allocated from: LEAK_DURING: INFO: to ignore leaks on libFuzzer side use -detect_leaks=0 @@ -13,29 +14,29 @@ LEAK_DURING-NOT: DONE LEAK_DURING-NOT: Done // Verify leaking input was not added to corpus -RUN: %t-LeakTest -runs=0 %t-corpus +RUN: %run %t-LeakTest -runs=0 %t-corpus -RUN: not %t-LeakTest -runs=0 -detect_leaks=1 %S 2>&1 | FileCheck %s --check-prefix=LEAK_IN_CORPUS +RUN: not %run %t-LeakTest -runs=0 -detect_leaks=1 %S 2>&1 | FileCheck %s --check-prefix=LEAK_IN_CORPUS LEAK_IN_CORPUS: ERROR: LeakSanitizer: detected memory leaks LEAK_IN_CORPUS: INFO: a leak has been found in the initial corpus. -RUN: not %t-LeakTest -runs=100000000 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=MULTI_RUN_LEAK +RUN: not %run %t-LeakTest -runs=100000000 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=MULTI_RUN_LEAK MULTI_RUN_LEAK-NOT: pulse MULTI_RUN_LEAK: LeakSanitizer: detected memory leaks -RUN: not %t-LeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER -RUN: not %t-LeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING -RUN: not %t-ThreadedLeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER -RUN: not %t-ThreadedLeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING +RUN: not %run %t-LeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER +RUN: not %run %t-LeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING +RUN: not %run %t-ThreadedLeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER +RUN: not %run %t-ThreadedLeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING LEAK_AFTER: Done 100000 runs in LEAK_AFTER: ERROR: LeakSanitizer: detected memory leaks -RUN: not %t-LeakTest -runs=100000 -max_len=1 2>&1 | FileCheck %s --check-prefix=MAX_LEN_1 +RUN: not %run %t-LeakTest -runs=100000 -max_len=1 2>&1 | FileCheck %s --check-prefix=MAX_LEN_1 MAX_LEN_1: Test unit written to ./leak-7cf184f4c67ad58283ecb19349720b0cae756829 -RUN: not %t-LeakTimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=LEAK_TIMEOUT +RUN: not %run %t-LeakTimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=LEAK_TIMEOUT LEAK_TIMEOUT: ERROR: libFuzzer: timeout after LEAK_TIMEOUT-NOT: LeakSanitizer -RUN: %t-LeakTest -error_exitcode=0 +RUN: %run %t-LeakTest -error_exitcode=0 diff --git a/test/fuzzer/fuzzer-mutationstats.test b/test/fuzzer/fuzzer-mutationstats.test new file mode 100644 index 000000000000..95743a818d1f --- /dev/null +++ b/test/fuzzer/fuzzer-mutationstats.test @@ -0,0 +1,5 @@ +RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-MutationStatsTest +RUN: not %run %t-MutationStatsTest -print_mutation_stats=1 2>&1 | FileCheck %s + +# Ensures there are some non-zero values in the usefulness percentages printed. +CHECK: stat::mutation_usefulness: {{[0-9]+\.[0-9]+}} diff --git a/test/fuzzer/fuzzer-oom-with-profile.test b/test/fuzzer/fuzzer-oom-with-profile.test index 75cf48430a46..918197abd5a2 100644 --- a/test/fuzzer/fuzzer-oom-with-profile.test +++ b/test/fuzzer/fuzzer-oom-with-profile.test @@ -1,6 +1,6 @@ REQUIRES: linux RUN: %cpp_compiler %S/OutOfMemoryTest.cpp -o %t-OutOfMemoryTest -RUN: not %t-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s +RUN: not %run %t-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 300Mb) CHECK: Live Heap Allocations CHECK: Test unit written to ./oom- diff --git a/test/fuzzer/fuzzer-oom.test b/test/fuzzer/fuzzer-oom.test index 308c4c5cd394..e82fb47c5bed 100644 --- a/test/fuzzer/fuzzer-oom.test +++ b/test/fuzzer/fuzzer-oom.test @@ -1,16 +1,17 @@ +UNSUPPORTED: aarch64 RUN: %cpp_compiler %S/OutOfMemoryTest.cpp -o %t-OutOfMemoryTest RUN: %cpp_compiler %S/OutOfMemorySingleLargeMallocTest.cpp -o %t-OutOfMemorySingleLargeMallocTest RUN: %cpp_compiler %S/AccumulateAllocationsTest.cpp -o %t-AccumulateAllocationsTest -RUN: not %t-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s +RUN: not %run %t-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 300Mb) CHECK: Test unit written to ./oom- SUMMARY: libFuzzer: out-of-memory -RUN: not %t-OutOfMemorySingleLargeMallocTest -rss_limit_mb=300 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC -RUN: not %t-OutOfMemorySingleLargeMallocTest -malloc_limit_mb=300 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC -RUN: not %t-OutOfMemorySingleLargeMallocTest -rss_limit_mb=1000 -malloc_limit_mb=300 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC +RUN: not %run %t-OutOfMemorySingleLargeMallocTest -rss_limit_mb=300 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC +RUN: not %run %t-OutOfMemorySingleLargeMallocTest -malloc_limit_mb=300 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC +RUN: not %run %t-OutOfMemorySingleLargeMallocTest -rss_limit_mb=1000 -malloc_limit_mb=300 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC We used to check for "out-of-memory (malloc(53{{.*}}))", but that would fail sometimes, so now we accept any OOM message. @@ -19,4 +20,4 @@ SINGLE_LARGE_MALLOC: libFuzzer: out-of-memory SINGLE_LARGE_MALLOC: in LLVMFuzzerTestOneInput # Check that -rss_limit_mb=0 means no limit. -RUN: %t-AccumulateAllocationsTest -runs=1000 -rss_limit_mb=0 +RUN: %run %t-AccumulateAllocationsTest -runs=1000 -rss_limit_mb=0 diff --git a/test/fuzzer/fuzzer-printcovpcs.test b/test/fuzzer/fuzzer-printcovpcs.test index e55ce14aa72f..decf0a7e5fff 100644 --- a/test/fuzzer/fuzzer-printcovpcs.test +++ b/test/fuzzer/fuzzer-printcovpcs.test @@ -1,5 +1,7 @@ +XFAIL: ios +UNSUPPORTED: aarch64 RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest -RUN: not %t-SimpleTest -print_pcs=1 -seed=1 2>&1 | FileCheck %s --check-prefix=PCS +RUN: not %run %t-SimpleTest -print_pcs=1 -seed=1 2>&1 | FileCheck %s --check-prefix=PCS PCS-NOT: NEW_PC PCS:INITED PCS:NEW_PC: {{0x[a-f0-9]+}} diff --git a/test/fuzzer/fuzzer-runs.test b/test/fuzzer/fuzzer-runs.test index 04987eee5029..b3f20c475aa9 100644 --- a/test/fuzzer/fuzzer-runs.test +++ b/test/fuzzer/fuzzer-runs.test @@ -1,9 +1,9 @@ RUN: mkdir -p %t RUN: %cpp_compiler %S/NthRunCrashTest.cpp -o %t-NthRunCrashTest RUN: echo abcd > %t/NthRunCrashTest.in -RUN: %t-NthRunCrashTest %t/NthRunCrashTest.in -RUN: %t-NthRunCrashTest %t/NthRunCrashTest.in -runs=10 -RUN: not %t-NthRunCrashTest %t/NthRunCrashTest.in -runs=10000 2>&1 | FileCheck %s +RUN: %run %t-NthRunCrashTest %t/NthRunCrashTest.in +RUN: %run %t-NthRunCrashTest %t/NthRunCrashTest.in -runs=10 +RUN: not %run %t-NthRunCrashTest %t/NthRunCrashTest.in -runs=10000 2>&1 | FileCheck %s RUN: rm %t/NthRunCrashTest.in CHECK: BINGO diff --git a/test/fuzzer/fuzzer-seed.test b/test/fuzzer/fuzzer-seed.test index a69ea5432849..b6343ffa3dd7 100644 --- a/test/fuzzer/fuzzer-seed.test +++ b/test/fuzzer/fuzzer-seed.test @@ -1,4 +1,4 @@ RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-SimpleCmpTest -RUN: %t-SimpleCmpTest -seed=-1 -runs=0 2>&1 | FileCheck %s --check-prefix=CHECK_SEED_MINUS_ONE +RUN: %run %t-SimpleCmpTest -seed=-1 -runs=0 2>&1 | FileCheck %s --check-prefix=CHECK_SEED_MINUS_ONE CHECK_SEED_MINUS_ONE: Seed: 4294967295 diff --git a/test/fuzzer/fuzzer-segv.test b/test/fuzzer/fuzzer-segv.test index 4d3c7575f7a8..0c4fafe08077 100644 --- a/test/fuzzer/fuzzer-segv.test +++ b/test/fuzzer/fuzzer-segv.test @@ -1,8 +1,8 @@ RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest -RUN: env ASAN_OPTIONS=handle_segv=0 not %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER +RUN: env ASAN_OPTIONS=handle_segv=0 not %run %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER LIBFUZZER_OWN_SEGV_HANDLER: == ERROR: libFuzzer: deadly signal LIBFUZZER_OWN_SEGV_HANDLER: SUMMARY: libFuzzer: deadly signal LIBFUZZER_OWN_SEGV_HANDLER: Test unit written to ./crash- -RUN: env ASAN_OPTIONS=handle_segv=1 not %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_ASAN_SEGV_HANDLER +RUN: env ASAN_OPTIONS=handle_segv=1 not %run %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_ASAN_SEGV_HANDLER LIBFUZZER_ASAN_SEGV_HANDLER: ERROR: AddressSanitizer: {{SEGV|access-violation}} on unknown address diff --git a/test/fuzzer/fuzzer-singleinputs.test b/test/fuzzer/fuzzer-singleinputs.test index 468da5622af9..704f9caa57f9 100644 --- a/test/fuzzer/fuzzer-singleinputs.test +++ b/test/fuzzer/fuzzer-singleinputs.test @@ -1,15 +1,15 @@ RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest -RUN: not %t-NullDerefTest %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInput +RUN: not %run %t-NullDerefTest %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInput SingleInput-NOT: Test unit written to ./crash- RUN: rm -rf %tmp/SINGLE_INPUTS RUN: mkdir -p %tmp/SINGLE_INPUTS RUN: echo aaa > %tmp/SINGLE_INPUTS/aaa RUN: echo bbb > %tmp/SINGLE_INPUTS/bbb -RUN: %t-SimpleTest %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS -RUN: %t-SimpleTest -max_len=2 %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS +RUN: %run %t-SimpleTest %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS +RUN: %run %t-SimpleTest -max_len=2 %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS RUN: rm -rf %tmp/SINGLE_INPUTS SINGLE_INPUTS: SimpleTest{{.*}}: Running 2 inputs 1 time(s) each. SINGLE_INPUTS: aaa in diff --git a/test/fuzzer/fuzzer-threaded.test b/test/fuzzer/fuzzer-threaded.test index 572ed5a35518..3321e19585c0 100644 --- a/test/fuzzer/fuzzer-threaded.test +++ b/test/fuzzer/fuzzer-threaded.test @@ -1,8 +1,8 @@ CHECK: Done 1000 runs in RUN: %cpp_compiler %S/ThreadedTest.cpp -o %t-ThreadedTest -RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s -RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s -RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s -RUN: %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: %run %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: %run %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: %run %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s +RUN: %run %t-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s diff --git a/test/fuzzer/fuzzer-timeout.test b/test/fuzzer/fuzzer-timeout.test index 41f4ba364398..a924cde73373 100644 --- a/test/fuzzer/fuzzer-timeout.test +++ b/test/fuzzer/fuzzer-timeout.test @@ -1,6 +1,6 @@ RUN: %cpp_compiler %S/TimeoutTest.cpp -o %t-TimeoutTest RUN: %cpp_compiler %S/TimeoutEmptyTest.cpp -o %t-TimeoutEmptyTest -RUN: not %t-TimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutTest +RUN: not %run %t-TimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutTest TimeoutTest: ALARM: working on the last Unit for TimeoutTest: Test unit written to ./timeout- TimeoutTest: == ERROR: libFuzzer: timeout after @@ -9,13 +9,13 @@ TimeoutTest: #1 TimeoutTest: #2 TimeoutTest: SUMMARY: libFuzzer: timeout -RUN: not %t-TimeoutTest -timeout=1 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInputTimeoutTest +RUN: not %run %t-TimeoutTest -timeout=1 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInputTimeoutTest SingleInputTimeoutTest: ALARM: working on the last Unit for {{[1-3]}} seconds SingleInputTimeoutTest-NOT: Test unit written to ./timeout- -RUN: %t-TimeoutTest -timeout=1 -timeout_exitcode=0 +RUN: %run %t-TimeoutTest -timeout=1 -timeout_exitcode=0 -RUN: not %t-TimeoutEmptyTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutEmptyTest +RUN: not %run %t-TimeoutEmptyTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutEmptyTest TimeoutEmptyTest: ALARM: working on the last Unit for TimeoutEmptyTest: == ERROR: libFuzzer: timeout after TimeoutEmptyTest: SUMMARY: libFuzzer: timeout diff --git a/test/fuzzer/fuzzer-ubsan.test b/test/fuzzer/fuzzer-ubsan.test index 49c190cd034b..6bc2c3863668 100644 --- a/test/fuzzer/fuzzer-ubsan.test +++ b/test/fuzzer/fuzzer-ubsan.test @@ -1,5 +1,5 @@ RUN: %cpp_compiler -fsanitize=undefined -fno-sanitize-recover=all %S/SignedIntOverflowTest.cpp -o %t-SignedIntOverflowTest-Ubsan -RUN: not %t-SignedIntOverflowTest-Ubsan 2>&1 | FileCheck %s +RUN: not %run %t-SignedIntOverflowTest-Ubsan 2>&1 | FileCheck %s CHECK: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int' CHECK: Test unit written to ./crash- diff --git a/test/fuzzer/fuzzer.test b/test/fuzzer/fuzzer.test deleted file mode 100644 index 29bc8f0ce795..000000000000 --- a/test/fuzzer/fuzzer.test +++ /dev/null @@ -1,70 +0,0 @@ -CHECK: BINGO -Done1000000: Done 1000000 runs in -RUN: %cpp_compiler %S/BogusInitializeTest.cpp -o %t-BogusInitializeTest -RUN: %cpp_compiler %S/BufferOverflowOnInput.cpp -o %t-BufferOverflowOnInput -RUN: %cpp_compiler %S/CounterTest.cpp -o %t-CounterTest -RUN: %cpp_compiler %S/DSO1.cpp -fPIC -shared -o %t-DSO1.so -RUN: %cpp_compiler %S/DSO2.cpp -fPIC -shared -o %t-DSO2.so -RUN: %cpp_compiler %S/DSOTestMain.cpp %S/DSOTestExtra.cpp -L. %t-DSO1.so %t-DSO2.so -o %t-DSOTest -RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest -RUN: %cpp_compiler %S/InitializeTest.cpp -o %t-InitializeTest -RUN: %cpp_compiler %S/NotinstrumentedTest.cpp -fsanitize-coverage=0 -o %t-NotinstrumentedTest-NoCoverage -RUN: %cpp_compiler %S/NullDerefOnEmptyTest.cpp -o %t-NullDerefOnEmptyTest -RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest -RUN: %cpp_compiler %S/SimpleCmpTest.cpp -o %t-SimpleCmpTest -RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest -RUN: %cpp_compiler %S/StrncmpOOBTest.cpp -o %t-StrncmpOOBTest - -RUN: not %t-SimpleTest 2>&1 | FileCheck %s - -# only_ascii mode. Will perform some minimal self-validation. -RUN: not %t-SimpleTest -only_ascii=1 2>&1 - -RUN: %t-SimpleCmpTest -max_total_time=1 -use_cmp=0 2>&1 | FileCheck %s --check-prefix=MaxTotalTime -MaxTotalTime: Done {{.*}} runs in {{.}} second(s) - -RUN: not %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest -RUN: not %t-NullDerefTest -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=NullDerefTest -NullDerefTest: ERROR: AddressSanitizer: {{SEGV|access-violation}} on unknown address -NullDerefTest: Test unit written to ./crash- -RUN: not %t-NullDerefTest -artifact_prefix=ZZZ 2>&1 | FileCheck %s --check-prefix=NullDerefTestPrefix -NullDerefTestPrefix: Test unit written to ZZZcrash- -RUN: not %t-NullDerefTest -artifact_prefix=ZZZ -exact_artifact_path=FOOBAR 2>&1 | FileCheck %s --check-prefix=NullDerefTestExactPath -NullDerefTestExactPath: Test unit written to FOOBAR - -RUN: not %t-NullDerefOnEmptyTest -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=NULL_DEREF_ON_EMPTY -NULL_DEREF_ON_EMPTY: stat::number_of_executed_units: - -#not %t-FullCoverageSetTest -timeout=15 -seed=1 -mutate_depth=2 -use_full_coverage_set=1 2>&1 | FileCheck %s - -RUN: not %t-CounterTest -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s --check-prefix=COUNTERS - -COUNTERS: INITED {{.*}} {{bits:|ft:}} -COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}} -COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}} -COUNTERS: BINGO - -# Don't run UninstrumentedTest for now since we build libFuzzer itself with asan. -DISABLED: not %t-UninstrumentedTest-Uninstrumented 2>&1 | FileCheck %s --check-prefix=UNINSTRUMENTED -UNINSTRUMENTED: ERROR: __sanitizer_set_death_callback is not defined. Exiting. - -RUN: not %t-NotinstrumentedTest-NoCoverage 2>&1 | FileCheck %s --check-prefix=NO_COVERAGE -NO_COVERAGE: ERROR: no interesting inputs were found. Is the code instrumented for coverage? Exiting - -RUN: not %t-BufferOverflowOnInput 2>&1 | FileCheck %s --check-prefix=OOB -OOB: AddressSanitizer: heap-buffer-overflow -OOB: is located 0 bytes to the right of 3-byte region - -RUN: not %t-InitializeTest -use_value_profile=1 2>&1 | FileCheck %s - -RUN: not %t-DSOTest 2>&1 | FileCheck %s --check-prefix=DSO -DSO: INFO: Loaded 3 modules -DSO: BINGO - -RUN: env ASAN_OPTIONS=strict_string_checks=1 not %t-StrncmpOOBTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=STRNCMP -STRNCMP: AddressSanitizer: heap-buffer-overflow -STRNCMP-NOT: __sanitizer_weak_hook_strncmp -STRNCMP: in LLVMFuzzerTestOneInput - -RUN: not %t-BogusInitializeTest 2>&1 | FileCheck %s --check-prefix=BOGUS_INITIALIZE -BOGUS_INITIALIZE: argv[0] has been modified in LLVMFuzzerInitialize diff --git a/test/fuzzer/gc-sections.test b/test/fuzzer/gc-sections.test index 8785bb00ec1b..b8abfbbdf17b 100644 --- a/test/fuzzer/gc-sections.test +++ b/test/fuzzer/gc-sections.test @@ -1,12 +1,14 @@ -REQUIRES: linux +REQUIRES: linux, lld-available No gc-sections: RUN: %cpp_compiler %S/GcSectionsTest.cpp -o %t RUN: nm %t | grep UnusedFunctionShouldBeRemovedByLinker | count 1 -With gc-sections. Currently, we can't remove unused code. -DISABLED: %cpp_compiler %S/GcSectionsTest.cpp -o %t -ffunction-sections -Wl,-gc-sections -DISABLED: nm %t | grep UnusedFunctionShouldBeRemovedByLinker | count 1 +With gc-sections. Currently, we can't remove unused code except with LLD. +RUN: %cpp_compiler %S/GcSectionsTest.cpp -o %t -fuse-ld=lld -ffunction-sections -Wl,-gc-sections +RUN: nm %t | not grep UnusedFunctionShouldBeRemovedByLinker +RUN: %run %t -runs=0 2>&1 | FileCheck %s +CHECK-NOT: ERROR: The size of coverage PC tables does not match With gc sections, with trace-pc. Unused code is removed. RUN: %cpp_compiler %S/GcSectionsTest.cpp -o %t -fsanitize-coverage=0 -fsanitize-coverage=trace-pc -ffunction-sections -Wl,-gc-sections diff --git a/test/fuzzer/handle-unstable.test b/test/fuzzer/handle-unstable.test new file mode 100644 index 000000000000..798ee2dc042f --- /dev/null +++ b/test/fuzzer/handle-unstable.test @@ -0,0 +1,42 @@ +# Tests -handle_unstable +UNSUPPORTED: aarch64 + +RUN: %cpp_compiler %S/PrintUnstableStatsTest.cpp -o %t-HandleUnstableTest + +; Normal +RUN: %run %t-HandleUnstableTest -print_coverage=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=NORMAL +NORMAL-DAG: det0() +NORMAL-DAG: det1() +NORMAL-DAG: det2() +NORMAL-DAG: det3() +NORMAL-DAG: det4() +NORMAL-DAG: ini0() +NORMAL-DAG: ini1() +NORMAL-DAG: ini2() +NORMAL-DAG: t0() +NORMAL-DAG: t1() +NORMAL-DAG: t2() +NORMAL-DAG: t3() +NORMAL-DAG: t4() + +; MinUnstable +RUN: %run %t-HandleUnstableTest -print_coverage=1 -handle_unstable=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=MIN +MIN-NOT: ini0() +MIN-NOT: ini1() +MIN-NOT: ini2() +MIN: det0() +MIN: det1() +MIN: det2() +MIN: det3() +MIN: det4() + +; ZeroUnstable +RUN: %run %t-HandleUnstableTest -print_coverage=1 -handle_unstable=2 -runs=1 2>&1 | FileCheck %s --check-prefix=ZERO +ZERO-NOT: ini0() +ZERO-NOT: ini1() +ZERO-NOT: ini2() +ZERO: det0() +ZERO: det1() +ZERO: det2() +ZERO: det3() +ZERO: det4() diff --git a/test/fuzzer/initialize.test b/test/fuzzer/initialize.test new file mode 100644 index 000000000000..dc6e8697558e --- /dev/null +++ b/test/fuzzer/initialize.test @@ -0,0 +1,3 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/InitializeTest.cpp -o %t-InitializeTest +RUN: not %run %t-InitializeTest -use_value_profile=1 2>&1 | FileCheck %s diff --git a/test/fuzzer/inline-8bit-counters.test b/test/fuzzer/inline-8bit-counters.test deleted file mode 100644 index 76ae1f537f72..000000000000 --- a/test/fuzzer/inline-8bit-counters.test +++ /dev/null @@ -1,4 +0,0 @@ -RUN: %cpp_compiler %S/SimpleTest.cpp -fno-sanitize-coverage=trace-pc-guard -fsanitize-coverage=inline-8bit-counters -o %t-SimpleTest-Inline8bitCounters -CHECK: INFO: Loaded 1 modules ({{.*}} inline 8-bit counters) -CHECK: BINGO -RUN: not %t-SimpleTest-Inline8bitCounters -runs=1000000 -seed=1 2>&1 | FileCheck %s diff --git a/test/fuzzer/lit.cfg b/test/fuzzer/lit.cfg index 0350a1ad7797..8a44860d4a5d 100644 --- a/test/fuzzer/lit.cfg +++ b/test/fuzzer/lit.cfg @@ -2,7 +2,7 @@ import lit.formats import sys import os -config.name = "LLVMFuzzer" +config.name = "libFuzzer" + config.name_suffix config.test_format = lit.formats.ShTest(True) config.suffixes = ['.test'] config.test_source_root = os.path.dirname(__file__) @@ -25,12 +25,20 @@ else: config.test_format = lit.formats.ShTest(execute_external) # LeakSanitizer is not supported on OSX right now. -if sys.platform.startswith('darwin'): +if sys.platform.startswith('darwin') or sys.platform.startswith('freebsd'): lit_config.note('lsan feature unavailable') else: lit_config.note('lsan feature available') config.available_features.add('lsan') +# MemorySanitizer is not supported on OSX right now +if sys.platform.startswith('darwin'): + lit_config.note('msan feature unavailable') + assert 'msan' not in config.available_features +else: + lit_config.note('msan feature available') + config.available_features.add('msan') + if sys.platform.startswith('win') or sys.platform.startswith('cygwin'): config.available_features.add('windows') @@ -49,18 +57,36 @@ config.substitutions.append(('%build_dir', config.cmake_binary_dir)) libfuzzer_src_root = os.path.join(config.compiler_rt_src_root, "lib", "fuzzer") config.substitutions.append(('%libfuzzer_src', libfuzzer_src_root)) -def generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True): - compiler_cmd = config.c_compiler - link_cmd = '-lc++' if 'darwin' in config.target_triple else '-lstdc++' - std_cmd = '-std=c++11' if is_cpp else '' - sanitizers = ['address'] +def generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True, msan_enabled=False): + compiler_cmd = config.clang + extra_cmd = config.target_flags + if config.clang and config.stdlib == 'libc++': + link_cmd = '-stdlib=libc++ -Wl,-rpath=%s' % config.runtime_library_dir + elif config.clang and config.stdlib == 'static-libc++': + link_cmd = '-stdlib=libc++ -lc++abi -static-libstdc++ -Wl,-rpath=%s' % ( + config.runtime_library_dir) + elif any(x in config.target_triple for x in ('darwin', 'freebsd')): + link_cmd = '-lc++' + else: + link_cmd = '-lstdc++' + + std_cmd = '--driver-mode=g++ -std=c++11' if is_cpp else '' + if msan_enabled: + sanitizers = ['memory'] + else: + sanitizers = ['address'] if fuzzer_enabled: sanitizers.append('fuzzer') sanitizers_cmd = ('-fsanitize=%s' % ','.join(sanitizers)) - isysroot_cmd = config.osx_sysroot_flag if config.osx_sysroot_flag else '' - include_cmd = '-I%s' % libfuzzer_src_root - return '%s %s %s -gline-tables-only %s %s %s' % ( - compiler_cmd, std_cmd, link_cmd, isysroot_cmd, sanitizers_cmd, include_cmd) + return " ".join([ + compiler_cmd, + std_cmd, + link_cmd, + "-O2 -gline-tables-only", + sanitizers_cmd, + "-I%s" % libfuzzer_src_root, + extra_cmd + ]) config.substitutions.append(('%cpp_compiler', generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True) @@ -77,3 +103,13 @@ config.substitutions.append(('%no_fuzzer_cpp_compiler', config.substitutions.append(('%no_fuzzer_c_compiler', generate_compiler_cmd(is_cpp=False, fuzzer_enabled=False) )) + +config.substitutions.append(('%msan_compiler', + generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True, msan_enabled=True) + )) + +if config.host_os == 'Darwin': + if config.target_arch in ["x86_64", "x86_64h"]: + config.parallelism_group = "darwin-64bit-sanitizer" + elif config.apple_platform != "osx" and not config.apple_platform.endswith("sim"): + config.parallelism_group = "darwin-ios-device-sanitizer" diff --git a/test/fuzzer/lit.site.cfg.in b/test/fuzzer/lit.site.cfg.in index 7f70c8f67d69..b333c78e59e9 100644 --- a/test/fuzzer/lit.site.cfg.in +++ b/test/fuzzer/lit.site.cfg.in @@ -1,17 +1,24 @@ @LIT_SITE_CFG_IN_HEADER@ -config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" - config.cpp_compiler = "@LIBFUZZER_TEST_COMPILER@" config.target_flags = "@LIBFUZZER_TEST_FLAGS@" config.c_compiler = "@LIBFUZZER_TEST_COMPILER@" +config.stdlib = "@LIBFUZZER_TEST_STDLIB@" +config.apple_platform = "@LIBFUZZER_TEST_APPLE_PLATFORM@" +config.name_suffix = "@LIBFUZZER_TEST_CONFIG_SUFFIX@" config.osx_sysroot_flag = "@OSX_SYSROOT_FLAG@" config.cmake_binary_dir = "@CMAKE_BINARY_DIR@" +config.llvm_library_dir = "@LLVM_LIBRARY_DIR@" config.target_triple = "@TARGET_TRIPLE@" # Load common config for all compiler-rt lit tests. lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") +if config.enable_per_target_runtime_dir: + config.runtime_library_dir = config.compiler_rt_libdir +else: + config.runtime_library_dir = "@LLVM_LIBRARY_DIR@" + lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") diff --git a/test/fuzzer/max-number-of-runs.test b/test/fuzzer/max-number-of-runs.test index efe7a9c0f629..c1fa93101510 100644 --- a/test/fuzzer/max-number-of-runs.test +++ b/test/fuzzer/max-number-of-runs.test @@ -1,10 +1,10 @@ RUN: %cpp_compiler %S/AccumulateAllocationsTest.cpp -o %t-AccumulateAllocationsTest -RUN: %t-AccumulateAllocationsTest -seed=1 -runs=2 2>&1 | FileCheck %s --check-prefix=CHECK1 +RUN: %run %t-AccumulateAllocationsTest -seed=1 -runs=2 2>&1 | FileCheck %s --check-prefix=CHECK1 CHECK1: Done 2 runs -RUN: %t-AccumulateAllocationsTest -seed=1 -runs=3 2>&1 | FileCheck %s --check-prefix=CHECK2 +RUN: %run %t-AccumulateAllocationsTest -seed=1 -runs=3 2>&1 | FileCheck %s --check-prefix=CHECK2 CHECK2: Done 3 runs -RUN: %t-AccumulateAllocationsTest -seed=1 -runs=4 2>&1 | FileCheck %s --check-prefix=CHECK3 +RUN: %run %t-AccumulateAllocationsTest -seed=1 -runs=4 2>&1 | FileCheck %s --check-prefix=CHECK3 CHECK3: Done 4 runs diff --git a/test/fuzzer/memcmp.test b/test/fuzzer/memcmp.test index 3431a524ced5..5657cab41dfc 100644 --- a/test/fuzzer/memcmp.test +++ b/test/fuzzer/memcmp.test @@ -1,3 +1,4 @@ +UNSUPPORTED: freebsd RUN: %cpp_compiler %S/MemcmpTest.cpp -o %t-MemcmpTest -RUN: not %t-MemcmpTest -seed=1 -runs=10000000 2>&1 | FileCheck %s +RUN: not %run %t-MemcmpTest -seed=1 -runs=10000000 2>&1 | FileCheck %s CHECK: BINGO diff --git a/test/fuzzer/memcmp64.test b/test/fuzzer/memcmp64.test index 223c3bd42a7d..24d14bf73bbf 100644 --- a/test/fuzzer/memcmp64.test +++ b/test/fuzzer/memcmp64.test @@ -1,3 +1,4 @@ +UNSUPPORTED: freebsd RUN: %cpp_compiler %S/Memcmp64BytesTest.cpp -o %t-Memcmp64BytesTest -RUN: not %t-Memcmp64BytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s +RUN: not %run %t-Memcmp64BytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s CHECK: BINGO diff --git a/test/fuzzer/merge-control-file.test b/test/fuzzer/merge-control-file.test index 2da5c4ccfb2b..64b747116a9f 100644 --- a/test/fuzzer/merge-control-file.test +++ b/test/fuzzer/merge-control-file.test @@ -1,3 +1,4 @@ +XFAIL: ios RUN: mkdir -p %t RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t/T @@ -10,9 +11,9 @@ RUN: echo ..Z... > %t/T0/3 # Test what happens if the control file is junk. RUN: echo JUNK > %t/MCF -RUN: not %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=JUNK +RUN: not %run %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=JUNK RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF -RUN: not %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=JUNK +RUN: not %run %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=JUNK JUNK: MERGE-OUTER: non-empty control file provided: {{.*}}MCF JUNK: MERGE-OUTER: bad control file, will overwrite it @@ -21,18 +22,18 @@ JUNK: MERGE-OUTER: bad control file, will overwrite it RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1 RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF; echo %t/T1/2 >> %t/MCF; echo %t/T1/3 >> %t/MCF -RUN: %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_0 +RUN: %run %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_0 OK_0: MERGE-OUTER: control file ok, 3 files total, first not processed file 0 OK_0: MERGE-OUTER: 3 new files with {{.*}} new features added RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1 RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF; echo %t/T1/2 >> %t/MCF; echo %t/T1/3 >> %t/MCF -RUN: %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF -save_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=SAVE_SUMMARY +RUN: %run %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF -save_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=SAVE_SUMMARY SAVE_SUMMARY: MERGE-OUTER: writing coverage summary for 3 files to {{.*}}/SUMMARY RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1 RUN: echo 3 > %t/MCF; echo 0 >> %t/MCF; echo %t/T1/1 >> %t/MCF; echo %t/T1/2 >> %t/MCF; echo %t/T1/3 >> %t/MCF -RUN: %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF -load_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=LOAD_SUMMARY +RUN: %run %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF -load_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=LOAD_SUMMARY LOAD_SUMMARY: MERGE-OUTER: coverage summary loaded from RUN: rm -f %t/T1/*; cp %t/T0/* %t/T1 @@ -41,7 +42,7 @@ RUN: echo STARTED 0 1 >> %t/MCF RUN: echo DONE 0 11 >> %t/MCF RUN: echo STARTED 1 2 >> %t/MCF RUN: echo DONE 1 12 >> %t/MCF -RUN: %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_2 +RUN: %run %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_2 OK_2: MERGE-OUTER: control file ok, 3 files total, first not processed file 2 OK_2: MERGE-OUTER: 3 new files with {{.*}} new features added @@ -53,5 +54,5 @@ RUN: echo STARTED 1 2 >> %t/MCF RUN: echo DONE 1 12 >> %t/MCF RUN: echo STARTED 2 2 >> %t/MCF RUN: echo DONE 2 13 >> %t/MCF -RUN: %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_3 +RUN: %run %t/T -merge=1 %t/T1 %t/T2 -merge_control_file=%t/MCF 2>&1 | FileCheck %s --check-prefix=OK_3 OK_3: MERGE-OUTER: nothing to do, merge has been completed before diff --git a/test/fuzzer/merge-posix.test b/test/fuzzer/merge-posix.test index e34e3a325b74..db0a48b5481e 100644 --- a/test/fuzzer/merge-posix.test +++ b/test/fuzzer/merge-posix.test @@ -1,3 +1,4 @@ +XFAIL: ios RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest RUN: rm -rf %tmp/T1 %tmp/T2 @@ -15,9 +16,9 @@ RUN: echo ....E. > %tmp/T2/5 RUN: echo .....R > %tmp/T2/6 # Check that we can report an error if file size exceeded -RUN: (ulimit -f 1; not %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=SIGXFSZ) +RUN: (ulimit -f 1; not %run %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=SIGXFSZ) SIGXFSZ: ERROR: libFuzzer: file size exceeded # Check that we honor TMPDIR -RUN: TMPDIR=DIR_DOES_NOT_EXIST not %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=TMPDIR +RUN: TMPDIR=DIR_DOES_NOT_EXIST not %run %t-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=TMPDIR TMPDIR: MERGE-OUTER: failed to write to the control file: DIR_DOES_NOT_EXIST/libFuzzerTemp diff --git a/test/fuzzer/merge-sigusr.test b/test/fuzzer/merge-sigusr.test index efb00daa4643..a03e5440a8b8 100644 --- a/test/fuzzer/merge-sigusr.test +++ b/test/fuzzer/merge-sigusr.test @@ -1,4 +1,5 @@ # Check that libFuzzer honors SIGUSR1/SIGUSR2 +UNSUPPORTED: darwin RUN: rm -rf %t RUN: mkdir -p %t RUN: %cpp_compiler %S/SleepOneSecondTest.cpp -o %t/LFSIGUSR @@ -12,7 +13,7 @@ RUN: echo e > %t/C2/e RUN: echo f > %t/C2/f RUN: echo g > %t/C2/g -RUN: %t/LFSIGUSR -merge=1 -merge_control_file=%t/MCF %t/C1 %t/C2 2> %t/log & export PID=$! +RUN: %run %t/LFSIGUSR -merge=1 -merge_control_file=%t/MCF %t/C1 %t/C2 2> %t/log & export PID=$! RUN: sleep 3 RUN: pkill -SIGUSR2 -f %t/LFSIGUSR RUN: sleep 3 diff --git a/test/fuzzer/merge-summary.test b/test/fuzzer/merge-summary.test index 3e21c23ef38d..116cf1db8755 100644 --- a/test/fuzzer/merge-summary.test +++ b/test/fuzzer/merge-summary.test @@ -9,9 +9,9 @@ RUN: echo F..... > %t/T2/a RUN: echo .U.... > %t/T2/b RUN: echo ..Z... > %t/T2/c -RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -save_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=SAVE_SUMMARY +RUN: %run %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -save_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=SAVE_SUMMARY SAVE_SUMMARY: MERGE-OUTER: writing coverage summary for 6 files to {{.*}}SUMMARY RUN: rm %t/T1/* -RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -load_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=LOAD_SUMMARY +RUN: %run %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -load_coverage_summary=%t/SUMMARY 2>&1 | FileCheck %s --check-prefix=LOAD_SUMMARY LOAD_SUMMARY: MERGE-OUTER: coverage summary loaded from {{.*}}SUMMAR LOAD_SUMMARY: MERGE-OUTER: 0 new files with 0 new features added diff --git a/test/fuzzer/merge.test b/test/fuzzer/merge.test index d17405595eb7..ec41c82b9344 100644 --- a/test/fuzzer/merge.test +++ b/test/fuzzer/merge.test @@ -1,3 +1,4 @@ +XFAIL: ios CHECK: BINGO RUN: %cpp_compiler %S/FullCoverageSetTest.cpp -o %t-FullCoverageSetTest @@ -10,7 +11,7 @@ RUN: echo ..Z... > %t/T0/3 # T1 has 3 elements, T2 is empty. RUN: cp %t/T0/* %t/T1/ -RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=CHECK1 +RUN: %run %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=CHECK1 CHECK1: MERGE-OUTER: 3 files, 3 in the initial corpus CHECK1: MERGE-OUTER: 0 new files with 0 new features added @@ -22,12 +23,12 @@ RUN: echo .U.... > %t/T2/b RUN: echo ..Z... > %t/T2/c # T1 has 3 elements, T2 has 6 elements, only 3 are new. -RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=CHECK2 +RUN: %run %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=CHECK2 CHECK2: MERGE-OUTER: 9 files, 3 in the initial corpus CHECK2: MERGE-OUTER: 3 new files with 3 new features added # Now, T1 has 6 units and T2 has no new interesting units. -RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=CHECK3 +RUN: %run %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=CHECK3 CHECK3: MERGE-OUTER: 12 files, 6 in the initial corpus CHECK3: MERGE-OUTER: 0 new files with 0 new features added @@ -35,14 +36,14 @@ CHECK3: MERGE-OUTER: 0 new files with 0 new features added RUN: rm %t/T1/* RUN: cp %t/T0/* %t/T1/ RUN: echo looooooooong > %t/T2/looooooooong -RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -max_len=6 2>&1 | FileCheck %s --check-prefix=MAX_LEN +RUN: %run %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -max_len=6 2>&1 | FileCheck %s --check-prefix=MAX_LEN MAX_LEN: MERGE-OUTER: 3 new files # Check that we respect -merge_control_file=FILE RUN: rm %t/T1/* RUN: cp %t/T0/* %t/T1/ RUN: rm -f %t/MCF -RUN: %t-FullCoverageSetTest -merge=1 -merge_control_file=%t/MCF %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=MCF +RUN: %run %t-FullCoverageSetTest -merge=1 -merge_control_file=%t/MCF %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=MCF RUN: grep STARTED %t/MCF RUN: grep DONE %t/MCF MCF: MERGE-INNER: using the control file {{.*}}MCF @@ -53,18 +54,18 @@ MCF: MERGE-OUTER: 3 new files RUN: rm %t/T1/* RUN: cp %t/T0/* %t/T1/ RUN: echo 'FUZZER' > %t/T2/FUZZER -RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=MERGE_WITH_CRASH +RUN: %run %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=MERGE_WITH_CRASH MERGE_WITH_CRASH: MERGE-OUTER: succesfull in 2 attempt(s) MERGE_WITH_CRASH: MERGE-OUTER: 3 new files # Check that we actually limit the size with max_len RUN: rm %t/T1/* %t/T2/* RUN: echo 'FUZZER' > %t/T2/FUZZER -RUN: %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -max_len=5 2>&1 | FileCheck %s --check-prefix=MERGE_LEN5 +RUN: %run %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 -max_len=5 2>&1 | FileCheck %s --check-prefix=MERGE_LEN5 RUN: not grep FUZZER %t/T1/* RUN: grep FUZZE %t/T1/* MERGE_LEN5: MERGE-OUTER: succesfull in 1 attempt(s) RUN: rm -rf %t/T1/* %t/T2/* -RUN: not %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=EMPTY +RUN: not %run %t-FullCoverageSetTest -merge=1 %t/T1 %t/T2 2>&1 | FileCheck %s --check-prefix=EMPTY EMPTY: MERGE-OUTER: zero succesfull attempts, exiting diff --git a/test/fuzzer/minimize_crash.test b/test/fuzzer/minimize_crash.test index 77ab370fa899..de44b8747e04 100644 --- a/test/fuzzer/minimize_crash.test +++ b/test/fuzzer/minimize_crash.test @@ -1,16 +1,17 @@ RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest RUN: %cpp_compiler %S/SingleByteInputTest.cpp -o %t-SingleByteInputTest +RUN: mkdir -p %t.dir -RUN: echo 'Hi!rv349f34t3gg' > not_minimal_crash -RUN: %t-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 2>&1 | FileCheck %s -CHECK: CRASH_MIN: failed to minimize beyond ./minimized-from-{{.*}} (3 bytes), exiting -RUN: %t-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 -exact_artifact_path=exact_minimized_path 2>&1 | FileCheck %s --check-prefix=CHECK_EXACT -CHECK_EXACT: CRASH_MIN: failed to minimize beyond exact_minimized_path (3 bytes), exiting -RUN: rm not_minimal_crash minimized-from-* exact_minimized_path +RUN: echo 'Hi!rv349f34t3gg' > %t.dir/not_minimal_crash +RUN: %run %t-NullDerefTest -minimize_crash=1 %t.dir/not_minimal_crash -max_total_time=2 2>&1 | FileCheck %s +CHECK: CRASH_MIN: failed to minimize beyond {{.*}}minimized-from{{.*}} (3 bytes), exiting +RUN: %run %t-NullDerefTest -minimize_crash=1 %t.dir/not_minimal_crash -max_total_time=2 -exact_artifact_path=%t.exact_minimized_path 2>&1 | FileCheck %s --check-prefix=CHECK_EXACT +CHECK_EXACT: CRASH_MIN: failed to minimize beyond {{.*}}exact_minimized_path{{.*}} (3 bytes), exiting +RUN: rm %t.dir/not_minimal_crash %t.exact_minimized_path -RUN: echo -n 'abcd*xyz' > not_minimal_crash -RUN: %t-SingleByteInputTest -minimize_crash=1 not_minimal_crash -exact_artifact_path=exact_minimized_path 2>&1 | FileCheck %s --check-prefix=MIN1 -MIN1: Test unit written to exact_minimized_path -MIN1: Test unit written to exact_minimized_path +RUN: echo -n 'abcd*xyz' > %t.dir/not_minimal_crash +RUN: %run %t-SingleByteInputTest -minimize_crash=1 %t.dir/not_minimal_crash -exact_artifact_path=%t.exact_minimized_path 2>&1 | FileCheck %s --check-prefix=MIN1 +MIN1: Test unit written to {{.*}}exact_minimized_path +MIN1: Test unit written to {{.*}}exact_minimized_path MIN1: INFO: The input is small enough, exiting -MIN1: CRASH_MIN: failed to minimize beyond exact_minimized_path (1 bytes), exiting +MIN1: CRASH_MIN: failed to minimize beyond {{.*}}exact_minimized_path (1 bytes), exiting diff --git a/test/fuzzer/minimize_two_crashes.test b/test/fuzzer/minimize_two_crashes.test index e6ff9990ffd8..3c528f707666 100644 --- a/test/fuzzer/minimize_two_crashes.test +++ b/test/fuzzer/minimize_two_crashes.test @@ -1,10 +1,12 @@ # Test that the minimizer stops when it sees a differe bug. +UNSUPPORTED: freebsd -RUN: %cpp_compiler %S/TwoDifferentBugsTest.cpp -o %t-TwoDifferentBugsTest +# TODO: Find out why test fails on Darwin with -O2. +RUN: %cpp_compiler -O0 %S/TwoDifferentBugsTest.cpp -o %t-TwoDifferentBugsTest RUN: rm -rf %t && mkdir %t RUN: echo H12345678901234667888090 > %t/long_crash -RUN: env ASAN_OPTIONS=dedup_token_length=3 %t-TwoDifferentBugsTest -seed=1 -minimize_crash=1 %t/long_crash -exact_artifact_path=%t/result 2>&1 | FileCheck %s +RUN: env ASAN_OPTIONS=dedup_token_length=3 %run %t-TwoDifferentBugsTest -seed=1 -minimize_crash=1 %t/long_crash -exact_artifact_path=%t/result 2>&1 | FileCheck %s CHECK: DedupToken1: DEDUP_TOKEN: Bar CHECK: DedupToken2: DEDUP_TOKEN: Bar @@ -12,7 +14,7 @@ CHECK: DedupToken1: DEDUP_TOKEN: Bar CHECK: DedupToken2: DEDUP_TOKEN: Foo CHECK: CRASH_MIN: mismatch in dedup tokens -RUN: not %t-TwoDifferentBugsTest %t/result 2>&1 | FileCheck %s --check-prefix=VERIFY +RUN: not %run %t-TwoDifferentBugsTest %t/result 2>&1 | FileCheck %s --check-prefix=VERIFY VERIFY: ERROR: AddressSanitizer: VERIFY: in Bar diff --git a/test/fuzzer/msan.test b/test/fuzzer/msan.test new file mode 100644 index 000000000000..2e0339bb8ff7 --- /dev/null +++ b/test/fuzzer/msan.test @@ -0,0 +1,24 @@ +REQUIRES: msan +RUN: %msan_compiler %S/SimpleTestStdio.cpp -o %t +RUN: not %run %t -seed=1 -runs=10000000 2>&1 | FileCheck %s --check-prefix=NO-REPORT + +RUN: %msan_compiler %S/SimpleCmpTest.cpp -o %t +RUN: not %run %t -seed=1 -runs=10000000 2>&1 | FileCheck %s --check-prefix=NO-REPORT + +RUN: %msan_compiler %S/MemcmpTest.cpp -o %t +RUN: not %run %t -seed=1 -runs=10000000 2>&1 | FileCheck %s --check-prefix=NO-REPORT + +RUN: %msan_compiler %S/StrcmpTest.cpp -o %t +RUN: not %run %t -seed=1 -runs=10000000 2>&1 | FileCheck %s --check-prefix=NO-REPORT + +NO-REPORT-NOT: MemorySanitizer +NO-REPORT: BINGO + + +RUN: %msan_compiler %S/UseAfterDtor.cpp -o %t +RUN: MSAN_OPTIONS=poison_in_dtor=1 not %run %t -seed=1 -runs=10000000 2>&1 | FileCheck %s --check-prefix=REPORT + +RUN: %msan_compiler %S/UninitializedStrlen.cpp -o %t +RUN: not %run %t -seed=1 -runs=10000000 2>&1 | FileCheck %s --check-prefix=REPORT + +REPORT: MemorySanitizer: use-of-uninitialized-value diff --git a/test/fuzzer/not-instrumented.test b/test/fuzzer/not-instrumented.test new file mode 100644 index 000000000000..2330c4770067 --- /dev/null +++ b/test/fuzzer/not-instrumented.test @@ -0,0 +1,4 @@ +RUN: %cpp_compiler %S/NotinstrumentedTest.cpp -fsanitize-coverage=0 -o %t-NotinstrumentedTest-NoCoverage +RUN: not %run %t-NotinstrumentedTest-NoCoverage 2>&1 | FileCheck %s --check-prefix=NO_COVERAGE + +NO_COVERAGE: ERROR: no interesting inputs were found. Is the code instrumented for coverage? Exiting diff --git a/test/fuzzer/null-deref-on-empty.test b/test/fuzzer/null-deref-on-empty.test new file mode 100644 index 000000000000..f159a79f4838 --- /dev/null +++ b/test/fuzzer/null-deref-on-empty.test @@ -0,0 +1,4 @@ +RUN: %cpp_compiler %S/NullDerefOnEmptyTest.cpp -o %t-NullDerefOnEmptyTest + +RUN: not %run %t-NullDerefOnEmptyTest -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=NULL_DEREF_ON_EMPTY +NULL_DEREF_ON_EMPTY: stat::number_of_executed_units: diff --git a/test/fuzzer/null-deref.test b/test/fuzzer/null-deref.test new file mode 100644 index 000000000000..31eb5990da33 --- /dev/null +++ b/test/fuzzer/null-deref.test @@ -0,0 +1,10 @@ +RUN: %cpp_compiler %S/NullDerefTest.cpp -o %t-NullDerefTest + +RUN: not %run %t-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest +RUN: not %run %t-NullDerefTest -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=NullDerefTest +NullDerefTest: ERROR: AddressSanitizer: {{SEGV|access-violation}} on unknown address +NullDerefTest: Test unit written to ./crash- +RUN: not %run %t-NullDerefTest -artifact_prefix=ZZZ 2>&1 | FileCheck %s --check-prefix=NullDerefTestPrefix +NullDerefTestPrefix: Test unit written to ZZZcrash- +RUN: not %run %t-NullDerefTest -artifact_prefix=ZZZ -exact_artifact_path=FOOBAR 2>&1 | FileCheck %s --check-prefix=NullDerefTestExactPath +NullDerefTestExactPath: Test unit written to FOOBAR diff --git a/test/fuzzer/only-some-bytes.test b/test/fuzzer/only-some-bytes.test new file mode 100644 index 000000000000..fbfef14c7850 --- /dev/null +++ b/test/fuzzer/only-some-bytes.test @@ -0,0 +1,38 @@ +# Tests the data flow tracer. +REQUIRES: linux +UNSUPPORTED: aarch64 + +# Build the tracer and the test. +RUN: %no_fuzzer_cpp_compiler -c -fno-sanitize=all -fsanitize=dataflow %S/../../lib/fuzzer/dataflow/DataFlow.cpp -o %t-DataFlow.o +RUN: %no_fuzzer_cpp_compiler -fno-sanitize=all -fsanitize=dataflow -fsanitize-coverage=trace-pc-guard,pc-table,func,trace-cmp %S/OnlySomeBytesTest.cpp %t-DataFlow.o -o %t-DFT +RUN: %cpp_compiler %S/OnlySomeBytesTest.cpp -o %t-Fuzz + +# Prepare the inputs. +RUN: rm -rf %t/* +RUN: mkdir -p %t/IN +RUN: echo -n 0123456789012345678901234567890123456789012345678901234567891234 > %t/IN/6 +RUN: cat %t/IN/6 %t/IN/6 %t/IN/6 %t/IN/6 > %t/IN/8 +RUN: cat %t/IN/8 %t/IN/8 %t/IN/8 %t/IN/8 > %t/IN/10 +RUN: cat %t/IN/10 %t/IN/10 %t/IN/10 %t/IN/10 > %t/IN/12 +# %t/IN/12 is 4096 bytes-long. + +RUN: %t-Fuzz -focus_function=f0 -runs=0 %t/IN 2>&1 | FileCheck %s --check-prefix=NO_FOCUSED_INPUT +NO_FOCUSED_INPUT: INFO: 0/2 inputs touch the focus function + +RUN: (echo -n ABC; cat %t/IN/12) > %t/IN/ABC +RUN: %t-Fuzz -focus_function=f0 -runs=0 %t/IN 2>&1 | FileCheck %s --check-prefix=ONE_FOCUSED_INPUT +ONE_FOCUSED_INPUT: INFO: 1/3 inputs touch the focus function + +RUN: rm -rf %t/IN_DFT +RUN: %libfuzzer_src/scripts/collect_data_flow.py %t-DFT %t/IN %t/IN_DFT > /dev/null 2>&1 + +# Repeat twice to make sure that the inputs with DFT are not removed from the corpus. +RUN: %t-Fuzz -focus_function=f0 -data_flow_trace=%t/IN_DFT -runs=100 %t/IN 2>&1 | FileCheck %s --check-prefix=HAVE_DFT +RUN: %t-Fuzz -focus_function=f0 -data_flow_trace=%t/IN_DFT -runs=100 %t/IN 2>&1 | FileCheck %s --check-prefix=HAVE_DFT +HAVE_DFT: INFO: 1/{{.*}} inputs have the Data Flow Trace + +# Collect DFT, then use it. +RUN: rm -rf %t/C && mkdir %t/C && cp %t/IN/* %t/C +RUN: rm -rf %t/C_DFT && %libfuzzer_src/scripts/collect_data_flow.py %t-DFT %t/C %t/C_DFT > /dev/null 2>&1 +RUN: not %t-Fuzz -focus_function=f0 -data_flow_trace=%t/C_DFT -seed=1 -runs=1000000 -use_value_profile=3 %t/C 2> %t/log +RUN: grep BINGO %t/log diff --git a/test/fuzzer/overwrite-input.test b/test/fuzzer/overwrite-input.test index 3695622d0352..e5ddd62cbdc7 100644 --- a/test/fuzzer/overwrite-input.test +++ b/test/fuzzer/overwrite-input.test @@ -1,3 +1,3 @@ RUN: %cpp_compiler %S/OverwriteInputTest.cpp -o %t-OverwriteInputTest -RUN: not %t-OverwriteInputTest 2>&1 | FileCheck %s +RUN: not %run %t-OverwriteInputTest 2>&1 | FileCheck %s CHECK: ERROR: libFuzzer: fuzz target overwrites it's const input diff --git a/test/fuzzer/print-func.test b/test/fuzzer/print-func.test index 930e9992a2f9..c74da218282e 100644 --- a/test/fuzzer/print-func.test +++ b/test/fuzzer/print-func.test @@ -1,6 +1,7 @@ +UNSUPPORTED: darwin, aarch64 RUN: %cpp_compiler %S/PrintFuncTest.cpp -o %t -RUN: %t -seed=1 -runs=100000 2>&1 | FileCheck %s -RUN: %t -seed=1 -runs=100000 -print_funcs=0 2>&1 | FileCheck %s --check-prefix=NO +RUN: %run %t -seed=1 -runs=100000 2>&1 | FileCheck %s +RUN: %run %t -seed=1 -runs=100000 -print_funcs=0 2>&1 | FileCheck %s --check-prefix=NO CHECK: NEW_FUNC{{.*}} FunctionA CHECK: NEW_FUNC{{.*}} FunctionB CHECK: NEW_FUNC{{.*}} FunctionC diff --git a/test/fuzzer/print_unstable_stats.test b/test/fuzzer/print_unstable_stats.test new file mode 100644 index 000000000000..bba99aecc838 --- /dev/null +++ b/test/fuzzer/print_unstable_stats.test @@ -0,0 +1,3 @@ +RUN: %cpp_compiler %S/PrintUnstableStatsTest.cpp -o %t-PrintUnstableStatsTest +RUN: %run %t-PrintUnstableStatsTest -print_unstable_stats=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=LONG +LONG: stat::stability_rate: 27.59 diff --git a/test/fuzzer/recommended-dictionary.test b/test/fuzzer/recommended-dictionary.test index 41b62c924ceb..e1d58c96fa20 100644 --- a/test/fuzzer/recommended-dictionary.test +++ b/test/fuzzer/recommended-dictionary.test @@ -1,5 +1,6 @@ +UNSUPPORTED: freebsd RUN: %cpp_compiler %S/RepeatedMemcmp.cpp -o %t-RepeatedMemcmp -RUN: %t-RepeatedMemcmp -seed=11 -runs=100000 -max_len=20 2>&1 | FileCheck %s --check-prefix=RECOMMENDED_DICT +RUN: %run %t-RepeatedMemcmp -seed=11 -runs=100000 -max_len=20 2>&1 | FileCheck %s --check-prefix=RECOMMENDED_DICT RECOMMENDED_DICT:###### Recommended dictionary. ###### RECOMMENDED_DICT-DAG: "foo" RECOMMENDED_DICT-DAG: "bar" diff --git a/test/fuzzer/reduce_inputs.test b/test/fuzzer/reduce_inputs.test index 94f8cc4f37a8..e65f57227729 100644 --- a/test/fuzzer/reduce_inputs.test +++ b/test/fuzzer/reduce_inputs.test @@ -4,13 +4,13 @@ RUN: rm -rf %t/C RUN: mkdir -p %t/C RUN: %cpp_compiler %S/ShrinkControlFlowSimpleTest.cpp -o %t-ShrinkControlFlowSimpleTest RUN: %cpp_compiler %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest -RUN: %t-ShrinkControlFlowSimpleTest -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 %t/C 2>&1 | FileCheck %s +RUN: %run %t-ShrinkControlFlowSimpleTest -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 %t/C 2>&1 | FileCheck %s CHECK: INFO: found item with checksum '0eb8e4ed029b774d80f2b66408203801cb982a60' # Test that reduce_inputs deletes redundant files in the corpus. -RUN: %t-ShrinkControlFlowSimpleTest -runs=0 %t/C 2>&1 | FileCheck %s --check-prefix=COUNT +RUN: %run %t-ShrinkControlFlowSimpleTest -runs=0 %t/C 2>&1 | FileCheck %s --check-prefix=COUNT COUNT: seed corpus: files: 4 # a bit longer test -RUN: %t-ShrinkControlFlowTest -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -seed=1 -runs=1000000 2>&1 | FileCheck %s +RUN: %run %t-ShrinkControlFlowTest -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -seed=42 -runs=1000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/repeated-bytes.test b/test/fuzzer/repeated-bytes.test index 0bba2a91688f..e749a3e239a4 100644 --- a/test/fuzzer/repeated-bytes.test +++ b/test/fuzzer/repeated-bytes.test @@ -1,3 +1,3 @@ RUN: %cpp_compiler %S/RepeatedBytesTest.cpp -o %t-RepeatedBytesTest CHECK: BINGO -RUN: not %t-RepeatedBytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s +RUN: not %run %t-RepeatedBytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/shrink.test b/test/fuzzer/shrink.test index 2988d4bbb043..5abbcc90b8c0 100644 --- a/test/fuzzer/shrink.test +++ b/test/fuzzer/shrink.test @@ -1,9 +1,9 @@ RUN: %cpp_compiler %S/ShrinkControlFlowTest.cpp -o %t-ShrinkControlFlowTest RUN: %cpp_compiler %S/ShrinkValueProfileTest.cpp -o %t-ShrinkValueProfileTest -RUN: %t-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=1 -reduce_inputs=0 2>&1 | FileCheck %s --check-prefix=SHRINK1 +RUN: %run %t-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=1 -reduce_inputs=0 2>&1 | FileCheck %s --check-prefix=SHRINK1 # Limit max_len to run this negative test faster. -RUN: %t-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=0 -reduce_inputs=0 -max_len=64 2>&1 | FileCheck %s --check-prefix=SHRINK0 -RUN: %t-ShrinkValueProfileTest -seed=1 -exit_on_item=aea2e3923af219a8956f626558ef32f30a914ebc -runs=100000 -shrink=1 -reduce_inputs=0 -use_value_profile=1 2>&1 | FileCheck %s --check-prefix=SHRINK1_VP +RUN: %run %t-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=0 -reduce_inputs=0 -max_len=64 2>&1 | FileCheck %s --check-prefix=SHRINK0 +RUN: %run %t-ShrinkValueProfileTest -seed=1 -exit_on_item=aea2e3923af219a8956f626558ef32f30a914ebc -runs=100000 -shrink=1 -reduce_inputs=0 -use_value_profile=1 2>&1 | FileCheck %s --check-prefix=SHRINK1_VP SHRINK0: Done 1000000 runs in SHRINK1: INFO: found item with checksum '0eb8e4ed029b774d80f2b66408203801cb982a60', exiting. diff --git a/test/fuzzer/sigusr.test b/test/fuzzer/sigusr.test index 12e3ac996c6c..0b3ddc72832d 100644 --- a/test/fuzzer/sigusr.test +++ b/test/fuzzer/sigusr.test @@ -1,9 +1,10 @@ +UNSUPPORTED: darwin # Check that libFuzzer honors SIGUSR1/SIGUSR2 RUN: rm -rf %t RUN: mkdir -p %t RUN: %cpp_compiler %S/SleepOneSecondTest.cpp -o %t/LFSIGUSR -RUN: %t/LFSIGUSR 2> %t/log & export PID=$! +RUN: %run %t/LFSIGUSR 2> %t/log & export PID=$! RUN: sleep 2 RUN: kill -SIGUSR1 $PID RUN: sleep 3 diff --git a/test/fuzzer/simple-cmp.test b/test/fuzzer/simple-cmp.test index 08123ed3ac47..e146379b2a5b 100644 --- a/test/fuzzer/simple-cmp.test +++ b/test/fuzzer/simple-cmp.test @@ -1,3 +1,7 @@ RUN: %cpp_compiler %S/SimpleCmpTest.cpp -o %t-SimpleCmpTest + +RUN: not %run %t-SimpleCmpTest -seed=1 -runs=100000000 2>&1 | FileCheck %s +RUN: %run %t-SimpleCmpTest -max_total_time=1 -use_cmp=0 2>&1 | FileCheck %s --check-prefix=MaxTotalTime +MaxTotalTime: Done {{.*}} runs in {{.}} second(s) + CHECK: BINGO -RUN: not %t-SimpleCmpTest -seed=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/simple.test b/test/fuzzer/simple.test new file mode 100644 index 000000000000..97a09be7cec9 --- /dev/null +++ b/test/fuzzer/simple.test @@ -0,0 +1,7 @@ +CHECK: BINGO +RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest + +RUN: not %run %t-SimpleTest 2>&1 | FileCheck %s + +# only_ascii mode. Will perform some minimal self-validation. +RUN: not %run %t-SimpleTest -only_ascii=1 2>&1 diff --git a/test/fuzzer/standalone.test b/test/fuzzer/standalone.test index e6483703f966..cd2422e4e683 100644 --- a/test/fuzzer/standalone.test +++ b/test/fuzzer/standalone.test @@ -2,7 +2,7 @@ RUN: %no_fuzzer_c_compiler %libfuzzer_src/standalone/StandaloneFuzzTargetMain.c RUN: %no_fuzzer_cpp_compiler %S/InitializeTest.cpp -c -o %t_2.o RUN: %no_fuzzer_cpp_compiler %t_1.o %t_2.o -o %t-StandaloneInitializeTest -RUN: %t-StandaloneInitializeTest %S/hi.txt %S/dict1.txt 2>&1 | FileCheck %s +RUN: %run %t-StandaloneInitializeTest %S/hi.txt %S/dict1.txt 2>&1 | FileCheck %s CHECK: StandaloneFuzzTargetMain: running 2 inputs CHECK: Done: {{.*}}hi.txt: (3 bytes) CHECK: Done: {{.*}}dict1.txt: (61 bytes) diff --git a/test/fuzzer/strcmp.test b/test/fuzzer/strcmp.test index 47ad8f9ba0f5..bd917bba6b69 100644 --- a/test/fuzzer/strcmp.test +++ b/test/fuzzer/strcmp.test @@ -1,4 +1,5 @@ +UNSUPPORTED: freebsd RUN: %cpp_compiler %S/StrcmpTest.cpp -o %t-StrcmpTest -RUN: not %t-StrcmpTest -seed=1 -runs=2000000 2>&1 | FileCheck %s +RUN: not %run %t-StrcmpTest -seed=1 -runs=2000000 2>&1 | FileCheck %s CHECK: BINGO diff --git a/test/fuzzer/strncmp-oob.test b/test/fuzzer/strncmp-oob.test new file mode 100644 index 000000000000..a0365d961833 --- /dev/null +++ b/test/fuzzer/strncmp-oob.test @@ -0,0 +1,6 @@ +RUN: %cpp_compiler %S/StrncmpOOBTest.cpp -o %t-StrncmpOOBTest + +RUN: env ASAN_OPTIONS=strict_string_checks=1 not %run %t-StrncmpOOBTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=STRNCMP +STRNCMP: AddressSanitizer: heap-buffer-overflow +STRNCMP-NOT: __sanitizer_weak_hook_strncmp +STRNCMP: in LLVMFuzzerTestOneInput diff --git a/test/fuzzer/strncmp.test b/test/fuzzer/strncmp.test index 49693c8de8f0..50189445b102 100644 --- a/test/fuzzer/strncmp.test +++ b/test/fuzzer/strncmp.test @@ -1,4 +1,5 @@ +UNSUPPORTED: freebsd RUN: %cpp_compiler %S/StrncmpTest.cpp -o %t-StrncmpTest -RUN: not %t-StrncmpTest -seed=2 -runs=10000000 2>&1 | FileCheck %s +RUN: not %run %t-StrncmpTest -seed=2 -runs=10000000 2>&1 | FileCheck %s CHECK: BINGO diff --git a/test/fuzzer/strstr.test b/test/fuzzer/strstr.test index c39d5801acdb..f1fb210b47c7 100644 --- a/test/fuzzer/strstr.test +++ b/test/fuzzer/strstr.test @@ -1,4 +1,5 @@ +UNSUPPORTED: freebsd RUN: %cpp_compiler %S/StrstrTest.cpp -o %t-StrstrTest -RUN: not %t-StrstrTest -seed=1 -runs=2000000 2>&1 | FileCheck %s +RUN: not %run %t-StrstrTest -seed=1 -runs=2000000 2>&1 | FileCheck %s CHECK: BINGO diff --git a/test/fuzzer/swap-cmp.test b/test/fuzzer/swap-cmp.test index 5c2379cde4f6..7f7e2f60fa63 100644 --- a/test/fuzzer/swap-cmp.test +++ b/test/fuzzer/swap-cmp.test @@ -1,3 +1,3 @@ RUN: %cpp_compiler %S/SwapCmpTest.cpp -o %t-SwapCmpTest CHECK: BINGO -RUN: not %t-SwapCmpTest -seed=1 -runs=10000000 2>&1 | FileCheck %s +RUN: not %run %t-SwapCmpTest -seed=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/symbolize-deadlock.test b/test/fuzzer/symbolize-deadlock.test new file mode 100644 index 000000000000..25b519fd3fed --- /dev/null +++ b/test/fuzzer/symbolize-deadlock.test @@ -0,0 +1,2 @@ +RUN: %cpp_compiler %S/SymbolizeDeadlock.cpp -o %t +RUN: not %run %t -rss_limit_mb=20 2>&1 diff --git a/test/fuzzer/target-function.test b/test/fuzzer/target-function.test new file mode 100644 index 000000000000..afd29ab8a83f --- /dev/null +++ b/test/fuzzer/target-function.test @@ -0,0 +1,30 @@ +# Tests -focus_function +# +# TODO: don't require linux. +# REQUIRES: linux +UNSUPPORTED: aarch64 + +RUN: %cpp_compiler %S/OnlySomeBytesTest.cpp -o %t-exe + +RUN: %t-exe -runs=100 2>&1 | FileCheck %s --check-prefix=FOCUS_NONE +FOCUS_NONE-NOT: INFO: Focus function is set to +FOCUS_NONE-NOT: INFO: {{.*}} inputs touch the focus function + +RUN: %t-exe -runs=100 -focus_function=WRONG 2>&1 | FileCheck %s --check-prefix=FOCUS_WRONG +FOCUS_WRONG-NOT: INFO: Focus function is set to +FOCUS_WRONG: INFO: 0/1 inputs touch the focus function + +RUN: %t-exe -runs=100 -focus_function=f0 2>&1 | FileCheck %s --check-prefix=FOCUS_F0 +FOCUS_F0: INFO: Focus function is set to 'f0' +FOCUS_F0: INFO: 0/1 inputs touch the focus function + +RUN: rm -rf %t-corpus +RUN: mkdir %t-corpus +# ABC triggers the focus function, others don't. +RUN: echo ABC$(for((i=0;i<2048;i++)); do echo -n x; done) > %t-corpus/ABC +RUN: echo AXY$(for((i=0;i<2048;i++)); do echo -n x; done) > %t-corpus/AXY +RUN: echo ABX$(for((i=0;i<2048;i++)); do echo -n x; done) > %t-corpus/ABX + +RUN: %t-exe -runs=10000 -focus_function=f0 %t-corpus 2>&1 | FileCheck %s --check-prefix=CORPUS_1_3 +CORPUS_1_3: INFO: 1/3 inputs touch the focus function +CORPUS_1_3: DONE {{.*}} focus: diff --git a/test/fuzzer/three-bytes.test b/test/fuzzer/three-bytes.test new file mode 100644 index 000000000000..0b2187552cf5 --- /dev/null +++ b/test/fuzzer/three-bytes.test @@ -0,0 +1,8 @@ +Tests -use_value_profile=2 (alternative VP metric). +RUN: %cpp_compiler %S/ThreeBytes.cpp -o %t + +RUN: %run %t -seed=1 -runs=30000 +RUN: %run %t -seed=1 -runs=30000 -use_value_profile=1 +RUN: not %run %t -seed=1 -runs=1000000 -use_value_profile=2 2>&1 | FileCheck %s + +CHECK: Test unit written diff --git a/test/fuzzer/trace-malloc-2.test b/test/fuzzer/trace-malloc-2.test index 56f16d786012..2b32b95ed3e6 100644 --- a/test/fuzzer/trace-malloc-2.test +++ b/test/fuzzer/trace-malloc-2.test @@ -4,7 +4,7 @@ UNSUPPORTED: darwin RUN: %cpp_compiler %S/TraceMallocTest.cpp -o %t-TraceMallocTest -RUN: %t-TraceMallocTest -seed=1 -trace_malloc=2 -runs=1000 2>&1 | FileCheck %s --check-prefix=TRACE2 +RUN: %run %t-TraceMallocTest -seed=1 -trace_malloc=2 -runs=1000 2>&1 | FileCheck %s --check-prefix=TRACE2 TRACE2-DAG: FREE[0] TRACE2-DAG: MALLOC[0] TRACE2-DAG: in LLVMFuzzerTestOneInput diff --git a/test/fuzzer/trace-malloc-threaded.test b/test/fuzzer/trace-malloc-threaded.test index 11f3f049155f..8f972d61f5c6 100644 --- a/test/fuzzer/trace-malloc-threaded.test +++ b/test/fuzzer/trace-malloc-threaded.test @@ -1,10 +1,11 @@ // FIXME: This test infinite loops on darwin because it crashes // printing a stack trace repeatedly -UNSUPPORTED: darwin +UNSUPPORTED: darwin, aarch64 -RUN: %cpp_compiler %S/TraceMallocThreadedTest.cpp -o %t-TraceMallocThreadedTest +RUN: %cpp_compiler %S/TraceMallocThreadedTest.cpp -o \ +RUN: %t-TraceMallocThreadedTest -RUN: %t-TraceMallocThreadedTest -trace_malloc=2 -runs=1 2>&1 | FileCheck %s +RUN: %run %t-TraceMallocThreadedTest -trace_malloc=2 -runs=1 2>&1 | FileCheck %s CHECK: {{MALLOC\[[0-9]+] +0x[0-9]+ 5639}} CHECK-NEXT: {{ +\#0 +}} CHECK-NEXT: {{ +\#1 +}} diff --git a/test/fuzzer/trace-malloc-unbalanced.test b/test/fuzzer/trace-malloc-unbalanced.test index 8be5fab0ca43..193df01ddeff 100644 --- a/test/fuzzer/trace-malloc-unbalanced.test +++ b/test/fuzzer/trace-malloc-unbalanced.test @@ -6,10 +6,10 @@ UNSUPPORTED: darwin RUN: %cpp_compiler %S/TraceMallocTest.cpp -o %t-TraceMallocTest -RUN: %t-TraceMallocTest -seed=1 -trace_malloc=1 -runs=200 2>&1 | \ +RUN: %run %t-TraceMallocTest -seed=1 -trace_malloc=1 -runs=200 2>&1 | \ RUN: %libfuzzer_src/scripts/unbalanced_allocs.py --skip=5 | FileCheck %s -RUN: %t-TraceMallocTest -seed=1 -trace_malloc=2 -runs=200 2>&1 | \ +RUN: %run %t-TraceMallocTest -seed=1 -trace_malloc=2 -runs=200 2>&1 | \ RUN: %libfuzzer_src/scripts/unbalanced_allocs.py --skip=5 | FileCheck %s --check-prefixes=CHECK,CHECK2 CHECK: MallocFreeTracer: START diff --git a/test/fuzzer/trace-malloc.test b/test/fuzzer/trace-malloc.test index 979be99b7ac2..156d06a0c01e 100644 --- a/test/fuzzer/trace-malloc.test +++ b/test/fuzzer/trace-malloc.test @@ -1,6 +1,6 @@ RUN: %cpp_compiler %S/TraceMallocTest.cpp -o %t-TraceMallocTest -RUN: %t-TraceMallocTest -seed=1 -trace_malloc=1 -runs=10000 2>&1 | FileCheck %s +RUN: %run %t-TraceMallocTest -seed=1 -trace_malloc=1 -runs=10000 2>&1 | FileCheck %s CHECK-DAG: MallocFreeTracer: STOP 0 0 (same) CHECK-DAG: MallocFreeTracer: STOP 0 1 (DIFFERENT) CHECK-DAG: MallocFreeTracer: STOP 1 0 (DIFFERENT) diff --git a/test/fuzzer/trace-pc.test b/test/fuzzer/trace-pc.test index eaa0cb08afbe..30049331e360 100644 --- a/test/fuzzer/trace-pc.test +++ b/test/fuzzer/trace-pc.test @@ -1,3 +1,3 @@ -RUN: %cpp_compiler %S/SimpleTest.cpp -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard -fsanitize-coverage=trace-pc -o %t-SimpleTest-TracePC +RUN: %cpp_compiler %S/SimpleTest.cpp -fsanitize-coverage=0 -fsanitize-coverage=trace-pc -o %t-SimpleTest-TracePC CHECK: BINGO -RUN: not %t-SimpleTest-TracePC -runs=1000000 -seed=1 2>&1 | FileCheck %s +RUN: not %run %t-SimpleTest-TracePC -runs=1000000 -seed=1 2>&1 | FileCheck %s diff --git a/test/fuzzer/ulimit.test b/test/fuzzer/ulimit.test index 8772caa2d4c3..076866c50940 100644 --- a/test/fuzzer/ulimit.test +++ b/test/fuzzer/ulimit.test @@ -1,3 +1,3 @@ RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest RUN: ulimit -s 1000 -RUN: not %t-SimpleTest +RUN: not %run %t-SimpleTest diff --git a/test/fuzzer/value-profile-cmp.test b/test/fuzzer/value-profile-cmp.test index 64244297c64a..b927422d10ff 100644 --- a/test/fuzzer/value-profile-cmp.test +++ b/test/fuzzer/value-profile-cmp.test @@ -1,3 +1,3 @@ CHECK: BINGO RUN: %cpp_compiler %S/SimpleCmpTest.cpp -o %t-SimpleCmpTest -RUN: not %t-SimpleCmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s +RUN: not %run %t-SimpleCmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-cmp2.test b/test/fuzzer/value-profile-cmp2.test index a585c9317fab..4bf119fcb3df 100644 --- a/test/fuzzer/value-profile-cmp2.test +++ b/test/fuzzer/value-profile-cmp2.test @@ -1,3 +1,3 @@ CHECK: BINGO RUN: %cpp_compiler -fno-sanitize=address %S/SimpleHashTest.cpp -o %t-SimpleHashTest -RUN: not %t-SimpleHashTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 -max_len=64 2>&1 | FileCheck %s +RUN: not %run %t-SimpleHashTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 -max_len=64 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-cmp3.test b/test/fuzzer/value-profile-cmp3.test index d2284750b51e..58ba18b9001e 100644 --- a/test/fuzzer/value-profile-cmp3.test +++ b/test/fuzzer/value-profile-cmp3.test @@ -1,3 +1,3 @@ CHECK: BINGO RUN: %cpp_compiler %S/AbsNegAndConstantTest.cpp -o %t-AbsNegAndConstantTest -RUN: not %t-AbsNegAndConstantTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s +RUN: not %run %t-AbsNegAndConstantTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-cmp4.test b/test/fuzzer/value-profile-cmp4.test index bcbc67b1801f..05bc3f435912 100644 --- a/test/fuzzer/value-profile-cmp4.test +++ b/test/fuzzer/value-profile-cmp4.test @@ -1,3 +1,3 @@ CHECK: BINGO RUN: %cpp_compiler %S/AbsNegAndConstant64Test.cpp -o %t-AbsNegAndConstant64Test -RUN: not %t-AbsNegAndConstant64Test -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s +RUN: not %run %t-AbsNegAndConstant64Test -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-div.test b/test/fuzzer/value-profile-div.test index 8711a25466e5..59cc7c2f9552 100644 --- a/test/fuzzer/value-profile-div.test +++ b/test/fuzzer/value-profile-div.test @@ -1,4 +1,6 @@ +XFAIL: ios +UNSUPPORTED: aarch64 CHECK: AddressSanitizer: {{FPE|int-divide-by-zero}} RUN: %cpp_compiler %S/DivTest.cpp -fsanitize-coverage=trace-div -o %t-DivTest -RUN: not %t-DivTest -seed=1 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s +RUN: not %run %t-DivTest -seed=1 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-load.test b/test/fuzzer/value-profile-load.test index 3bf2a658a5b2..607b81cd527f 100644 --- a/test/fuzzer/value-profile-load.test +++ b/test/fuzzer/value-profile-load.test @@ -1,3 +1,3 @@ CHECK: AddressSanitizer: global-buffer-overflow -RUN: %cpp_compiler %S/LoadTest.cpp -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-gep,trace-div,trace-cmp -o %t-LoadTest -RUN: not %t-LoadTest -seed=2 -use_cmp=0 -use_value_profile=1 -runs=20000000 2>&1 | FileCheck %s +RUN: %cpp_compiler %S/LoadTest.cpp -fsanitize-coverage=trace-gep -o %t-LoadTest +RUN: not %run %t-LoadTest -seed=2 -use_cmp=0 -use_value_profile=1 -runs=20000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-mem.test b/test/fuzzer/value-profile-mem.test index 0b0c21d689ce..57c844e92261 100644 --- a/test/fuzzer/value-profile-mem.test +++ b/test/fuzzer/value-profile-mem.test @@ -1,3 +1,4 @@ +UNSUPPORTED: freebsd CHECK: BINGO RUN: %cpp_compiler %S/SingleMemcmpTest.cpp -o %t-SingleMemcmpTest -RUN: not %t-SingleMemcmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s +RUN: not %run %t-SingleMemcmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-set.test b/test/fuzzer/value-profile-set.test index e2e3fb47f3ad..e55f1e4a853a 100644 --- a/test/fuzzer/value-profile-set.test +++ b/test/fuzzer/value-profile-set.test @@ -1,4 +1,4 @@ CHECK: BINGO RUN: %cpp_compiler %S/FourIndependentBranchesTest.cpp -o %t-FourIndependentBranchesTest -RUN: not %t-FourIndependentBranchesTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s +RUN: not %run %t-FourIndependentBranchesTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-strcmp.test b/test/fuzzer/value-profile-strcmp.test index f5c766a658f4..647121f22820 100644 --- a/test/fuzzer/value-profile-strcmp.test +++ b/test/fuzzer/value-profile-strcmp.test @@ -1,3 +1,4 @@ +UNSUPPORTED: freebsd CHECK: BINGO RUN: %cpp_compiler %S/SingleStrcmpTest.cpp -o %t-SingleStrcmpTest -RUN: not %t-SingleStrcmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s +RUN: not %run %t-SingleStrcmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-strncmp.test b/test/fuzzer/value-profile-strncmp.test index 2dfe43c4abc5..b60b97f86f3e 100644 --- a/test/fuzzer/value-profile-strncmp.test +++ b/test/fuzzer/value-profile-strncmp.test @@ -1,3 +1,4 @@ +UNSUPPORTED: freebsd CHECK: BINGO RUN: %cpp_compiler %S/SingleStrncmpTest.cpp -o %t-SingleStrncmpTest -RUN: not %t-SingleStrncmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s +RUN: not %run %t-SingleStrncmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s diff --git a/test/fuzzer/value-profile-switch.test b/test/fuzzer/value-profile-switch.test index 7edb312a07b0..cc3d4944c0bf 100644 --- a/test/fuzzer/value-profile-switch.test +++ b/test/fuzzer/value-profile-switch.test @@ -1,5 +1,6 @@ +XFAIL: ios CHECK: BINGO RUN: %cpp_compiler %S/SwitchTest.cpp -o %t-SwitchTest RUN: %cpp_compiler %S/Switch2Test.cpp -o %t-Switch2Test -RUN: not %t-SwitchTest -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s -RUN: not %t-Switch2Test -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s +RUN: not %run %t-SwitchTest -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s +RUN: not %run %t-Switch2Test -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s diff --git a/test/hwasan/TestCases/Linux/aligned_alloc-alignment.cc b/test/hwasan/TestCases/Linux/aligned_alloc-alignment.cc new file mode 100644 index 000000000000..a5dc7f661c7a --- /dev/null +++ b/test/hwasan/TestCases/Linux/aligned_alloc-alignment.cc @@ -0,0 +1,25 @@ +// RUN: %clangxx_hwasan -O0 %s -o %t +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s +// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL + +// UNSUPPORTED: android + +// REQUIRES: stable-runtime + +#include <stdio.h> +#include <stdlib.h> + +extern void *aligned_alloc(size_t alignment, size_t size); + +int main() { + void *p = aligned_alloc(17, 100); + // CHECK: ERROR: HWAddressSanitizer: invalid alignment requested in aligned_alloc: 17 + // CHECK: {{#0 0x.* in .*}}{{aligned_alloc|memalign}} + // CHECK: {{#1 0x.* in main .*aligned_alloc-alignment.cc:}}[[@LINE-3]] + // CHECK: SUMMARY: HWAddressSanitizer: invalid-aligned-alloc-alignment + + printf("pointer after failed aligned_alloc: %zd\n", (size_t)p); + // CHECK-NULL: pointer after failed aligned_alloc: 0 + + return 0; +} diff --git a/test/hwasan/TestCases/Linux/lit.local.cfg b/test/hwasan/TestCases/Linux/lit.local.cfg new file mode 100644 index 000000000000..57271b8078a4 --- /dev/null +++ b/test/hwasan/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/hwasan/TestCases/Linux/pvalloc-overflow.cc b/test/hwasan/TestCases/Linux/pvalloc-overflow.cc new file mode 100644 index 000000000000..a4897c1279e7 --- /dev/null +++ b/test/hwasan/TestCases/Linux/pvalloc-overflow.cc @@ -0,0 +1,46 @@ +// RUN: %clangxx_hwasan -O0 %s -o %t +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t m1 2>&1 | FileCheck %s +// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t m1 2>&1 | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t psm1 2>&1 | FileCheck %s +// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t psm1 2>&1 | FileCheck %s --check-prefix=CHECK-NULL + +// UNSUPPORTED: android + +// REQUIRES: stable-runtime + +// Checks that pvalloc overflows are caught. If the allocator is allowed to +// return null, the errno should be set to ENOMEM. + +#include <assert.h> +#include <errno.h> +#include <malloc.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +int main(int argc, char *argv[]) { + assert(argc == 2); + const char *action = argv[1]; + + const size_t page_size = sysconf(_SC_PAGESIZE); + + void *p = nullptr; + if (!strcmp(action, "m1")) { + p = pvalloc((uintptr_t)-1); + } else if (!strcmp(action, "psm1")) { + p = pvalloc((uintptr_t)-(page_size - 1)); + } else { + assert(0); + } + + fprintf(stderr, "errno: %d\n", errno); + + return p != nullptr; +} + +// CHECK: {{ERROR: HWAddressSanitizer: pvalloc parameters overflow: size .* rounded up to system page size .* cannot be represented in type size_t}} +// CHECK: {{#0 0x.* in .*pvalloc}} +// CHECK: {{#1 0x.* in main .*pvalloc-overflow.cc:}} +// CHECK: SUMMARY: HWAddressSanitizer: pvalloc-overflow + +// CHECK-NULL: errno: 12 diff --git a/test/hwasan/TestCases/Posix/lit.local.cfg b/test/hwasan/TestCases/Posix/lit.local.cfg new file mode 100644 index 000000000000..60a9460820a6 --- /dev/null +++ b/test/hwasan/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']: + config.unsupported = True diff --git a/test/hwasan/TestCases/Posix/posix_memalign-alignment.cc b/test/hwasan/TestCases/Posix/posix_memalign-alignment.cc new file mode 100644 index 000000000000..1ecc39c42f23 --- /dev/null +++ b/test/hwasan/TestCases/Posix/posix_memalign-alignment.cc @@ -0,0 +1,22 @@ +// RUN: %clangxx_hwasan -O0 %s -o %t +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s +// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL + +// REQUIRES: stable-runtime + +#include <stdio.h> +#include <stdlib.h> + +int main() { + void *p = reinterpret_cast<void*>(42); + int res = posix_memalign(&p, 17, 100); + // CHECK: ERROR: HWAddressSanitizer: invalid alignment requested in posix_memalign: 17 + // CHECK: {{#0 0x.* in .*posix_memalign}} + // CHECK: {{#1 0x.* in main .*posix_memalign-alignment.cc:}}[[@LINE-3]] + // CHECK: SUMMARY: HWAddressSanitizer: invalid-posix-memalign-alignment + + printf("pointer after failed posix_memalign: %zd\n", (size_t)p); + // CHECK-NULL: pointer after failed posix_memalign: 42 + + return 0; +} diff --git a/test/msan/allocator_returns_null.cc b/test/hwasan/TestCases/allocator_returns_null.cc index 583b5b4f76be..8d2ef38d4ab7 100644 --- a/test/msan/allocator_returns_null.cc +++ b/test/hwasan/TestCases/allocator_returns_null.cc @@ -1,42 +1,44 @@ -// Test the behavior of malloc/calloc/realloc/new when the allocation size is -// more than MSan allocator's max allowed one. -// By default (allocator_may_return_null=0) the process should crash. -// With allocator_may_return_null=1 the allocator should return 0, except the -// operator new(), which should crash anyway (operator new(std::nothrow) should -// return nullptr, indeed). +// Test the behavior of malloc/calloc/realloc/new when the allocation size +// exceeds the HWASan allocator's max allowed one. +// By default (allocator_may_return_null=0) the process should crash. With +// allocator_may_return_null=1 the allocator should return 0 and set errno to +// the appropriate error code. // -// RUN: %clangxx_msan -O0 %s -o %t +// RUN: %clangxx_hwasan -O0 %s -o %t // RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t malloc 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t malloc 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t malloc 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-mNULL -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t calloc 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-cCRASH -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t calloc 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t calloc 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-cNULL -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-coCRASH -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t calloc-overflow 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t calloc-overflow 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-coNULL -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t realloc 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-rCRASH -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t realloc 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t realloc 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-rNULL -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-mrCRASH -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t realloc-after-malloc 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t realloc-after-malloc 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-mrNULL -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t new 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t new 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-nCRASH -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 not %run %t new 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=1 not %run %t new 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH-OOM +// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t new-nothrow 2>&1 \ +// RUN: %env_hwasan_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-nnNULL -// UNSUPPORTED: win32 +// REQUIRES: stable-runtime + +// TODO(alekseyshl): Fix it. +// UNSUPPORTED: android #include <assert.h> #include <errno.h> @@ -47,21 +49,13 @@ #include <new> int main(int argc, char **argv) { - // Disable stderr buffering. Needed on Windows. - setvbuf(stderr, NULL, _IONBF, 0); - assert(argc == 2); const char *action = argv[1]; fprintf(stderr, "%s:\n", action); - static const size_t kMaxAllowedMallocSizePlusOne = -#if __LP64__ || defined(_WIN64) - (8UL << 30) + 1; -#else - (2UL << 30) + 1; -#endif + static const size_t kMaxAllowedMallocSizePlusOne = (2UL << 30) + 1; - void *x = 0; + void *x = nullptr; if (!strcmp(action, "malloc")) { x = malloc(kMaxAllowedMallocSizePlusOne); } else if (!strcmp(action, "calloc")) { @@ -89,43 +83,36 @@ int main(int argc, char **argv) { fprintf(stderr, "errno: %d\n", errno); - // The NULL pointer is printed differently on different systems, while (long)0 - // is always the same. - fprintf(stderr, "x: %lx\n", (long)x); free(x); - return x != 0; + return x != nullptr; } // CHECK-mCRASH: malloc: -// CHECK-mCRASH: MemorySanitizer's allocator is terminating the process +// CHECK-mCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big // CHECK-cCRASH: calloc: -// CHECK-cCRASH: MemorySanitizer's allocator is terminating the process +// CHECK-cCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big // CHECK-coCRASH: calloc-overflow: -// CHECK-coCRASH: MemorySanitizer's allocator is terminating the process +// CHECK-coCRASH: SUMMARY: HWAddressSanitizer: calloc-overflow // CHECK-rCRASH: realloc: -// CHECK-rCRASH: MemorySanitizer's allocator is terminating the process +// CHECK-rCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big // CHECK-mrCRASH: realloc-after-malloc: -// CHECK-mrCRASH: MemorySanitizer's allocator is terminating the process +// CHECK-mrCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big // CHECK-nCRASH: new: -// CHECK-nCRASH: MemorySanitizer's allocator is terminating the process +// CHECK-nCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big +// CHECK-nCRASH-OOM: new: +// CHECK-nCRASH-OOM: SUMMARY: HWAddressSanitizer: out-of-memory // CHECK-nnCRASH: new-nothrow: -// CHECK-nnCRASH: MemorySanitizer's allocator is terminating the process +// CHECK-nnCRASH: SUMMARY: HWAddressSanitizer: allocation-size-too-big // CHECK-mNULL: malloc: // CHECK-mNULL: errno: 12 -// CHECK-mNULL: x: 0 // CHECK-cNULL: calloc: // CHECK-cNULL: errno: 12 -// CHECK-cNULL: x: 0 // CHECK-coNULL: calloc-overflow: // CHECK-coNULL: errno: 12 -// CHECK-coNULL: x: 0 // CHECK-rNULL: realloc: // CHECK-rNULL: errno: 12 -// CHECK-rNULL: x: 0 // CHECK-mrNULL: realloc-after-malloc: // CHECK-mrNULL: errno: 12 -// CHECK-mrNULL: x: 0 // CHECK-nnNULL: new-nothrow: -// CHECK-nnNULL: x: 0 diff --git a/test/hwasan/TestCases/check-interface.cc b/test/hwasan/TestCases/check-interface.cc new file mode 100644 index 000000000000..7ad911480359 --- /dev/null +++ b/test/hwasan/TestCases/check-interface.cc @@ -0,0 +1,22 @@ +// RUN: %clangxx_hwasan -mllvm -hwasan-instrument-with-calls=1 -O0 %s -o %t +// RUN: %clangxx_hwasan -mllvm -hwasan-instrument-with-calls=1 -O0 %s -o %t -fsanitize-recover=hwaddress + +// REQUIRES: stable-runtime + +// Utilizes all flavors of __hwasan_load/store interface functions to verify +// that the instrumentation and the interface provided by HWASan do match. +// In case of a discrepancy, this test fails to link. + +#include <sanitizer/hwasan_interface.h> + +#define F(T) void f_##T(T *a, T *b) { *a = *b; } + +F(uint8_t) +F(uint16_t) +F(uint32_t) +F(uint64_t) + +typedef unsigned V32 __attribute__((__vector_size__(32))); +F(V32) + +int main() {} diff --git a/test/hwasan/TestCases/stack-oob.cc b/test/hwasan/TestCases/stack-oob.cc new file mode 100644 index 000000000000..60b9a6295005 --- /dev/null +++ b/test/hwasan/TestCases/stack-oob.cc @@ -0,0 +1,25 @@ +// RUN: %clangxx_hwasan -DSIZE=16 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_hwasan -DSIZE=64 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_hwasan -DSIZE=0x1000 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// REQUIRES: stable-runtime + +#include <stdlib.h> +#include <sanitizer/hwasan_interface.h> + +__attribute__((noinline)) +int f() { + char z[SIZE]; + char *volatile p = z; + return p[SIZE]; +} + +int main() { + return f(); + // CHECK: READ of size 1 at + // CHECK: #0 {{.*}} in f{{.*}}stack-oob.cc:14 + + // CHECK: HWAddressSanitizer can not describe address in more detail. + + // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in f +} diff --git a/test/hwasan/TestCases/stack-uar.cc b/test/hwasan/TestCases/stack-uar.cc new file mode 100644 index 000000000000..e99dcceed533 --- /dev/null +++ b/test/hwasan/TestCases/stack-uar.cc @@ -0,0 +1,23 @@ +// RUN: %clangxx_hwasan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// REQUIRES: stable-runtime + +#include <stdlib.h> +#include <sanitizer/hwasan_interface.h> + +__attribute__((noinline)) +char *f() { + char z[0x1000]; + char *volatile p = z; + return p; +} + +int main() { + return *f(); + // CHECK: READ of size 1 at + // CHECK: #0 {{.*}} in main{{.*}}stack-uar.cc:16 + + // CHECK: HWAddressSanitizer can not describe address in more detail. + + // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main +} diff --git a/test/hwasan/TestCases/use-after-free.c b/test/hwasan/TestCases/use-after-free.c new file mode 100644 index 000000000000..b9f6060112c1 --- /dev/null +++ b/test/hwasan/TestCases/use-after-free.c @@ -0,0 +1,39 @@ +// RUN: %clang_hwasan -O0 -DLOAD %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,LOAD +// RUN: %clang_hwasan -O1 -DLOAD %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,LOAD +// RUN: %clang_hwasan -O2 -DLOAD %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,LOAD +// RUN: %clang_hwasan -O3 -DLOAD %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,LOAD + +// RUN: %clang_hwasan -O0 -DSTORE %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,STORE + +// REQUIRES: stable-runtime + +#include <stdlib.h> +#include <sanitizer/hwasan_interface.h> + +int main() { + __hwasan_enable_allocator_tagging(); + char * volatile x = (char*)malloc(10); + free(x); + __hwasan_disable_allocator_tagging(); +#ifdef STORE + x[5] = 42; +#endif +#ifdef LOAD + return x[5]; +#endif + // LOAD: READ of size 1 at + // LOAD: #0 {{.*}} in main {{.*}}use-after-free.c:22 + + // STORE: WRITE of size 1 at + // STORE: #0 {{.*}} in main {{.*}}use-after-free.c:19 + + // CHECK: freed here: + // CHECK: #0 {{.*}} in {{.*}}free{{.*}} {{.*}}hwasan_interceptors.cc + // CHECK: #1 {{.*}} in main {{.*}}use-after-free.c:16 + + // CHECK: previously allocated here: + // CHECK: #0 {{.*}} in {{.*}}malloc{{.*}} {{.*}}hwasan_interceptors.cc + // CHECK: #1 {{.*}} in main {{.*}}use-after-free.c:15 + + // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main +} diff --git a/test/hwasan/TestCases/use-after-free.cc b/test/hwasan/TestCases/use-after-free.cc deleted file mode 100644 index 37637898d7a1..000000000000 --- a/test/hwasan/TestCases/use-after-free.cc +++ /dev/null @@ -1,39 +0,0 @@ -// RUN: %clangxx_hwasan -O0 -DLOAD %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,LOAD -// RUN: %clangxx_hwasan -O1 -DLOAD %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,LOAD -// RUN: %clangxx_hwasan -O2 -DLOAD %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,LOAD -// RUN: %clangxx_hwasan -O3 -DLOAD %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,LOAD - -// RUN: %clangxx_hwasan -O0 -DSTORE %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,STORE - -// REQUIRES: stable-runtime - -#include <stdlib.h> -#include <sanitizer/hwasan_interface.h> - -int main() { - __hwasan_enable_allocator_tagging(); - char * volatile x = (char*)malloc(10); - free(x); - __hwasan_disable_allocator_tagging(); -#ifdef STORE - x[5] = 42; -#endif -#ifdef LOAD - return x[5]; -#endif - // LOAD: READ of size 1 at - // LOAD: #0 {{.*}} in main {{.*}}use-after-free.cc:22 - - // STORE: WRITE of size 1 at - // STORE: #0 {{.*}} in main {{.*}}use-after-free.cc:19 - - // CHECK: freed here: - // CHECK: #0 {{.*}} in free {{.*}}hwasan_interceptors.cc - // CHECK: #1 {{.*}} in main {{.*}}use-after-free.cc:16 - - // CHECK: previously allocated here: - // CHECK: #0 {{.*}} in __interceptor_malloc {{.*}}hwasan_interceptors.cc - // CHECK: #1 {{.*}} in main {{.*}}use-after-free.cc:15 - - // CHECK: SUMMARY: HWAddressSanitizer: tag-mismatch {{.*}} in main -} diff --git a/test/hwasan/lit.cfg b/test/hwasan/lit.cfg index 4f099af5b7fc..3ebba51d05e4 100644 --- a/test/hwasan/lit.cfg +++ b/test/hwasan/lit.cfg @@ -9,7 +9,7 @@ config.name = 'HWAddressSanitizer' + getattr(config, 'name_suffix', 'default') config.test_source_root = os.path.dirname(__file__) # Setup default compiler flags used with -fsanitize=memory option. -clang_hwasan_cflags = ["-fsanitize=hwaddress", config.target_cflags] + config.debug_info_flags +clang_hwasan_cflags = ["-fsanitize=hwaddress", "-mllvm", "-hwasan-generate-tags-with-calls", config.target_cflags] + config.debug_info_flags clang_hwasan_cxxflags = config.cxx_mode_flags + clang_hwasan_cflags def build_invocation(compile_flags): @@ -18,7 +18,7 @@ def build_invocation(compile_flags): config.substitutions.append( ("%clang_hwasan ", build_invocation(clang_hwasan_cflags)) ) config.substitutions.append( ("%clangxx_hwasan ", build_invocation(clang_hwasan_cxxflags)) ) -default_hwasan_opts_str = ':'.join(['disable_allocator_tagging=1'] + config.default_sanitizer_opts) +default_hwasan_opts_str = ':'.join(['disable_allocator_tagging=1', 'random_tags=0'] + config.default_sanitizer_opts) if default_hwasan_opts_str: config.environment['HWASAN_OPTIONS'] = default_hwasan_opts_str default_hwasan_opts_str += ':' diff --git a/test/lit.common.cfg b/test/lit.common.cfg index 0840f65a7161..5274b49c654f 100644 --- a/test/lit.common.cfg +++ b/test/lit.common.cfg @@ -7,6 +7,7 @@ import os import platform import re import subprocess +import json import lit.formats import lit.util @@ -37,7 +38,11 @@ if compiler_id == "Clang": # reports and stack traces even with minimal debug info. config.debug_info_flags = ["-gline-tables-only"] if platform.system() == 'Windows': + # On Windows, use CodeView with column info instead of DWARF. Both VS and + # windbg do not behave well when column info is enabled, but users have + # requested it because it makes ASan reports more precise. config.debug_info_flags.append("-gcodeview") + config.debug_info_flags.append("-gcolumn-info") elif compiler_id == 'GNU': config.cxx_mode_flags = ["-x c++"] config.debug_info_flags = ["-g"] @@ -86,8 +91,10 @@ config.environment['PATH'] = path if platform.system() == 'Windows' and '-win' in config.target_triple: config.environment['LIB'] = os.environ['LIB'] +config.available_features.add(config.host_os.lower()) + if re.match(r'^x86_64.*-linux', config.target_triple): - config.available_features.add("x86_64-linux") + config.available_features.add("x86_64-linux") # Use ugly construction to explicitly prohibit "clang", "clang++" etc. # in RUN lines. @@ -100,17 +107,50 @@ if config.emulator: config.substitutions.append( ('%run', config.emulator) ) config.substitutions.append( ('%env ', "env ") ) config.compile_wrapper = "" -elif config.ios: +elif config.host_os == 'Darwin' and config.apple_platform != "osx": + # Darwin tests can be targetting macOS, a device or a simulator. All devices + # are declared as "ios", even for iOS derivatives (tvOS, watchOS). Similarly, + # all simulators are "iossim". See the table below. + # + # ========================================================================= + # Target | Feature set + # ========================================================================= + # macOS | darwin + # iOS device | darwin, ios + # iOS simulator | darwin, ios, iossim + # tvOS device | darwin, ios, tvos + # tvOS simulator | darwin, ios, iossim, tvos, tvossim + # watchOS device | darwin, ios, watchos + # watchOS simulator | darwin, ios, iossim, watchos, watchossim + # ========================================================================= + + ios_or_iossim = "iossim" if config.apple_platform.endswith("sim") else "ios" + config.available_features.add('ios') - device_id_env = "SANITIZER_IOSSIM_TEST_DEVICE_IDENTIFIER" if config.iossim else "SANITIZER_IOS_TEST_DEVICE_IDENTIFIER" - if device_id_env in os.environ: config.environment[device_id_env] = os.environ[device_id_env] + if ios_or_iossim == "iossim": + config.available_features.add('iossim') + if config.apple_platform != "ios" and config.apple_platform != "iossim": + config.available_features.add(config.apple_platform) + ios_commands_dir = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "ios_commands") - run_wrapper = os.path.join(ios_commands_dir, "iossim_run.py" if config.iossim else "ios_run.py") + + device_id_env = "SANITIZER_" + ios_or_iossim.upper() + "_TEST_DEVICE_IDENTIFIER" + run_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_run.py") + env_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_env.py") + compile_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_compile.py") + prepare_script = os.path.join(ios_commands_dir, ios_or_iossim + "_prepare.py") + + if device_id_env in os.environ: + config.environment[device_id_env] = os.environ[device_id_env] config.substitutions.append(('%run', run_wrapper)) - env_wrapper = os.path.join(ios_commands_dir, "iossim_env.py" if config.iossim else "ios_env.py") config.substitutions.append(('%env ', env_wrapper + " ")) - compile_wrapper = os.path.join(ios_commands_dir, "iossim_compile.py" if config.iossim else "ios_compile.py") config.compile_wrapper = compile_wrapper + + prepare_output = subprocess.check_output([prepare_script, config.apple_platform, config.clang]).strip() + if len(prepare_output) > 0: print(prepare_output) + prepare_output_json = prepare_output.split("\n")[-1] + prepare_output = json.loads(prepare_output_json) + config.environment.update(prepare_output["env"]) elif config.android: config.available_features.add('android') compile_wrapper = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "android_commands", "android_compile.py") + " " @@ -197,8 +237,19 @@ if config.host_os == 'Darwin': pass config.substitutions.append( ("%macos_min_target_10_11", "-mmacosx-version-min=10.11") ) + + isIOS = config.apple_platform != "osx" + # rdar://problem/22207160 + config.substitutions.append( ("%darwin_min_target_with_full_runtime_arc_support", + "-miphoneos-version-min=9.0" if isIOS else "-mmacosx-version-min=10.11") ) + + # 32-bit iOS simulator is deprecated and removed in latest Xcode. + if config.apple_platform == "iossim": + if config.target_arch == "i386": + config.unsupported = True else: config.substitutions.append( ("%macos_min_target_10_11", "") ) + config.substitutions.append( ("%darwin_min_target_with_full_runtime_arc_support", "") ) if config.android: adb = os.environ.get('ADB', 'adb') @@ -265,6 +316,8 @@ if config.lto_supported: config.lto_flags += ["-flto=thin"] else: config.lto_flags += ["-flto"] + if config.use_newpm: + config.lto_flags += ["-fexperimental-new-pass-manager"] # Ask llvm-config about assertion mode. try: @@ -291,20 +344,43 @@ if platform.system() == 'Windows': if platform.system() == 'Darwin': lit_config.parallelism_groups["darwin-64bit-sanitizer"] = 3 -if config.host_os == 'Darwin': - config.substitutions.append( ("%ld_flags_rpath_exe", '-Wl,-rpath,@executable_path/ %dynamiclib') ) - config.substitutions.append( ("%ld_flags_rpath_so", '-install_name @rpath/`basename %dynamiclib`') ) -elif config.host_os == 'FreeBSD': - config.substitutions.append( ("%ld_flags_rpath_exe", "-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec") ) - config.substitutions.append( ("%ld_flags_rpath_so", '') ) -elif config.host_os == 'Linux': - config.substitutions.append( ("%ld_flags_rpath_exe", "-Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec") ) - config.substitutions.append( ("%ld_flags_rpath_so", '') ) - -# Must be defined after the substitutions that use %dynamiclib. -config.substitutions.append( ("%dynamiclib", '%T/%xdynamiclib_filename') ) -config.substitutions.append( ("%xdynamiclib_filename", 'lib%xdynamiclib_namespec.so') ) -config.substitutions.append( ("%xdynamiclib_namespec", '%basename_t.dynamic') ) +# The current implementation of the tools in sanitizer_common/ios_comamnds +# do not support parallel execution so force sequential execution of the +# tests on iOS devices. +if config.host_os == 'Darwin' and config.apple_platform != "osx" and not config.apple_platform.endswith("sim"): + lit_config.warning("iOS device test cases being run sequentially") + lit_config.parallelism_groups["darwin-ios-device-sanitizer"] = 1 + +# Multiple substitutions are necessary to support multiple shared objects used +# at once. +# Note that substitutions with numbers have to be defined first to avoid +# being subsumed by substitutions with smaller postfix. +for postfix in ["2", "1", ""]: + if config.host_os == 'Darwin': + config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, '-Wl,-rpath,@executable_path/ %dynamiclib' + postfix) ) + config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '-install_name @rpath/`basename %dynamiclib{}`'.format(postfix)) ) + elif config.host_os in ('FreeBSD', 'NetBSD', 'OpenBSD'): + config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) ) + config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') ) + elif config.host_os == 'Linux': + config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) ) + config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') ) + elif config.host_os == 'SunOS': + config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-R\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) ) + config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') ) + + # Must be defined after the substitutions that use %dynamiclib. + config.substitutions.append( ("%dynamiclib" + postfix, '%T/%xdynamiclib_filename' + postfix) ) + config.substitutions.append( ("%xdynamiclib_filename" + postfix, 'lib%xdynamiclib_namespec{}.so'.format(postfix)) ) + config.substitutions.append( ("%xdynamiclib_namespec", '%basename_t.dynamic') ) + +# Provide a substituion that can be used to tell Clang to use a static libstdc++. +# The substitution expands to nothing on non Linux platforms. +# FIXME: This should check the target OS, not the host OS. +if config.host_os == 'Linux': + config.substitutions.append( ("%linux_static_libstdcplusplus", "-stdlib=libstdc++ -static-libstdc++") ) +else: + config.substitutions.append( ("%linux_static_libstdcplusplus", "") ) config.default_sanitizer_opts = [] if config.host_os == 'Darwin': diff --git a/test/lit.common.configured.in b/test/lit.common.configured.in index 32a88200bf2d..63d55bfdea81 100644 --- a/test/lit.common.configured.in +++ b/test/lit.common.configured.in @@ -16,6 +16,7 @@ set_default("llvm_src_root", "@LLVM_MAIN_SRC_DIR@") set_default("llvm_obj_root", "@LLVM_BINARY_DIR@") set_default("compiler_rt_src_root", "@COMPILER_RT_SOURCE_DIR@") set_default("compiler_rt_obj_root", "@COMPILER_RT_BINARY_DIR@") +set_default("enable_per_target_runtime_dir", @LLVM_ENABLE_PER_TARGET_RUNTIME_DIR_PYBOOL@) set_default("llvm_tools_dir", "@LLVM_TOOLS_DIR@") set_default("llvm_shlib_dir", "@LLVM_LIBRARY_OUTPUT_INTDIR@") set_default("gold_executable", "@GOLD_EXECUTABLE@") @@ -26,17 +27,22 @@ set_default("compiler_rt_debug", @COMPILER_RT_DEBUG_PYBOOL@) set_default("compiler_rt_libdir", "@COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR@") set_default("emulator", "@COMPILER_RT_EMULATOR@") set_default("asan_shadow_scale", "@COMPILER_RT_ASAN_SHADOW_SCALE@") -set_default("ios", False) -set_default("iossim", False) +set_default("apple_platform", "osx") set_default("sanitizer_can_use_cxxabi", @SANITIZER_CAN_USE_CXXABI_PYBOOL@) set_default("has_lld", @COMPILER_RT_HAS_LLD_PYBOOL@) set_default("can_symbolize", @CAN_SYMBOLIZE@) set_default("use_lld", False) set_default("use_thinlto", False) set_default("use_lto", config.use_thinlto) +set_default("use_newpm", False) set_default("android", @ANDROID_PYBOOL@) config.available_features.add('target-is-%s' % config.target_arch) +if config.enable_per_target_runtime_dir: + set_default("target_suffix", "") +else: + set_default("target_suffix", "-%s" % config.target_arch) + # LLVM tools dir can be passed in lit parameters, so try to # apply substitution. try: diff --git a/test/lsan/TestCases/Linux/fork_with_threads.cc b/test/lsan/TestCases/Linux/fork_with_threads.cc new file mode 100644 index 000000000000..221c5d249d77 --- /dev/null +++ b/test/lsan/TestCases/Linux/fork_with_threads.cc @@ -0,0 +1,35 @@ +// Test forked process does not run lsan. +// RUN: %clangxx_lsan %s -o %t && %run %t 2>&1 | FileCheck %s + +#include <pthread.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <unistd.h> + +static pthread_barrier_t barrier; + +// CHECK-NOT: SUMMARY: {{(Leak|Address)}}Sanitizer: +static void *thread_func(void *arg) { + void *buffer = malloc(1337); + pthread_barrier_wait(&barrier); + for (;;) + pthread_yield(); + return 0; +} + +int main() { + pthread_barrier_init(&barrier, 0, 2); + pthread_t tid; + int res = pthread_create(&tid, 0, thread_func, 0); + pthread_barrier_wait(&barrier); + pthread_barrier_destroy(&barrier); + + pid_t pid = fork(); + if (pid > 0) { + int status = 0; + waitpid(pid, &status, 0); + } + return 0; +} + +// CHECK: WARNING: LeakSanitizer is disabled in forked process diff --git a/test/lsan/TestCases/Linux/log-path_test.cc b/test/lsan/TestCases/Linux/log-path_test.cc new file mode 100644 index 000000000000..a31b4f64acc5 --- /dev/null +++ b/test/lsan/TestCases/Linux/log-path_test.cc @@ -0,0 +1,26 @@ +// RUN: %clangxx_lsan %s -o %t +// The globs below do not work in the lit shell. + +// Regular run. +// RUN: %env_lsan_opts="use_stacks=0" not %run %t > %t.out 2>&1 +// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %t.out + +// Good log_path. +// RUN: rm -f %t.log.* +// RUN: %env_lsan_opts="use_stacks=0:log_path='"%t.log"'" not %run %t > %t.out 2>&1 +// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %t.log.* + +#include <stdio.h> +#include <stdlib.h> +#include "sanitizer_common/print_address.h" + +int main() { + void *stack_var = malloc(1337); + print_address("Test alloc: ", 1, stack_var); + // Do not return from main to prevent the pointer from going out of scope. + exit(0); +} + +// CHECK-ERROR: LeakSanitizer: detected memory leaks +// CHECK-ERROR: Direct leak of 1337 byte(s) in 1 object(s) allocated from +// CHECK-ERROR: SUMMARY: {{(Leak|Address)}}Sanitizer: diff --git a/test/lsan/TestCases/Linux/use_tls_dynamic.cc b/test/lsan/TestCases/Linux/use_tls_dynamic.cc index f5df231ba9a6..4d70a46f8183 100644 --- a/test/lsan/TestCases/Linux/use_tls_dynamic.cc +++ b/test/lsan/TestCases/Linux/use_tls_dynamic.cc @@ -5,7 +5,7 @@ // RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s // RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 -// UNSUPPORTED: i386-linux,arm +// UNSUPPORTED: i386-linux,arm,powerpc #ifndef BUILD_DSO #include <assert.h> diff --git a/test/lsan/TestCases/Posix/lit.local.cfg b/test/lsan/TestCases/Posix/lit.local.cfg new file mode 100644 index 000000000000..60a9460820a6 --- /dev/null +++ b/test/lsan/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']: + config.unsupported = True diff --git a/test/lsan/TestCases/allocator_returns_null.cc b/test/lsan/TestCases/allocator_returns_null.cc deleted file mode 100644 index 28dd696dc673..000000000000 --- a/test/lsan/TestCases/allocator_returns_null.cc +++ /dev/null @@ -1,131 +0,0 @@ -// Test the behavior of malloc/calloc/realloc/new when the allocation size is -// more than LSan allocator's max allowed one. -// By default (allocator_may_return_null=0) the process should crash. -// With allocator_may_return_null=1 the allocator should return 0, except the -// operator new(), which should crash anyway (operator new(std::nothrow) should -// return nullptr, indeed). -// -// RUN: %clangxx_lsan -O0 %s -o %t -// RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mNULL -// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-cCRASH -// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t calloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-cNULL -// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-coCRASH -// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t calloc-overflow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-coNULL -// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-rCRASH -// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t realloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-rNULL -// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mrCRASH -// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t realloc-after-malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mrNULL -// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t new 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH -// RUN: %env_lsan_opts=allocator_may_return_null=1 not %run %t new 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH -// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH -// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nnNULL - -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <limits> -#include <new> - -int main(int argc, char **argv) { - // Disable stderr buffering. Needed on Windows. - setvbuf(stderr, NULL, _IONBF, 0); - - assert(argc == 2); - const char *action = argv[1]; - fprintf(stderr, "%s:\n", action); - - // Use max of ASan and LSan allocator limits to cover both "lsan" and - // "lsan + asan" configs. - static const size_t kMaxAllowedMallocSizePlusOne = -#if __LP64__ || defined(_WIN64) - (1ULL << 40) + 1; -#else - (3UL << 30) + 1; -#endif - - void *x = 0; - if (!strcmp(action, "malloc")) { - x = malloc(kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "calloc")) { - x = calloc((kMaxAllowedMallocSizePlusOne / 4) + 1, 4); - } else if (!strcmp(action, "calloc-overflow")) { - volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max(); - size_t kArraySize = 4096; - volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10; - x = calloc(kArraySize, kArraySize2); - } else if (!strcmp(action, "realloc")) { - x = realloc(0, kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "realloc-after-malloc")) { - char *t = (char*)malloc(100); - *t = 42; - x = realloc(t, kMaxAllowedMallocSizePlusOne); - assert(*t == 42); - free(t); - } else if (!strcmp(action, "new")) { - x = operator new(kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "new-nothrow")) { - x = operator new(kMaxAllowedMallocSizePlusOne, std::nothrow); - } else { - assert(0); - } - - fprintf(stderr, "errno: %d\n", errno); - - // The NULL pointer is printed differently on different systems, while (long)0 - // is always the same. - fprintf(stderr, "x: %zu\n", (size_t)x); - free(x); - - return x != 0; -} - -// CHECK-mCRASH: malloc: -// CHECK-mCRASH: Sanitizer's allocator is terminating the process -// CHECK-cCRASH: calloc: -// CHECK-cCRASH: Sanitizer's allocator is terminating the process -// CHECK-coCRASH: calloc-overflow: -// CHECK-coCRASH: Sanitizer's allocator is terminating the process -// CHECK-rCRASH: realloc: -// CHECK-rCRASH: Sanitizer's allocator is terminating the process -// CHECK-mrCRASH: realloc-after-malloc: -// CHECK-mrCRASH: Sanitizer's allocator is terminating the process -// CHECK-nCRASH: new: -// CHECK-nCRASH: Sanitizer's allocator is terminating the process -// CHECK-nnCRASH: new-nothrow: -// CHECK-nnCRASH: Sanitizer's allocator is terminating the process - -// CHECK-mNULL: malloc: -// CHECK-mNULL: errno: 12 -// CHECK-mNULL: x: 0 -// CHECK-cNULL: calloc: -// CHECK-cNULL: errno: 12 -// CHECK-cNULL: x: 0 -// CHECK-coNULL: calloc-overflow: -// CHECK-coNULL: errno: 12 -// CHECK-coNULL: x: 0 -// CHECK-rNULL: realloc: -// CHECK-rNULL: errno: 12 -// CHECK-rNULL: x: 0 -// CHECK-mrNULL: realloc-after-malloc: -// CHECK-mrNULL: errno: 12 -// CHECK-mrNULL: x: 0 -// CHECK-nnNULL: new-nothrow: -// CHECK-nnNULL: x: 0 diff --git a/test/msan/Linux/name_to_handle_at.cc b/test/msan/Linux/name_to_handle_at.cc new file mode 100644 index 000000000000..0ff8d982f4f7 --- /dev/null +++ b/test/msan/Linux/name_to_handle_at.cc @@ -0,0 +1,28 @@ +// RUN: %clangxx_msan -std=c++11 -O0 -g %s -o %t && %run %t + +#include <assert.h> +#include <fcntl.h> +#include <sanitizer/msan_interface.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +int main(void) { + struct file_handle *handle = reinterpret_cast<struct file_handle *>( + malloc(sizeof(*handle) + MAX_HANDLE_SZ)); + handle->handle_bytes = MAX_HANDLE_SZ; + + int mount_id; + int res = name_to_handle_at(AT_FDCWD, "/bin/cat", handle, &mount_id, 0); + assert(!res); + __msan_check_mem_is_initialized(&mount_id, sizeof(mount_id)); + __msan_check_mem_is_initialized(&handle->handle_bytes, + sizeof(handle->handle_bytes)); + __msan_check_mem_is_initialized(&handle->handle_type, + sizeof(handle->handle_type)); + __msan_check_mem_is_initialized(&handle->f_handle, handle->handle_bytes); + + free(handle); + return 0; +} diff --git a/test/msan/Linux/sendmsg.cc b/test/msan/Linux/sendmsg.cc index 4fc6c88cc5dd..91c3f64d7f21 100644 --- a/test/msan/Linux/sendmsg.cc +++ b/test/msan/Linux/sendmsg.cc @@ -1,10 +1,12 @@ // RUN: %clangxx_msan %s -DSEND -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SEND // RUN: %clangxx_msan %s -DSENDTO -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDTO // RUN: %clangxx_msan %s -DSENDMSG -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG +// RUN: %clangxx_msan %s -DSENDMMSG -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMMSG // RUN: %clangxx_msan %s -DSEND -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE // RUN: %clangxx_msan %s -DSENDTO -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE // RUN: %clangxx_msan %s -DSENDMSG -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE +// RUN: %clangxx_msan %s -DSENDMMSG -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE // RUN: %clangxx_msan %s -DSEND -DPOISON -o %t && \ // RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE @@ -12,6 +14,8 @@ // RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE // RUN: %clangxx_msan %s -DSENDMSG -DPOISON -o %t && \ // RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE +// RUN: %clangxx_msan %s -DSENDMMSG -DPOISON -o %t && \ +// RUN: MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE // UNSUPPORTED: android @@ -20,54 +24,32 @@ #include <unistd.h> #include <stdlib.h> #include <string.h> -#include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <sanitizer/msan_interface.h> const int kBufSize = 10; -int sockfd; +const int kRecvBufSize = 100; +int sockfd[2]; int main() { int ret; + int sent; char buf[kBufSize] = {0}; - pthread_t client_thread; - struct sockaddr_in serveraddr; - struct sockaddr_in6 serveraddr6; - - memset(&serveraddr, 0, sizeof(serveraddr)); - serveraddr.sin_family = AF_INET; - serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); - serveraddr.sin_port = 0; - struct sockaddr *addr = (struct sockaddr *)&serveraddr; - socklen_t addrlen = sizeof(serveraddr); - - sockfd = socket(addr->sa_family, SOCK_DGRAM, 0); - if (sockfd <= 0) { - // Try to fall-back to IPv6 - memset(&serveraddr6, 0, sizeof(serveraddr6)); - serveraddr6.sin6_family = AF_INET6; - serveraddr6.sin6_addr = in6addr_any; - serveraddr6.sin6_port = 0; - addr = (struct sockaddr *)&serveraddr6; - addrlen = sizeof(serveraddr6); - - sockfd = socket(addr->sa_family, SOCK_DGRAM, 0); - } - assert(sockfd > 0); - - bind(sockfd, addr, addrlen); - getsockname(sockfd, addr, &addrlen); + char rbuf[kRecvBufSize]; + + ret = socketpair(AF_LOCAL, SOCK_DGRAM, 0, sockfd); + assert(!ret); #if defined(POISON) __msan_poison(buf + 7, 1); #endif -#if defined(SENDMSG) +#if defined(SENDMSG) || defined(SENDMMSG) struct iovec iov[2] = {{buf, 5}, {buf + 5, 5}}; struct msghdr msg; - msg.msg_name = addr; - msg.msg_namelen = addrlen; + msg.msg_name = nullptr; + msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 2; msg.msg_control = 0; @@ -75,20 +57,95 @@ int main() { msg.msg_flags = 0; #endif +#if defined(SENDMMSG) + struct iovec iov0[1] = {{buf, 7}}; + struct msghdr msg0; + msg0.msg_name = nullptr; + msg0.msg_namelen = 0; + msg0.msg_iov = iov0; + msg0.msg_iovlen = 1; + msg0.msg_control = 0; + msg0.msg_controllen = 0; + msg0.msg_flags = 0; + + struct mmsghdr mmsg[2]; + mmsg[0].msg_hdr = msg0; // good + mmsg[1].msg_hdr = msg; // poisoned +#endif + #if defined(SEND) - ret = connect(sockfd, addr, addrlen); - assert(ret == 0); - ret = send(sockfd, buf, kBufSize, 0); + sent = send(sockfd[0], buf, kBufSize, 0); // SEND: Uninitialized bytes in __interceptor_send at offset 7 inside [{{.*}}, 10) - assert(ret > 0); + assert(sent > 0); + + ret = recv(sockfd[1], rbuf, kRecvBufSize, 0); + assert(ret == sent); + assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent); #elif defined(SENDTO) - ret = sendto(sockfd, buf, kBufSize, 0, addr, addrlen); + sent = sendto(sockfd[0], buf, kBufSize, 0, nullptr, 0); // SENDTO: Uninitialized bytes in __interceptor_sendto at offset 7 inside [{{.*}}, 10) - assert(ret > 0); + assert(sent > 0); + + struct sockaddr_storage ss; + socklen_t sslen = sizeof(ss); + ret = recvfrom(sockfd[1], rbuf, kRecvBufSize, 0, (struct sockaddr *)&ss, + &sslen); + assert(ret == sent); + assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent); + assert(__msan_test_shadow(&ss, sizeof(ss)) == sslen); #elif defined(SENDMSG) - ret = sendmsg(sockfd, &msg, 0); + sent = sendmsg(sockfd[0], &msg, 0); // SENDMSG: Uninitialized bytes in {{.*}} at offset 2 inside [{{.*}}, 5) - assert(ret > 0); + assert(sent > 0); + + struct iovec riov[2] = {{rbuf, 3}, {rbuf + 3, kRecvBufSize - 3}}; + struct msghdr rmsg; + rmsg.msg_name = nullptr; + rmsg.msg_namelen = 0; + rmsg.msg_iov = riov; + rmsg.msg_iovlen = 2; + rmsg.msg_control = 0; + rmsg.msg_controllen = 0; + rmsg.msg_flags = 0; + + ret = recvmsg(sockfd[1], &rmsg, 0); + assert(ret == sent); + assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent); +#elif defined(SENDMMSG) + sent = sendmmsg(sockfd[0], mmsg, 2, 0); + // SENDMMSG: Uninitialized bytes in {{.*}} at offset 2 inside [{{.*}}, 5) + assert(sent == 2); + if (ret >= 2) + assert(mmsg[1].msg_len > 0); + + struct iovec riov[2] = {{rbuf + kRecvBufSize / 2, kRecvBufSize / 2}}; + struct msghdr rmsg; + rmsg.msg_name = nullptr; + rmsg.msg_namelen = 0; + rmsg.msg_iov = riov; + rmsg.msg_iovlen = 1; + rmsg.msg_control = 0; + rmsg.msg_controllen = 0; + rmsg.msg_flags = 0; + + struct iovec riov0[2] = {{rbuf, kRecvBufSize / 2}}; + struct msghdr rmsg0; + rmsg0.msg_name = nullptr; + rmsg0.msg_namelen = 0; + rmsg0.msg_iov = riov0; + rmsg0.msg_iovlen = 1; + rmsg0.msg_control = 0; + rmsg0.msg_controllen = 0; + rmsg0.msg_flags = 0; + + struct mmsghdr rmmsg[2]; + rmmsg[0].msg_hdr = rmsg0; + rmmsg[1].msg_hdr = rmsg; + + ret = recvmmsg(sockfd[1], rmmsg, 2, 0, nullptr); + assert(ret == sent); + assert(__msan_test_shadow(rbuf, kRecvBufSize) == 7); + assert(__msan_test_shadow(rbuf + kRecvBufSize / 2, kRecvBufSize / 2) == 10); #endif fprintf(stderr, "== done\n"); // NEGATIVE: == done diff --git a/test/msan/check-handler.cc b/test/msan/check-handler.cc new file mode 100644 index 000000000000..4721f8c3068e --- /dev/null +++ b/test/msan/check-handler.cc @@ -0,0 +1,16 @@ +// RUN: %clangxx_msan -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s + +// Verify that CHECK handler prints a stack on CHECK fail. + +#include <stdlib.h> + +int main(void) { + // Allocate chunk from the secondary allocator to trigger CHECK(IsALigned()) + // in its free() path. + void *p = malloc(8 << 20); + free(reinterpret_cast<char*>(p) + 1); + // CHECK: MemorySanitizer: bad pointer + // CHECK: MemorySanitizer CHECK failed + // CHECK: #0 + return 0; +} diff --git a/test/msan/coverage-levels.cc b/test/msan/coverage-levels.cc index b881cecac7e9..5ca3b717d04f 100644 --- a/test/msan/coverage-levels.cc +++ b/test/msan/coverage-levels.cc @@ -1,14 +1,14 @@ // Test various levels of coverage // // RUN: %clangxx_msan -DINIT_VAR=1 -O1 -fsanitize-coverage=func %s -o %t -// RUN: mkdir -p %T/coverage-levels -// RUN: MSAN_OPTIONS=coverage=1:verbosity=1:coverage_dir=%T/coverage-levels %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN +// RUN: mkdir -p %t-dir +// RUN: MSAN_OPTIONS=coverage=1:verbosity=1:coverage_dir=%t-dir %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN // RUN: %clangxx_msan -O1 -fsanitize-coverage=func %s -o %t -// RUN: MSAN_OPTIONS=coverage=1:verbosity=1:coverage_dir=%T/coverage-levels not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_WARN +// RUN: MSAN_OPTIONS=coverage=1:verbosity=1:coverage_dir=%t-dir not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_WARN // RUN: %clangxx_msan -O1 -fsanitize-coverage=bb %s -o %t -// RUN: MSAN_OPTIONS=coverage=1:verbosity=1:coverage_dir=%T/coverage-levels not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 --check-prefix=CHECK_WARN +// RUN: MSAN_OPTIONS=coverage=1:verbosity=1:coverage_dir=%t-dir not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 --check-prefix=CHECK_WARN // RUN: %clangxx_msan -O1 -fsanitize-coverage=edge %s -o %t -// RUN: MSAN_OPTIONS=coverage=1:verbosity=1:coverage_dir=%T/coverage-levels not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN +// RUN: MSAN_OPTIONS=coverage=1:verbosity=1:coverage_dir=%t-dir not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN volatile int sink; int main(int argc, char **argv) { diff --git a/test/msan/dtls_test.c b/test/msan/dtls_test.c index 49d95c44c1d8..b9021e0da1af 100644 --- a/test/msan/dtls_test.c +++ b/test/msan/dtls_test.c @@ -5,6 +5,9 @@ Regression test for a bug in msan/glibc integration, see https://sourceware.org/bugzilla/show_bug.cgi?id=16291 and https://github.com/google/sanitizers/issues/547 + + XFAIL: FreeBSD + UNSUPPORTED: powerpc */ #ifndef BUILD_SO diff --git a/test/msan/dtor-member.cc b/test/msan/dtor-member.cc index 13a059947bca..bf20221a363b 100644 --- a/test/msan/dtor-member.cc +++ b/test/msan/dtor-member.cc @@ -7,7 +7,7 @@ // RUN: %clangxx_msan %s -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t >%t.out 2>&1 // RUN: FileCheck %s < %t.out -// RUN: %clangxx_msan %s -fsanitize=memory -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t >%t.out 2>&1 +// RUN: %clangxx_msan %s -fsanitize=memory -fno-sanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 %run %t >%t.out 2>&1 // RUN: FileCheck %s --check-prefix=CHECK-NO-FLAG < %t.out // RUN: %clangxx_msan -fsanitize=memory -fsanitize-memory-use-after-dtor %s -o %t && MSAN_OPTIONS=poison_in_dtor=0 %run %t >%t.out 2>&1 diff --git a/test/msan/fgets_fputs.cc b/test/msan/fgets_fputs.cc new file mode 100644 index 000000000000..1e96943980d6 --- /dev/null +++ b/test/msan/fgets_fputs.cc @@ -0,0 +1,47 @@ +// RUN: %clangxx_msan -g %s -o %t +// RUN: %run %t +// RUN: not %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-FPUTS +// RUN: not %run %t 3 3 2>&1 | FileCheck %s --check-prefix=CHECK-PUTS + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int test_fgets() { + FILE *fp = fopen("/dev/zero", "r"); + char c; + + if (!fgets(&c, 1, fp)) + return 1; + + if (c == '1') // No error + return 2; + + fclose(fp); + return 0; +} + +int test_fputs() { + FILE *fp = fopen("/dev/null", "w"); + char buf[2]; + fputs(buf, fp); // BOOM + return fclose(fp); +} + +void test_puts() { + char buf[2]; + puts(buf); // BOOM +} + +int main(int argc, char *argv[]) { + if (argc == 1) + test_fgets(); + else if (argc == 2) + test_fputs(); + else + test_puts(); + return 0; +} + +// CHECK-FPUTS: Uninitialized bytes in __interceptor_fputs at offset 0 inside +// CHECK-PUTS: Uninitialized bytes in __interceptor_puts at offset 0 inside diff --git a/test/msan/fstat.cc b/test/msan/fstat.cc new file mode 100644 index 000000000000..83f97054cea7 --- /dev/null +++ b/test/msan/fstat.cc @@ -0,0 +1,15 @@ +// RUN: %clangxx_msan -O0 %s -o %t && %run %t + +#include <sys/stat.h> +#include <stdlib.h> + +int main(void) { + struct stat st; + if (fstat(0, &st)) + exit(1); + + if (S_ISBLK(st.st_mode)) + exit(0); + + return 0; +} diff --git a/test/msan/getutent.cc b/test/msan/getutent.cc index 36f9e1f1f7e3..b57101068ddd 100644 --- a/test/msan/getutent.cc +++ b/test/msan/getutent.cc @@ -1,14 +1,18 @@ // RUN: %clangxx_msan -O0 -g %s -o %t && %run %t +#ifndef __FreeBSD__ #include <utmp.h> +#endif #include <utmpx.h> #include <sanitizer/msan_interface.h> int main(void) { +#ifndef __FreeBSD__ setutent(); while (struct utmp *ut = getutent()) __msan_check_mem_is_initialized(ut, sizeof(*ut)); endutent(); +#endif setutxent(); while (struct utmpx *utx = getutxent()) diff --git a/test/msan/iconv.cc b/test/msan/iconv.cc index 7beb6a01877c..7713cb8e5f45 100644 --- a/test/msan/iconv.cc +++ b/test/msan/iconv.cc @@ -15,7 +15,7 @@ int main(void) { char inbuf_[100]; strcpy(inbuf_, "sample text"); char outbuf_[100]; -#if defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__NetBSD__) // Some OSes expect the 2nd argument of iconv(3) to be of type const char ** const char *inbuf = inbuf_; #else diff --git a/test/msan/lit.cfg b/test/msan/lit.cfg index cac260999877..550d04d0812b 100644 --- a/test/msan/lit.cfg +++ b/test/msan/lit.cfg @@ -29,7 +29,7 @@ config.substitutions.append( ("%clangxx_msan ", build_invocation(clang_msan_cxxf # Default test suffixes. config.suffixes = ['.c', '.cc', '.cpp'] -if config.host_os not in ['Linux', 'NetBSD']: +if config.host_os not in ['Linux', 'NetBSD', 'FreeBSD']: config.unsupported = True # For mips64, mips64el we have forced store_context_size to 1 because these diff --git a/test/msan/mmap.cc b/test/msan/mmap.cc index 65d8beeefe3a..d83423735211 100644 --- a/test/msan/mmap.cc +++ b/test/msan/mmap.cc @@ -63,9 +63,13 @@ int main() { const size_t kMapSize = 0x1000000000ULL; #endif int success_count = 0; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; +#if defined(MAP_NORESERVE) + flags |= MAP_NORESERVE; +#endif while (true) { void *p = mmap(0, kMapSize, PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); + flags, -1, 0); printf("%p\n", p); if (p == MAP_FAILED) { assert(errno == ENOMEM); diff --git a/test/msan/pthread_getattr_np_deadlock.cc b/test/msan/pthread_getattr_np_deadlock.cc index 0f52280856cc..241caa2a211d 100644 --- a/test/msan/pthread_getattr_np_deadlock.cc +++ b/test/msan/pthread_getattr_np_deadlock.cc @@ -4,10 +4,20 @@ #include <assert.h> #include <pthread.h> +#if defined(__FreeBSD__) +#include <pthread_np.h> +#endif void *ThreadFn(void *) { pthread_attr_t attr; +#if defined(__FreeBSD__) + // On FreeBSD it needs to allocate attr underlying memory + int res = pthread_attr_init(&attr); + assert(!res); + res = pthread_attr_get_np(pthread_self(), &attr); +#else int res = pthread_getattr_np(pthread_self(), &attr); +#endif assert(!res); return 0; } diff --git a/test/msan/pthread_getname_np.cc b/test/msan/pthread_getname_np.cc index ca27d8b6fd6c..e19b652a73c9 100644 --- a/test/msan/pthread_getname_np.cc +++ b/test/msan/pthread_getname_np.cc @@ -1,5 +1,7 @@ // RUN: %clangxx_msan -std=c++11 -O0 %s -o %t && %run %t -// UNSUPPORTED: android, netbsd +// The main goal is getting the pthread name back and +// FreeBSD based do not support this feature +// UNSUPPORTED: android, netbsd, freebsd // Regression test for a deadlock in pthread_getattr_np @@ -10,12 +12,22 @@ #include <stdio.h> +// Stall child thread on this lock to make sure it doesn't finish +// before the end of the pthread_getname_np() / pthread_setname_np() tests. +static pthread_mutex_t lock; + void *ThreadFn(void *) { + pthread_mutex_lock (&lock); + pthread_mutex_unlock (&lock); return nullptr; } int main(void) { pthread_t t; + + pthread_mutex_init (&lock, NULL); + pthread_mutex_lock (&lock); + int res = pthread_create(&t, 0, ThreadFn, 0); assert(!res); @@ -28,6 +40,8 @@ int main(void) { assert(!res); assert(strcmp(buf, kMyThreadName) == 0); + pthread_mutex_unlock (&lock); + res = pthread_join(t, 0); assert(!res); return 0; diff --git a/test/msan/pvalloc.cc b/test/msan/pvalloc.cc deleted file mode 100644 index 7c406df79bb1..000000000000 --- a/test/msan/pvalloc.cc +++ /dev/null @@ -1,43 +0,0 @@ -// RUN: %clangxx_msan -O0 %s -o %t -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t m1 2>&1 | FileCheck %s -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t m1 2>&1 -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t psm1 2>&1 | FileCheck %s -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t psm1 2>&1 - -// UNSUPPORTED: win32, freebsd, netbsd - -// Checks that pvalloc overflows are caught. If the allocator is allowed to -// return null, the errno should be set to ENOMEM. - -#include <assert.h> -#include <errno.h> -#include <malloc.h> -#include <stdint.h> -#include <string.h> -#include <unistd.h> - -int main(int argc, char *argv[]) { - void *p; - size_t page_size; - - assert(argc == 2); - - page_size = sysconf(_SC_PAGESIZE); - // Check that the page size is a power of two. - assert((page_size & (page_size - 1)) == 0); - - if (!strcmp(argv[1], "m1")) { - p = pvalloc((uintptr_t)-1); - assert(!p); - assert(errno == ENOMEM); - } - if (!strcmp(argv[1], "psm1")) { - p = pvalloc((uintptr_t)-(page_size - 1)); - assert(!p); - assert(errno == ENOMEM); - } - - return 0; -} - -// CHECK: MemorySanitizer's allocator is terminating the process diff --git a/test/msan/scoped-interceptors.cc b/test/msan/scoped-interceptors.cc new file mode 100644 index 000000000000..fc7d4578482b --- /dev/null +++ b/test/msan/scoped-interceptors.cc @@ -0,0 +1,52 @@ +// RUN: %clangxx_msan %s -o %t +// RUN: %run %t --disable-checks 0 2>&1 | FileCheck --check-prefix=DISABLED --allow-empty %s +// RUN: %run %t --disable-checks 1 2>&1 | FileCheck --check-prefix=DISABLED --allow-empty %s +// RUN: %run %t --disable-checks 2 2>&1 | FileCheck --check-prefix=DISABLED --allow-empty %s +// RUN: %run %t --disable-checks 3 2>&1 | FileCheck --check-prefix=DISABLED --allow-empty %s +// RUN: not %run %t --reenable-checks 0 2>&1 | FileCheck --check-prefix=CASE-0 %s +// RUN: not %run %t --reenable-checks 1 2>&1 | FileCheck --check-prefix=CASE-1 %s +// RUN: not %run %t --reenable-checks 2 2>&1 | FileCheck --check-prefix=CASE-2 %s +// RUN: not %run %t --reenable-checks 3 2>&1 | FileCheck --check-prefix=CASE-3 %s + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sanitizer/msan_interface.h> + +int main(int argc, char *argv[]) { + assert(argc == 3); + __msan_scoped_disable_interceptor_checks(); + if (strcmp(argv[1], "--reenable-checks") == 0) + __msan_scoped_enable_interceptor_checks(); + + char uninit[7]; + switch (argv[2][0]) { + case '0': { + char *copy = strndup(uninit, sizeof(uninit)); // BOOM + free(copy); + break; + // CASE-0: Uninitialized bytes in __interceptor_strndup + } + case '1': { + puts(uninit); // BOOM + puts(uninit); // Ensure previous call did not enable interceptor checks. + break; + // CASE-1: Uninitialized bytes in __interceptor_puts + } + case '2': { + int cmp = memcmp(uninit, uninit, sizeof(uninit)); // BOOM + break; + // CASE-2: Uninitialized bytes in __interceptor_memcmp + } + case '3': { + size_t len = strlen(uninit); // BOOM + break; + // CASE-3: Uninitialized bytes in __interceptor_strlen + } + default: assert(0); + } + // DISABLED-NOT: Uninitialized bytes + return 0; +} + diff --git a/test/msan/strlen_of_shadow.cc b/test/msan/strlen_of_shadow.cc index b9cf5f065d2d..718cc08dc1fd 100644 --- a/test/msan/strlen_of_shadow.cc +++ b/test/msan/strlen_of_shadow.cc @@ -2,6 +2,8 @@ // Check that strlen() and similar intercepted functions can be called on shadow // memory. +// The mem_to_shadow's part might need rework +// XFAIL: freebsd #include <assert.h> #include <stdint.h> diff --git a/test/msan/textdomain.cc b/test/msan/textdomain.cc index 760debd68c33..478b0993f837 100644 --- a/test/msan/textdomain.cc +++ b/test/msan/textdomain.cc @@ -1,4 +1,6 @@ // RUN: %clangxx_msan -O0 -g %s -o %t && %run %t +// textdomain() is not a part of libc on FreeBSD and NetBSD. +// UNSUPPORTED: netbsd, freebsd #include <libintl.h> #include <stdio.h> diff --git a/test/msan/tls_reuse.cc b/test/msan/tls_reuse.cc index 78a328fa3ce0..9c2ee975cb57 100644 --- a/test/msan/tls_reuse.cc +++ b/test/msan/tls_reuse.cc @@ -1,6 +1,7 @@ // RUN: %clangxx_msan -O0 %s -o %t && %run %t // Check that when TLS block is reused between threads, its shadow is cleaned. +// XFAIL: freebsd #include <pthread.h> #include <stdio.h> diff --git a/test/msan/tsearch.cc b/test/msan/tsearch.cc index 0d8ee8f35b25..50a2efb31fad 100644 --- a/test/msan/tsearch.cc +++ b/test/msan/tsearch.cc @@ -1,7 +1,7 @@ // RUN: %clangxx_msan -O0 -g %s -o %t && %run %t // tdestroy is a GNU extension -// UNSUPPORTED: netbsd +// UNSUPPORTED: netbsd, freebsd #include <assert.h> #include <search.h> diff --git a/test/msan/tzset.cc b/test/msan/tzset.cc index 05915e047e15..86805cd56c5d 100644 --- a/test/msan/tzset.cc +++ b/test/msan/tzset.cc @@ -1,4 +1,5 @@ // RUN: %clangxx_msan -O0 %s -o %t && %run %t +// XFAIL: freebsd #include <stdlib.h> #include <string.h> diff --git a/test/msan/use-after-dtor.cc b/test/msan/use-after-dtor.cc index 6c751a14f377..45f4dcd69b78 100644 --- a/test/msan/use-after-dtor.cc +++ b/test/msan/use-after-dtor.cc @@ -1,14 +1,17 @@ // RUN: %clangxx_msan %s -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t >%t.out 2>&1 -// RUN: FileCheck %s < %t.out +// RUN: FileCheck %s --check-prefix=CHECK-UAD < %t.out // RUN: %clangxx_msan %s -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t >%t.out 2>&1 -// RUN: FileCheck %s < %t.out +// RUN: FileCheck %s --check-prefix=CHECK-UAD < %t.out // RUN: %clangxx_msan %s -O2 -fsanitize=memory -fsanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t >%t.out 2>&1 -// RUN: FileCheck %s < %t.out +// RUN: FileCheck %s --check-prefix=CHECK-UAD < %t.out // RUN: %clangxx_msan %s -O1 -fsanitize=memory -fsanitize-memory-use-after-dtor -fsanitize-memory-track-origins -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t >%t.out 2>&1 -// RUN: FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out +// RUN: FileCheck %s --check-prefixes=CHECK-UAD,CHECK-ORIGINS < %t.out + +// RUN: %clangxx_msan %s -fno-sanitize-memory-use-after-dtor -o %t && MSAN_OPTIONS=poison_in_dtor=1 not %run %t > %t.out 2>&1 +// RUN: FileCheck %s --check-prefix=CHECK-UAD-OFF < %t.out #include <sanitizer/msan_interface.h> #include <assert.h> @@ -32,14 +35,16 @@ int main() { Simple *s = new(&buf) Simple(); s->~Simple(); + fprintf(stderr, "\n"); // Need output to parse for CHECK-UAD-OFF case return s->x_; - // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value - // CHECK: {{#0 0x.* in main.*use-after-dtor.cc:}}[[@LINE-3]] + // CHECK-UAD: WARNING: MemorySanitizer: use-of-uninitialized-value + // CHECK-UAD: {{#0 0x.* in main.*use-after-dtor.cc:}}[[@LINE-3]] // CHECK-ORIGINS: Memory was marked as uninitialized // CHECK-ORIGINS: {{#0 0x.* in __sanitizer_dtor_callback}} // CHECK-ORIGINS: {{#1 0x.* in Simple::~Simple}} - // CHECK: SUMMARY: MemorySanitizer: use-of-uninitialized-value {{.*main}} + // CHECK-UAD: SUMMARY: MemorySanitizer: use-of-uninitialized-value {{.*main}} + // CHECK-UAD-OFF-NOT: SUMMARY: MemorySanitizer: use-of-uninitialized-value } diff --git a/test/msan/vector_div.cc b/test/msan/vector_div.cc new file mode 100644 index 000000000000..4ca2369d63e6 --- /dev/null +++ b/test/msan/vector_div.cc @@ -0,0 +1,17 @@ +// Regression test for https://bugs.llvm.org/show_bug.cgi?id=37523 + +// RUN: %clangxx_msan -O0 %s -o %t && %run %t +// RUN: %clangxx_msan -O3 %s -o %t && %run %t +// REQUIRES: x86_64-target-arch + +#include <assert.h> +#include <emmintrin.h> + +int main() { + volatile int scale = 5; + volatile auto zz = _mm_div_ps(_mm_set1_ps(255), _mm_set1_ps(scale)); + assert(zz[0] == 51); + assert(zz[1] == 51); + assert(zz[2] == 51); + assert(zz[3] == 51); +} diff --git a/test/msan/wcsxfrm.cc b/test/msan/wcsxfrm.cc new file mode 100644 index 000000000000..f13c5d3969a8 --- /dev/null +++ b/test/msan/wcsxfrm.cc @@ -0,0 +1,30 @@ +// RUN: %clangxx_msan -O0 -g %s -o %t && not %run %t + +#include <assert.h> +#include <locale.h> +#include <sanitizer/msan_interface.h> +#include <stdlib.h> +#include <wchar.h> + +int main(void) { + wchar_t q[10]; + size_t n = wcsxfrm(q, L"abcdef", sizeof(q) / sizeof(wchar_t)); + assert(n < sizeof(q)); + __msan_check_mem_is_initialized(q, (n + 1) * sizeof(wchar_t)); + + locale_t loc = newlocale(LC_ALL_MASK, "", (locale_t)0); + + __msan_poison(&q, sizeof(q)); + n = wcsxfrm_l(q, L"qwerty", sizeof(q) / sizeof(wchar_t), loc); + assert(n < sizeof(q)); + __msan_check_mem_is_initialized(q, (n + 1) * sizeof(wchar_t)); + + q[0] = 'A'; + q[1] = '\x00'; + __msan_poison(&q, sizeof(q)); + wcsxfrm(NULL, q, 0); + + // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value + // CHECK: in main {{.*}}wcsxfrm.cc:25 + return 0; +} diff --git a/test/profile/Inputs/instrprof-dlopen-dlclose-main.c b/test/profile/Inputs/instrprof-dlopen-dlclose-main.c new file mode 100644 index 000000000000..3f4a4f6cc6a6 --- /dev/null +++ b/test/profile/Inputs/instrprof-dlopen-dlclose-main.c @@ -0,0 +1,86 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +int main(int argc, char *argv[]) { + dlerror(); + void *f1_handle = dlopen("func.shared", RTLD_LAZY | RTLD_GLOBAL); + if (f1_handle == NULL) { + fprintf(stderr, "unable to open 'func.shared': %s\n", dlerror()); + return EXIT_FAILURE; + } + + void (*func)(void) = (void (*)(void))dlsym(f1_handle, "func"); + if (func == NULL) { + fprintf(stderr, "unable to lookup symbol 'func': %s\n", dlerror()); + return EXIT_FAILURE; + } + + dlerror(); + void *f2_handle = dlopen("func2.shared", RTLD_LAZY | RTLD_GLOBAL); + if (f2_handle == NULL) { + fprintf(stderr, "unable to open 'func2.shared': %s\n", dlerror()); + return EXIT_FAILURE; + } + + void (*func2)(void) = (void (*)(void))dlsym(f2_handle, "func2"); + if (func2 == NULL) { + fprintf(stderr, "unable to lookup symbol 'func2': %s\n", dlerror()); + return EXIT_FAILURE; + } + func2(); + +#ifdef USE_LIB3 + void *f3_handle = dlopen("func3.shared", RTLD_LAZY | RTLD_GLOBAL); + if (f3_handle == NULL) { + fprintf(stderr, "unable to open 'func3.shared': %s\n", dlerror()); + return EXIT_FAILURE; + } + + void (*func3)(void) = (void (*)(void))dlsym(f3_handle, "func3"); + if (func3 == NULL) { + fprintf(stderr, "unable to lookup symbol 'func3': %s\n", dlerror()); + return EXIT_FAILURE; + } + func3(); +#endif + + dlerror(); + void (*gcov_flush1)() = (void (*)())dlsym(f1_handle, "__gcov_flush"); + if (gcov_flush1 == NULL) { + fprintf(stderr, "unable to find __gcov_flush in func.shared': %s\n", dlerror()); + return EXIT_FAILURE; + } + + dlerror(); + void (*gcov_flush2)() = (void (*)())dlsym(f2_handle, "__gcov_flush"); + if (gcov_flush2 == NULL) { + fprintf(stderr, "unable to find __gcov_flush in func2.shared': %s\n", dlerror()); + return EXIT_FAILURE; + } + + if (gcov_flush1 == gcov_flush2) { + fprintf(stderr, "Same __gcov_flush found in func.shared and func2.shared\n"); + return EXIT_FAILURE; + } + + dlerror(); + if (dlclose(f2_handle) != 0) { + fprintf(stderr, "unable to close 'func2.shared': %s\n", dlerror()); + return EXIT_FAILURE; + } + + func(); + + int g1 = 0; + int g2 = 0; + int n = 10; + + if (n % 5 == 0) + g1++; + else + g2++; + + return EXIT_SUCCESS; +} + diff --git a/test/profile/Inputs/instrprof-dlopen-dlclose-main.c.gcov b/test/profile/Inputs/instrprof-dlopen-dlclose-main.c.gcov new file mode 100644 index 000000000000..acb2076fd763 --- /dev/null +++ b/test/profile/Inputs/instrprof-dlopen-dlclose-main.c.gcov @@ -0,0 +1,91 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-dlopen-dlclose-main.c +// CHECK-NEXT: -: 0:Graph:instrprof-dlopen-dlclose-main.gcno +// CHECK-NEXT: -: 0:Data:instrprof-dlopen-dlclose-main.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:#include <dlfcn.h> +// CHECK-NEXT: -: 2:#include <stdio.h> +// CHECK-NEXT: -: 3:#include <stdlib.h> +// CHECK-NEXT: -: 4: +// CHECK-NEXT: -: 5:int main(int argc, char *argv[]) { +// CHECK-NEXT: 1: 6: dlerror(); +// CHECK-NEXT: 1: 7: void *f1_handle = dlopen("func.shared", RTLD_LAZY | RTLD_GLOBAL); +// CHECK-NEXT: 1: 8: if (f1_handle == NULL) { +// CHECK-NEXT: #####: 9: fprintf(stderr, "unable to open 'func.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 10: return EXIT_FAILURE; +// CHECK-NEXT: -: 11: } +// CHECK-NEXT: -: 12: +// CHECK-NEXT: 1: 13: void (*func)(void) = (void (*)(void))dlsym(f1_handle, "func"); +// CHECK-NEXT: 1: 14: if (func == NULL) { +// CHECK-NEXT: #####: 15: fprintf(stderr, "unable to lookup symbol 'func': %s\n", dlerror()); +// CHECK-NEXT: #####: 16: return EXIT_FAILURE; +// CHECK-NEXT: -: 17: } +// CHECK-NEXT: -: 18: +// CHECK-NEXT: 1: 19: dlerror(); +// CHECK-NEXT: 1: 20: void *f2_handle = dlopen("func2.shared", RTLD_LAZY | RTLD_GLOBAL); +// CHECK-NEXT: 1: 21: if (f2_handle == NULL) { +// CHECK-NEXT: #####: 22: fprintf(stderr, "unable to open 'func2.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 23: return EXIT_FAILURE; +// CHECK-NEXT: -: 24: } +// CHECK-NEXT: -: 25: +// CHECK-NEXT: 1: 26: void (*func2)(void) = (void (*)(void))dlsym(f2_handle, "func2"); +// CHECK-NEXT: 1: 27: if (func2 == NULL) { +// CHECK-NEXT: #####: 28: fprintf(stderr, "unable to lookup symbol 'func2': %s\n", dlerror()); +// CHECK-NEXT: #####: 29: return EXIT_FAILURE; +// CHECK-NEXT: -: 30: } +// CHECK-NEXT: 1: 31: func2(); +// CHECK-NEXT: -: 32: +// CHECK-NEXT: -: 33:#ifdef USE_LIB3 +// CHECK-NEXT: -: 34: void *f3_handle = dlopen("func3.shared", RTLD_LAZY | RTLD_GLOBAL); +// CHECK-NEXT: -: 35: if (f3_handle == NULL) { +// CHECK-NEXT: -: 36: fprintf(stderr, "unable to open 'func3.shared': %s\n", dlerror()); +// CHECK-NEXT: -: 37: return EXIT_FAILURE; +// CHECK-NEXT: -: 38: } +// CHECK-NEXT: -: 39: +// CHECK-NEXT: -: 40: void (*func3)(void) = (void (*)(void))dlsym(f3_handle, "func3"); +// CHECK-NEXT: -: 41: if (func3 == NULL) { +// CHECK-NEXT: -: 42: fprintf(stderr, "unable to lookup symbol 'func3': %s\n", dlerror()); +// CHECK-NEXT: -: 43: return EXIT_FAILURE; +// CHECK-NEXT: -: 44: } +// CHECK-NEXT: -: 45: func3(); +// CHECK-NEXT: -: 46:#endif +// CHECK-NEXT: -: 47: +// CHECK-NEXT: 1: 48: dlerror(); +// CHECK-NEXT: 1: 49: void (*gcov_flush1)() = (void (*)())dlsym(f1_handle, "__gcov_flush"); +// CHECK-NEXT: 1: 50: if (gcov_flush1 == NULL) { +// CHECK-NEXT: #####: 51: fprintf(stderr, "unable to find __gcov_flush in func.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 52: return EXIT_FAILURE; +// CHECK-NEXT: -: 53: } +// CHECK-NEXT: -: 54: +// CHECK-NEXT: 1: 55: dlerror(); +// CHECK-NEXT: 1: 56: void (*gcov_flush2)() = (void (*)())dlsym(f2_handle, "__gcov_flush"); +// CHECK-NEXT: 1: 57: if (gcov_flush2 == NULL) { +// CHECK-NEXT: #####: 58: fprintf(stderr, "unable to find __gcov_flush in func2.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 59: return EXIT_FAILURE; +// CHECK-NEXT: -: 60: } +// CHECK-NEXT: -: 61: +// CHECK-NEXT: 1: 62: if (gcov_flush1 == gcov_flush2) { +// CHECK-NEXT: #####: 63: fprintf(stderr, "Same __gcov_flush found in func.shared and func2.shared\n"); +// CHECK-NEXT: #####: 64: return EXIT_FAILURE; +// CHECK-NEXT: -: 65: } +// CHECK-NEXT: -: 66: +// CHECK-NEXT: 1: 67: dlerror(); +// CHECK-NEXT: 1: 68: if (dlclose(f2_handle) != 0) { +// CHECK-NEXT: #####: 69: fprintf(stderr, "unable to close 'func2.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 70: return EXIT_FAILURE; +// CHECK-NEXT: -: 71: } +// CHECK-NEXT: -: 72: +// CHECK-NEXT: 1: 73: func(); +// CHECK-NEXT: -: 74: +// CHECK-NEXT: 1: 75: int g1 = 0; +// CHECK-NEXT: 1: 76: int g2 = 0; +// CHECK-NEXT: 1: 77: int n = 10; +// CHECK-NEXT: -: 78: +// CHECK-NEXT: 1: 79: if (n % 5 == 0) +// CHECK-NEXT: 1: 80: g1++; +// CHECK-NEXT: -: 81: else +// CHECK-NEXT: #####: 82: g2++; +// CHECK-NEXT: -: 83: +// CHECK-NEXT: 1: 84: return EXIT_SUCCESS; +// CHECK-NEXT: 1: 85:} +// CHECK-NEXT: -: 86: diff --git a/test/profile/Inputs/instrprof-dlopen-dlclose-main_three-libs.c.gcov b/test/profile/Inputs/instrprof-dlopen-dlclose-main_three-libs.c.gcov new file mode 100644 index 000000000000..97eef4c3b905 --- /dev/null +++ b/test/profile/Inputs/instrprof-dlopen-dlclose-main_three-libs.c.gcov @@ -0,0 +1,91 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-dlopen-dlclose-main.c +// CHECK-NEXT: -: 0:Graph:instrprof-dlopen-dlclose-main.gcno +// CHECK-NEXT: -: 0:Data:instrprof-dlopen-dlclose-main.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:#include <dlfcn.h> +// CHECK-NEXT: -: 2:#include <stdio.h> +// CHECK-NEXT: -: 3:#include <stdlib.h> +// CHECK-NEXT: -: 4: +// CHECK-NEXT: -: 5:int main(int argc, char *argv[]) { +// CHECK-NEXT: 1: 6: dlerror(); +// CHECK-NEXT: 1: 7: void *f1_handle = dlopen("func.shared", RTLD_LAZY | RTLD_GLOBAL); +// CHECK-NEXT: 1: 8: if (f1_handle == NULL) { +// CHECK-NEXT: #####: 9: fprintf(stderr, "unable to open 'func.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 10: return EXIT_FAILURE; +// CHECK-NEXT: -: 11: } +// CHECK-NEXT: -: 12: +// CHECK-NEXT: 1: 13: void (*func)(void) = (void (*)(void))dlsym(f1_handle, "func"); +// CHECK-NEXT: 1: 14: if (func == NULL) { +// CHECK-NEXT: #####: 15: fprintf(stderr, "unable to lookup symbol 'func': %s\n", dlerror()); +// CHECK-NEXT: #####: 16: return EXIT_FAILURE; +// CHECK-NEXT: -: 17: } +// CHECK-NEXT: -: 18: +// CHECK-NEXT: 1: 19: dlerror(); +// CHECK-NEXT: 1: 20: void *f2_handle = dlopen("func2.shared", RTLD_LAZY | RTLD_GLOBAL); +// CHECK-NEXT: 1: 21: if (f2_handle == NULL) { +// CHECK-NEXT: #####: 22: fprintf(stderr, "unable to open 'func2.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 23: return EXIT_FAILURE; +// CHECK-NEXT: -: 24: } +// CHECK-NEXT: -: 25: +// CHECK-NEXT: 1: 26: void (*func2)(void) = (void (*)(void))dlsym(f2_handle, "func2"); +// CHECK-NEXT: 1: 27: if (func2 == NULL) { +// CHECK-NEXT: #####: 28: fprintf(stderr, "unable to lookup symbol 'func2': %s\n", dlerror()); +// CHECK-NEXT: #####: 29: return EXIT_FAILURE; +// CHECK-NEXT: -: 30: } +// CHECK-NEXT: 1: 31: func2(); +// CHECK-NEXT: -: 32: +// CHECK-NEXT: -: 33:#ifdef USE_LIB3 +// CHECK-NEXT: 1: 34: void *f3_handle = dlopen("func3.shared", RTLD_LAZY | RTLD_GLOBAL); +// CHECK-NEXT: 1: 35: if (f3_handle == NULL) { +// CHECK-NEXT: #####: 36: fprintf(stderr, "unable to open 'func3.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 37: return EXIT_FAILURE; +// CHECK-NEXT: -: 38: } +// CHECK-NEXT: -: 39: +// CHECK-NEXT: 1: 40: void (*func3)(void) = (void (*)(void))dlsym(f3_handle, "func3"); +// CHECK-NEXT: 1: 41: if (func3 == NULL) { +// CHECK-NEXT: #####: 42: fprintf(stderr, "unable to lookup symbol 'func3': %s\n", dlerror()); +// CHECK-NEXT: #####: 43: return EXIT_FAILURE; +// CHECK-NEXT: -: 44: } +// CHECK-NEXT: 1: 45: func3(); +// CHECK-NEXT: -: 46:#endif +// CHECK-NEXT: -: 47: +// CHECK-NEXT: 1: 48: dlerror(); +// CHECK-NEXT: 1: 49: void (*gcov_flush1)() = (void (*)())dlsym(f1_handle, "__gcov_flush"); +// CHECK-NEXT: 1: 50: if (gcov_flush1 == NULL) { +// CHECK-NEXT: #####: 51: fprintf(stderr, "unable to find __gcov_flush in func.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 52: return EXIT_FAILURE; +// CHECK-NEXT: -: 53: } +// CHECK-NEXT: -: 54: +// CHECK-NEXT: 1: 55: dlerror(); +// CHECK-NEXT: 1: 56: void (*gcov_flush2)() = (void (*)())dlsym(f2_handle, "__gcov_flush"); +// CHECK-NEXT: 1: 57: if (gcov_flush2 == NULL) { +// CHECK-NEXT: #####: 58: fprintf(stderr, "unable to find __gcov_flush in func2.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 59: return EXIT_FAILURE; +// CHECK-NEXT: -: 60: } +// CHECK-NEXT: -: 61: +// CHECK-NEXT: 1: 62: if (gcov_flush1 == gcov_flush2) { +// CHECK-NEXT: #####: 63: fprintf(stderr, "Same __gcov_flush found in func.shared and func2.shared\n"); +// CHECK-NEXT: #####: 64: return EXIT_FAILURE; +// CHECK-NEXT: -: 65: } +// CHECK-NEXT: -: 66: +// CHECK-NEXT: 1: 67: dlerror(); +// CHECK-NEXT: 1: 68: if (dlclose(f2_handle) != 0) { +// CHECK-NEXT: #####: 69: fprintf(stderr, "unable to close 'func2.shared': %s\n", dlerror()); +// CHECK-NEXT: #####: 70: return EXIT_FAILURE; +// CHECK-NEXT: -: 71: } +// CHECK-NEXT: -: 72: +// CHECK-NEXT: 1: 73: func(); +// CHECK-NEXT: -: 74: +// CHECK-NEXT: 1: 75: int g1 = 0; +// CHECK-NEXT: 1: 76: int g2 = 0; +// CHECK-NEXT: 1: 77: int n = 10; +// CHECK-NEXT: -: 78: +// CHECK-NEXT: 1: 79: if (n % 5 == 0) +// CHECK-NEXT: 1: 80: g1++; +// CHECK-NEXT: -: 81: else +// CHECK-NEXT: #####: 82: g2++; +// CHECK-NEXT: -: 83: +// CHECK-NEXT: 1: 84: return EXIT_SUCCESS; +// CHECK-NEXT: 1: 85:} +// CHECK-NEXT: -: 86: diff --git a/test/profile/Inputs/instrprof-dlopen-func.c b/test/profile/Inputs/instrprof-dlopen-func.c index f2de3883535a..9a56e4976570 100644 --- a/test/profile/Inputs/instrprof-dlopen-func.c +++ b/test/profile/Inputs/instrprof-dlopen-func.c @@ -1 +1 @@ -void func(int K) { if (K) {} } +void func(int K) {} diff --git a/test/profile/Inputs/instrprof-dlopen-func.c.gcov b/test/profile/Inputs/instrprof-dlopen-func.c.gcov new file mode 100644 index 000000000000..3af4ec94a1b0 --- /dev/null +++ b/test/profile/Inputs/instrprof-dlopen-func.c.gcov @@ -0,0 +1,6 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-dlopen-func.c +// CHECK-NEXT: -: 0:Graph:instrprof-dlopen-func.gcno +// CHECK-NEXT: -: 0:Data:instrprof-dlopen-func.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: 1: 1:void func(int K) {} diff --git a/test/profile/Inputs/instrprof-dlopen-func2.c b/test/profile/Inputs/instrprof-dlopen-func2.c index d4d93dc0b256..ab62f14952c7 100644 --- a/test/profile/Inputs/instrprof-dlopen-func2.c +++ b/test/profile/Inputs/instrprof-dlopen-func2.c @@ -1 +1 @@ -void func2(int K) { if (K) {} } +void func2(int K) {} diff --git a/test/profile/Inputs/instrprof-dlopen-func2.c.gcov b/test/profile/Inputs/instrprof-dlopen-func2.c.gcov new file mode 100644 index 000000000000..7101f74b938d --- /dev/null +++ b/test/profile/Inputs/instrprof-dlopen-func2.c.gcov @@ -0,0 +1,6 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-dlopen-func2.c +// CHECK-NEXT: -: 0:Graph:instrprof-dlopen-func2.gcno +// CHECK-NEXT: -: 0:Data:instrprof-dlopen-func2.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: 1: 1:void func2(int K) {} diff --git a/test/profile/Inputs/instrprof-dlopen-func3.c b/test/profile/Inputs/instrprof-dlopen-func3.c new file mode 100644 index 000000000000..ec0dddb45274 --- /dev/null +++ b/test/profile/Inputs/instrprof-dlopen-func3.c @@ -0,0 +1 @@ +void func3(int K) {} diff --git a/test/profile/Inputs/instrprof-dlopen-func3.c.gcov b/test/profile/Inputs/instrprof-dlopen-func3.c.gcov new file mode 100644 index 000000000000..7101f74b938d --- /dev/null +++ b/test/profile/Inputs/instrprof-dlopen-func3.c.gcov @@ -0,0 +1,6 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-dlopen-func2.c +// CHECK-NEXT: -: 0:Graph:instrprof-dlopen-func2.gcno +// CHECK-NEXT: -: 0:Data:instrprof-dlopen-func2.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: 1: 1:void func2(int K) {} diff --git a/test/profile/Inputs/instrprof-gcov-__gcov_flush-terminate.c b/test/profile/Inputs/instrprof-gcov-__gcov_flush-terminate.c new file mode 100644 index 000000000000..7b24d69c75fc --- /dev/null +++ b/test/profile/Inputs/instrprof-gcov-__gcov_flush-terminate.c @@ -0,0 +1,13 @@ +int main(void) { + int i = 22; + + __gcov_flush(); + + i = 42; + + asm("int $3"); + + i = 84; + + return 0; +} diff --git a/test/profile/Inputs/instrprof-gcov-__gcov_flush-terminate.c.gcov b/test/profile/Inputs/instrprof-gcov-__gcov_flush-terminate.c.gcov new file mode 100644 index 000000000000..69e229a3127e --- /dev/null +++ b/test/profile/Inputs/instrprof-gcov-__gcov_flush-terminate.c.gcov @@ -0,0 +1,18 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-gcov-__gcov_flush-terminate.c +// CHECK-NEXT: -: 0:Graph:instrprof-gcov-__gcov_flush-terminate.gcno +// CHECK-NEXT: -: 0:Data:instrprof-gcov-__gcov_flush-terminate.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:int main(void) { +// CHECK-NEXT: 1: 2: int i = 22; +// CHECK-NEXT: -: 3: +// CHECK-NEXT: 1: 4: __gcov_flush(); +// CHECK-NEXT: -: 5: +// CHECK-NEXT: #####: 6: i = 42; +// CHECK-NEXT: -: 7: +// CHECK-NEXT: #####: 8: asm("int $3"); +// CHECK-NEXT: -: 9: +// CHECK-NEXT: #####: 10: i = 84; +// CHECK-NEXT: -: 11: +// CHECK-NEXT: #####: 12: return 0; +// CHECK-NEXT: -: 13:} diff --git a/test/profile/Inputs/instrprof-gcov-exceptions.cpp b/test/profile/Inputs/instrprof-gcov-exceptions.cpp new file mode 100644 index 000000000000..327966551d09 --- /dev/null +++ b/test/profile/Inputs/instrprof-gcov-exceptions.cpp @@ -0,0 +1,11 @@ +#include <string> + +void asd(std::string i) { +} + +int main(void) +{ + asd("22"); + + return 0; +} diff --git a/test/profile/Inputs/instrprof-gcov-exceptions.cpp.gcov b/test/profile/Inputs/instrprof-gcov-exceptions.cpp.gcov new file mode 100644 index 000000000000..7caf50806020 --- /dev/null +++ b/test/profile/Inputs/instrprof-gcov-exceptions.cpp.gcov @@ -0,0 +1,16 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-gcov-exceptions.cpp +// CHECK-NEXT: -: 0:Graph:instrprof-gcov-exceptions.gcno +// CHECK-NEXT: -: 0:Data:instrprof-gcov-exceptions.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:#include <string> +// CHECK-NEXT: -: 2: +// CHECK-NEXT: -: 3:void asd(std::string i) { +// CHECK-NEXT: 2: 4:} +// CHECK-NEXT: -: 5: +// CHECK-NEXT: -: 6:int main(void) +// CHECK-NEXT: -: 7:{ +// CHECK-NEXT: 1: 8: asd("22"); +// CHECK-NEXT: -: 9: +// CHECK-NEXT: 1: 10: return 0; +// CHECK-NEXT: -: 11:} diff --git a/test/profile/Inputs/instrprof-gcov-multiple-bbs-single-line.c b/test/profile/Inputs/instrprof-gcov-multiple-bbs-single-line.c new file mode 100644 index 000000000000..a2e187b5cb61 --- /dev/null +++ b/test/profile/Inputs/instrprof-gcov-multiple-bbs-single-line.c @@ -0,0 +1,20 @@ +int main(void) +{ + int var; + + int a = 1; + if (a) { + var++; + } + + if (a) {} + + int b = 0; + if (b) { + var++; + } + + if (b) {} + + return 0; +} diff --git a/test/profile/Inputs/instrprof-gcov-multiple-bbs-single-line.c.gcov b/test/profile/Inputs/instrprof-gcov-multiple-bbs-single-line.c.gcov new file mode 100644 index 000000000000..92532af30674 --- /dev/null +++ b/test/profile/Inputs/instrprof-gcov-multiple-bbs-single-line.c.gcov @@ -0,0 +1,34 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-gcov-multiple-bbs-single-line.c +// CHECK-NEXT: -: 0:Graph:instrprof-gcov-multiple-bbs-single-line.gcno +// CHECK-NEXT: -: 0:Data:instrprof-gcov-multiple-bbs-single-line.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT:function main called 1 returned 100% blocks executed 80% +// CHECK-NEXT: -: 1:int main(void) +// CHECK-NEXT: -: 2:{ +// CHECK-NEXT: -: 3: int var; +// CHECK-NEXT: -: 4: +// CHECK-NEXT: 1: 5: int a = 1; +// CHECK-NEXT: 1: 6: if (a) { +// CHECK-NEXT:branch 0 taken 1 +// CHECK-NEXT:branch 1 taken 0 +// CHECK-NEXT: 1: 7: var++; +// CHECK-NEXT: 1: 8: } +// CHECK-NEXT: -: 9: +// CHECK-NEXT: 1: 10: if (a) {} +// CHECK-NEXT:branch 0 taken 1 +// CHECK-NEXT:branch 1 taken 0 +// CHECK-NEXT: -: 11: +// CHECK-NEXT: 1: 12: int b = 0; +// CHECK-NEXT: 1: 13: if (b) { +// CHECK-NEXT:branch 0 taken 0 +// CHECK-NEXT:branch 1 taken 1 +// CHECK-NEXT: #####: 14: var++; +// CHECK-NEXT: #####: 15: } +// CHECK-NEXT: -: 16: +// CHECK-NEXT: 1: 17: if (b) {} +// CHECK-NEXT:branch 0 taken 0 +// CHECK-NEXT:branch 1 taken 1 +// CHECK-NEXT: -: 18: +// CHECK-NEXT: 1: 19: return 0; +// CHECK-NEXT: -: 20:} diff --git a/test/profile/Inputs/instrprof-shared-lib.c.gcov b/test/profile/Inputs/instrprof-shared-lib.c.gcov new file mode 100644 index 000000000000..fbc43d5f7d50 --- /dev/null +++ b/test/profile/Inputs/instrprof-shared-lib.c.gcov @@ -0,0 +1,14 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-shared-lib.c +// CHECK-NEXT: -: 0:Graph:instrprof-shared-lib.gcno +// CHECK-NEXT: -: 0:Data:instrprof-shared-lib.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:int g1 = 0; +// CHECK-NEXT: -: 2:int g2 = 1; +// CHECK-NEXT: -: 3: +// CHECK-NEXT: -: 4:void foo(int n) { +// CHECK-NEXT: 1: 5: if (n % 5 == 0) +// CHECK-NEXT: #####: 6: g1++; +// CHECK-NEXT: -: 7: else +// CHECK-NEXT: 1: 8: g2++; +// CHECK-NEXT: 1: 9:} diff --git a/test/profile/Inputs/instrprof-shared-lib_called-twice.c.gcov b/test/profile/Inputs/instrprof-shared-lib_called-twice.c.gcov new file mode 100644 index 000000000000..779c885d862d --- /dev/null +++ b/test/profile/Inputs/instrprof-shared-lib_called-twice.c.gcov @@ -0,0 +1,14 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-shared-lib.c +// CHECK-NEXT: -: 0:Graph:instrprof-shared-lib.gcno +// CHECK-NEXT: -: 0:Data:instrprof-shared-lib.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:int g1 = 0; +// CHECK-NEXT: -: 2:int g2 = 1; +// CHECK-NEXT: -: 3: +// CHECK-NEXT: -: 4:void foo(int n) { +// CHECK-NEXT: 2: 5: if (n % 5 == 0) +// CHECK-NEXT: #####: 6: g1++; +// CHECK-NEXT: -: 7: else +// CHECK-NEXT: 2: 8: g2++; +// CHECK-NEXT: 2: 9:} diff --git a/test/profile/Inputs/instrprof-shared-lib_in-loop.c.gcov b/test/profile/Inputs/instrprof-shared-lib_in-loop.c.gcov new file mode 100644 index 000000000000..76503d91426e --- /dev/null +++ b/test/profile/Inputs/instrprof-shared-lib_in-loop.c.gcov @@ -0,0 +1,14 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-shared-lib.c +// CHECK-NEXT: -: 0:Graph:instrprof-shared-lib.gcno +// CHECK-NEXT: -: 0:Data:instrprof-shared-lib.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:int g1 = 0; +// CHECK-NEXT: -: 2:int g2 = 1; +// CHECK-NEXT: -: 3: +// CHECK-NEXT: -: 4:void foo(int n) { +// CHECK-NEXT: 1000000: 5: if (n % 5 == 0) +// CHECK-NEXT: 360000: 6: g1++; +// CHECK-NEXT: -: 7: else +// CHECK-NEXT: 640000: 8: g2++; +// CHECK-NEXT: 1000000: 9:} diff --git a/test/profile/Inputs/instrprof-shared-main-gcov-flush.c b/test/profile/Inputs/instrprof-shared-main-gcov-flush.c new file mode 100644 index 000000000000..9f41b7e6362a --- /dev/null +++ b/test/profile/Inputs/instrprof-shared-main-gcov-flush.c @@ -0,0 +1,36 @@ +extern void foo(int n); +extern void __gcov_flush(void); + +int bar1 = 0; +int bar2 = 1; + +void bar(int n) { + if (n % 5 == 0) + bar1++; + else + bar2++; +} + +int main(int argc, char *argv[]) { +#ifdef SHARED_CALL_BEFORE_GCOV_FLUSH + foo(1); +#endif + + bar(5); + + __gcov_flush(); + + bar(5); + +#ifdef SHARED_CALL_AFTER_GCOV_FLUSH + foo(1); +#endif + +#ifdef EXIT_ABRUPTLY + _exit(0); +#endif + + bar(5); + + return 0; +} diff --git a/test/profile/Inputs/instrprof-shared-main-gcov-flush_no-writeout.c.gcov b/test/profile/Inputs/instrprof-shared-main-gcov-flush_no-writeout.c.gcov new file mode 100644 index 000000000000..b2dfe2acde67 --- /dev/null +++ b/test/profile/Inputs/instrprof-shared-main-gcov-flush_no-writeout.c.gcov @@ -0,0 +1,41 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-shared-main-gcov-flush.c +// CHECK-NEXT: -: 0:Graph:instrprof-shared-main-gcov-flush.gcno +// CHECK-NEXT: -: 0:Data:instrprof-shared-main-gcov-flush.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:extern void foo(int n); +// CHECK-NEXT: -: 2:extern void __gcov_flush(void); +// CHECK-NEXT: -: 3: +// CHECK-NEXT: -: 4:int bar1 = 0; +// CHECK-NEXT: -: 5:int bar2 = 1; +// CHECK-NEXT: -: 6: +// CHECK-NEXT: -: 7:void bar(int n) { +// CHECK-NEXT: 1: 8: if (n % 5 == 0) +// CHECK-NEXT: 1: 9: bar1++; +// CHECK-NEXT: -: 10: else +// CHECK-NEXT: #####: 11: bar2++; +// CHECK-NEXT: 1: 12:} +// CHECK-NEXT: -: 13: +// CHECK-NEXT: -: 14:int main(int argc, char *argv[]) { +// CHECK-NEXT: -: 15:#ifdef SHARED_CALL_BEFORE_GCOV_FLUSH +// CHECK-NEXT: 1: 16: foo(1); +// CHECK-NEXT: -: 17:#endif +// CHECK-NEXT: -: 18: +// CHECK-NEXT: 1: 19: bar(5); +// CHECK-NEXT: -: 20: +// CHECK-NEXT: 1: 21: __gcov_flush(); +// CHECK-NEXT: -: 22: +// CHECK-NEXT: 1: 23: bar(5); +// CHECK-NEXT: -: 24: +// CHECK-NEXT: -: 25:#ifdef SHARED_CALL_AFTER_GCOV_FLUSH +// CHECK-NEXT: 1: 26: foo(1); +// CHECK-NEXT: -: 27:#endif +// CHECK-NEXT: -: 28: +// CHECK-NEXT: -: 29:#ifdef EXIT_ABRUPTLY +// CHECK-NEXT: 1: 30: _exit(0); +// CHECK-NEXT: -: 31:#endif +// CHECK-NEXT: -: 32: +// CHECK-NEXT: -: 33: bar(5); +// CHECK-NEXT: -: 34: +// CHECK-NEXT: -: 35: return 0; +// CHECK-NEXT: #####: 36:} diff --git a/test/profile/Inputs/instrprof-shared-main-gcov-flush_shared-call-after.c.gcov b/test/profile/Inputs/instrprof-shared-main-gcov-flush_shared-call-after.c.gcov new file mode 100644 index 000000000000..f70e34e52894 --- /dev/null +++ b/test/profile/Inputs/instrprof-shared-main-gcov-flush_shared-call-after.c.gcov @@ -0,0 +1,41 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-shared-main-gcov-flush.c +// CHECK-NEXT: -: 0:Graph:instrprof-shared-main-gcov-flush.gcno +// CHECK-NEXT: -: 0:Data:instrprof-shared-main-gcov-flush.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:extern void foo(int n); +// CHECK-NEXT: -: 2:extern void __gcov_flush(void); +// CHECK-NEXT: -: 3: +// CHECK-NEXT: -: 4:int bar1 = 0; +// CHECK-NEXT: -: 5:int bar2 = 1; +// CHECK-NEXT: -: 6: +// CHECK-NEXT: -: 7:void bar(int n) { +// CHECK-NEXT: 3: 8: if (n % 5 == 0) +// CHECK-NEXT: 3: 9: bar1++; +// CHECK-NEXT: -: 10: else +// CHECK-NEXT: #####: 11: bar2++; +// CHECK-NEXT: 3: 12:} +// CHECK-NEXT: -: 13: +// CHECK-NEXT: -: 14:int main(int argc, char *argv[]) { +// CHECK-NEXT: -: 15:#ifdef SHARED_CALL_BEFORE_GCOV_FLUSH +// CHECK-NEXT: -: 16: foo(1); +// CHECK-NEXT: -: 17:#endif +// CHECK-NEXT: -: 18: +// CHECK-NEXT: 1: 19: bar(5); +// CHECK-NEXT: -: 20: +// CHECK-NEXT: 1: 21: __gcov_flush(); +// CHECK-NEXT: -: 22: +// CHECK-NEXT: 1: 23: bar(5); +// CHECK-NEXT: -: 24: +// CHECK-NEXT: -: 25:#ifdef SHARED_CALL_AFTER_GCOV_FLUSH +// CHECK-NEXT: 1: 26: foo(1); +// CHECK-NEXT: -: 27:#endif +// CHECK-NEXT: -: 28: +// CHECK-NEXT: -: 29:#ifdef EXIT_ABRUPTLY +// CHECK-NEXT: -: 30: _exit(0); +// CHECK-NEXT: -: 31:#endif +// CHECK-NEXT: -: 32: +// CHECK-NEXT: 1: 33: bar(5); +// CHECK-NEXT: -: 34: +// CHECK-NEXT: 1: 35: return 0; +// CHECK-NEXT: -: 36:} diff --git a/test/profile/Inputs/instrprof-shared-main-gcov-flush_shared-call-before-after.c.gcov b/test/profile/Inputs/instrprof-shared-main-gcov-flush_shared-call-before-after.c.gcov new file mode 100644 index 000000000000..b9ecff698722 --- /dev/null +++ b/test/profile/Inputs/instrprof-shared-main-gcov-flush_shared-call-before-after.c.gcov @@ -0,0 +1,41 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-shared-main-gcov-flush.c +// CHECK-NEXT: -: 0:Graph:instrprof-shared-main-gcov-flush.gcno +// CHECK-NEXT: -: 0:Data:instrprof-shared-main-gcov-flush.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:extern void foo(int n); +// CHECK-NEXT: -: 2:extern void __gcov_flush(void); +// CHECK-NEXT: -: 3: +// CHECK-NEXT: -: 4:int bar1 = 0; +// CHECK-NEXT: -: 5:int bar2 = 1; +// CHECK-NEXT: -: 6: +// CHECK-NEXT: -: 7:void bar(int n) { +// CHECK-NEXT: 3: 8: if (n % 5 == 0) +// CHECK-NEXT: 3: 9: bar1++; +// CHECK-NEXT: -: 10: else +// CHECK-NEXT: #####: 11: bar2++; +// CHECK-NEXT: 3: 12:} +// CHECK-NEXT: -: 13: +// CHECK-NEXT: -: 14:int main(int argc, char *argv[]) { +// CHECK-NEXT: -: 15:#ifdef SHARED_CALL_BEFORE_GCOV_FLUSH +// CHECK-NEXT: 1: 16: foo(1); +// CHECK-NEXT: -: 17:#endif +// CHECK-NEXT: -: 18: +// CHECK-NEXT: 1: 19: bar(5); +// CHECK-NEXT: -: 20: +// CHECK-NEXT: 1: 21: __gcov_flush(); +// CHECK-NEXT: -: 22: +// CHECK-NEXT: 1: 23: bar(5); +// CHECK-NEXT: -: 24: +// CHECK-NEXT: -: 25:#ifdef SHARED_CALL_AFTER_GCOV_FLUSH +// CHECK-NEXT: 1: 26: foo(1); +// CHECK-NEXT: -: 27:#endif +// CHECK-NEXT: -: 28: +// CHECK-NEXT: -: 29:#ifdef EXIT_ABRUPTLY +// CHECK-NEXT: -: 30: _exit(0); +// CHECK-NEXT: -: 31:#endif +// CHECK-NEXT: -: 32: +// CHECK-NEXT: 1: 33: bar(5); +// CHECK-NEXT: -: 34: +// CHECK-NEXT: 1: 35: return 0; +// CHECK-NEXT: -: 36:} diff --git a/test/profile/Inputs/instrprof-shared-main-gcov-flush_shared-call-before.c.gcov b/test/profile/Inputs/instrprof-shared-main-gcov-flush_shared-call-before.c.gcov new file mode 100644 index 000000000000..7c9e0afa11b2 --- /dev/null +++ b/test/profile/Inputs/instrprof-shared-main-gcov-flush_shared-call-before.c.gcov @@ -0,0 +1,41 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-shared-main-gcov-flush.c +// CHECK-NEXT: -: 0:Graph:instrprof-shared-main-gcov-flush.gcno +// CHECK-NEXT: -: 0:Data:instrprof-shared-main-gcov-flush.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:extern void foo(int n); +// CHECK-NEXT: -: 2:extern void __gcov_flush(void); +// CHECK-NEXT: -: 3: +// CHECK-NEXT: -: 4:int bar1 = 0; +// CHECK-NEXT: -: 5:int bar2 = 1; +// CHECK-NEXT: -: 6: +// CHECK-NEXT: -: 7:void bar(int n) { +// CHECK-NEXT: 3: 8: if (n % 5 == 0) +// CHECK-NEXT: 3: 9: bar1++; +// CHECK-NEXT: -: 10: else +// CHECK-NEXT: #####: 11: bar2++; +// CHECK-NEXT: 3: 12:} +// CHECK-NEXT: -: 13: +// CHECK-NEXT: -: 14:int main(int argc, char *argv[]) { +// CHECK-NEXT: -: 15:#ifdef SHARED_CALL_BEFORE_GCOV_FLUSH +// CHECK-NEXT: 1: 16: foo(1); +// CHECK-NEXT: -: 17:#endif +// CHECK-NEXT: -: 18: +// CHECK-NEXT: 1: 19: bar(5); +// CHECK-NEXT: -: 20: +// CHECK-NEXT: 1: 21: __gcov_flush(); +// CHECK-NEXT: -: 22: +// CHECK-NEXT: 1: 23: bar(5); +// CHECK-NEXT: -: 24: +// CHECK-NEXT: -: 25:#ifdef SHARED_CALL_AFTER_GCOV_FLUSH +// CHECK-NEXT: -: 26: foo(1); +// CHECK-NEXT: -: 27:#endif +// CHECK-NEXT: -: 28: +// CHECK-NEXT: -: 29:#ifdef EXIT_ABRUPTLY +// CHECK-NEXT: -: 30: _exit(0); +// CHECK-NEXT: -: 31:#endif +// CHECK-NEXT: -: 32: +// CHECK-NEXT: 1: 33: bar(5); +// CHECK-NEXT: -: 34: +// CHECK-NEXT: 1: 35: return 0; +// CHECK-NEXT: -: 36:} diff --git a/test/profile/Inputs/instrprof-shared-main.c.gcov b/test/profile/Inputs/instrprof-shared-main.c.gcov new file mode 100644 index 000000000000..70be367507ff --- /dev/null +++ b/test/profile/Inputs/instrprof-shared-main.c.gcov @@ -0,0 +1,18 @@ +// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-shared-main.c +// CHECK-NEXT: -: 0:Graph:instrprof-shared-main.gcno +// CHECK-NEXT: -: 0:Data:instrprof-shared-main.gcda +// CHECK-NEXT: -: 0:Runs:1 +// CHECK-NEXT: -: 0:Programs:1 +// CHECK-NEXT: -: 1:extern int g1, g2; +// CHECK-NEXT: -: 2:extern void foo(int n); +// CHECK-NEXT: -: 3: +// CHECK-NEXT: -: 4:int main() { +// CHECK-NEXT: -: 5: int i, j; +// CHECK-NEXT: 2002: 6: for (i = 0; i < 1000; i++) +// CHECK-NEXT: 2002000: 7: for (j = 0; j < 1000; j++) +// CHECK-NEXT: 1001000: 8: foo(i * j); +// CHECK-NEXT: -: 9: +// CHECK-NEXT: 1: 10: if (g2 - g1 == 280001) +// CHECK-NEXT: 1: 11: return 0; +// CHECK-NEXT: #####: 12: return 1; +// CHECK-NEXT: 1: 13:} diff --git a/test/profile/Linux/counter_promo_nest.c b/test/profile/Linux/counter_promo_nest.c index 0792f0c76abb..ebd52dda7f48 100644 --- a/test/profile/Linux/counter_promo_nest.c +++ b/test/profile/Linux/counter_promo_nest.c @@ -25,6 +25,9 @@ int main() // PROMO: load{{.*}}@__profc_main{{.*}} // PROMO-NEXT: add // PROMO-NEXT: store{{.*}}@__profc_main{{.*}} +// PROMO: load{{.*}}@__profc_main{{.*}} +// PROMO-NEXT: add +// PROMO-NEXT: store{{.*}}@__profc_main{{.*}} // PROMO-NEXT: load{{.*}}@__profc_main{{.*}} // PROMO-NEXT: add // PROMO-NEXT: store{{.*}}@__profc_main{{.*}} diff --git a/test/profile/Linux/instrprof-value-merge.c b/test/profile/Linux/instrprof-value-merge.c new file mode 100644 index 000000000000..902430a4a968 --- /dev/null +++ b/test/profile/Linux/instrprof-value-merge.c @@ -0,0 +1,79 @@ +// RUN: %clang_pgogen -o %t -O3 %s +// RUN: rm -rf %t.profdir +// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t +// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t +// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t +// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t 1 +// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t 1 +// RUN: llvm-profdata show -counts -function=main -ic-targets -memop-sizes %t.profdir/default_*.profraw | FileCheck %s + +#include <string.h> + +void (*f0)(); +void (*f1)(); +void (*f2)(); + +char dst[200]; +char src[200]; +volatile int n; + +__attribute__((noinline)) void foo() {} + +__attribute__((noinline)) void bar() { + f0 = foo; + f1 = foo; + f2 = foo; + n = 4; +} +int main(int argc, char *argv[]) { + int i; + bar(); + if (argc == 1) { + f0(); + for (i = 0; i < 9; i++) + f1(); + for (i = 0; i < 99; i++) + f2(); + } else { + memcpy((void *)dst, (void *)src, n); + for (i = 0; i < 6; i++) + memcpy((void *)(dst + 2), (void *)src, n + 1); + for (i = 0; i < 66; i++) + memcpy((void *)(dst + 9), (void *)src, n + 2); + } +} + +// CHECK: Counters: +// CHECK: main: +// CHECK: Hash: 0x00030012a7ab6e87 +// CHECK: Counters: 6 +// CHECK: Indirect Call Site Count: 3 +// CHECK: Number of Memory Intrinsics Calls: 3 +// CHECK: Block counts: [27, 297, 12, 132, 3, 2] +// CHECK: Indirect Target Results: +// CHECK: [ 0, foo, 3 ] +// CHECK: [ 1, foo, 27 ] +// CHECK: [ 2, foo, 297 ] +// CHECK: Memory Intrinsic Size Results: +// CHECK: [ 0, 4, 2 ] +// CHECK: [ 1, 5, 12 ] +// CHECK: [ 2, 6, 132 ] +// CHECK: Instrumentation level: IR +// CHECK: Functions shown: 1 +// CHECK: Total functions: 3 +// CHECK: Maximum function count: 327 +// CHECK: Maximum internal block count: 297 +// CHECK: Statistics for indirect call sites profile: +// CHECK: Total number of sites: 3 +// CHECK: Total number of sites with values: 3 +// CHECK: Total number of profiled values: 3 +// CHECK: Value sites histogram: +// CHECK: NumTargets, SiteCount +// CHECK: 1, 3 +// CHECK: Statistics for memory intrinsic calls sizes profile: +// CHECK: Total number of sites: 3 +// CHECK: Total number of sites with values: 3 +// CHECK: Total number of profiled values: 3 +// CHECK: Value sites histogram: +// CHECK: NumTargets, SiteCount +// CHECK: 1, 3 diff --git a/test/profile/instrprof-darwin-dead-strip.c b/test/profile/instrprof-darwin-dead-strip.c index 03049335efda..6a2bffc213a3 100644 --- a/test/profile/instrprof-darwin-dead-strip.c +++ b/test/profile/instrprof-darwin-dead-strip.c @@ -1,7 +1,7 @@ // REQUIRES: osx-ld64-live_support // REQUIRES: lto -// RUN: %clang_profgen=%t.profraw -fcoverage-mapping -mllvm -enable-name-compression=false -Wl,-dead_strip -o %t %s +// RUN: %clang_profgen=%t.profraw -fcoverage-mapping -mllvm -enable-name-compression=false -DCODE=1 -Wl,-dead_strip -o %t %s // RUN: %run %t // RUN: llvm-profdata merge -o %t.profdata %t.profraw // RUN: llvm-profdata show --all-functions %t.profdata | FileCheck %s -check-prefix=PROF @@ -10,7 +10,7 @@ // RUN: otool -s __DATA __llvm_prf_names %t | FileCheck %s -check-prefix=PRF_NAMES // RUN: otool -s __DATA __llvm_prf_cnts %t | FileCheck %s -check-prefix=PRF_CNTS -// RUN: %clang_lto_profgen=%t.lto.profraw -fcoverage-mapping -mllvm -enable-name-compression=false -Wl,-dead_strip -flto -o %t.lto %s +// RUN: %clang_lto_profgen=%t.lto.profraw -fcoverage-mapping -mllvm -enable-name-compression=false -DCODE=1 -Wl,-dead_strip -flto -o %t.lto %s // RUN: %run %t.lto // RUN: llvm-profdata merge -o %t.lto.profdata %t.lto.profraw // RUN: llvm-profdata show --all-functions %t.lto.profdata | FileCheck %s -check-prefix=PROF @@ -22,12 +22,24 @@ // Note: We expect foo() and some of the profiling data associated with it to // be dead-stripped. +// Note: When there is no code in a program, we expect to see the exact same +// set of external functions provided by the profile runtime. + +// RUN: %clang_profgen -fcoverage-mapping -Wl,-dead_strip -dynamiclib -o %t.nocode.dylib %s +// RUN: nm -jgU %t.nocode.dylib > %t.nocode.syms +// RUN: nm -jgU %t | grep -vE "main|foo|mh_execute_header" > %t.code.syms +// RUN: diff %t.nocode.syms %t.code.syms + +#ifdef CODE + // COV: [[@LINE+1]]{{ *}}|{{ *}}0|void foo() void foo() {} // COV: [[@LINE+1]]{{ *}}|{{ *}}1|int main int main() { return 0; } +#endif // CODE + // NM-NOT: foo // PROF: Counters: diff --git a/test/profile/instrprof-darwin-exports.c b/test/profile/instrprof-darwin-exports.c new file mode 100644 index 000000000000..6667cabdb2df --- /dev/null +++ b/test/profile/instrprof-darwin-exports.c @@ -0,0 +1,11 @@ +// REQUIRES: osx-ld64-live_support + +// Compiling with PGO/code coverage on Darwin should raise no warnings or errors +// when using an exports list. + +// RUN: echo "_main" > %t.exports +// RUN: %clang_pgogen -Werror -Wl,-exported_symbols_list,%t.exports -o %t %s 2>&1 | tee %t.log +// RUN: %clang_profgen -Werror -fcoverage-mapping -Wl,-exported_symbols_list,%t.exports -o %t %s 2>&1 | tee -a %t.log +// RUN: cat %t.log | count 0 + +int main() {} diff --git a/test/profile/instrprof-dlopen-dlclose-gcov.test b/test/profile/instrprof-dlopen-dlclose-gcov.test new file mode 100644 index 000000000000..0444fca2692c --- /dev/null +++ b/test/profile/instrprof-dlopen-dlclose-gcov.test @@ -0,0 +1,30 @@ +RUN: mkdir -p %t.d +RUN: cd %t.d + +RUN: %clang --coverage -o func.shared -fPIC -shared %S/Inputs/instrprof-dlopen-func.c +RUN: %clang --coverage -o func2.shared -fPIC -shared %S/Inputs/instrprof-dlopen-func2.c +RUN: %clang --coverage -o func3.shared -fPIC -shared %S/Inputs/instrprof-dlopen-func3.c +RUN: %clang --coverage -o %t -fPIC -rpath %t.d %S/Inputs/instrprof-dlopen-dlclose-main.c + +# Test with two dlopened libraries. +RUN: %run %t +RUN: llvm-cov gcov instrprof-dlopen-dlclose-main.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-dlclose-main.c.gcov %S/Inputs/instrprof-dlopen-dlclose-main.c.gcov +RUN: llvm-cov gcov instrprof-dlopen-func.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-func.c.gcov %S/Inputs/instrprof-dlopen-func.c.gcov +RUN: llvm-cov gcov instrprof-dlopen-func2.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-func2.c.gcov %S/Inputs/instrprof-dlopen-func2.c.gcov +RUN: rm instrprof-dlopen-dlclose-main.gcda instrprof-dlopen-func.gcda instrprof-dlopen-func2.gcda + +# Test with three dlopened libraries. +RUN: %clang -DUSE_LIB3 --coverage -o %t -fPIC -rpath %t.d %S/Inputs/instrprof-dlopen-dlclose-main.c +RUN: %run %t +RUN: llvm-cov gcov instrprof-dlopen-dlclose-main.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-dlclose-main.c.gcov %S/Inputs/instrprof-dlopen-dlclose-main_three-libs.c.gcov +RUN: llvm-cov gcov instrprof-dlopen-func.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-func.c.gcov %S/Inputs/instrprof-dlopen-func.c.gcov +RUN: llvm-cov gcov instrprof-dlopen-func2.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-func2.c.gcov %S/Inputs/instrprof-dlopen-func2.c.gcov +RUN: llvm-cov gcov instrprof-dlopen-func3.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-func2.c.gcov %S/Inputs/instrprof-dlopen-func3.c.gcov +RUN: rm instrprof-dlopen-dlclose-main.gcda instrprof-dlopen-func.gcda instrprof-dlopen-func2.gcda instrprof-dlopen-func3.gcda diff --git a/test/profile/instrprof-gcov-__gcov_flush-terminate.test b/test/profile/instrprof-gcov-__gcov_flush-terminate.test new file mode 100644 index 000000000000..aa51461a3bd0 --- /dev/null +++ b/test/profile/instrprof-gcov-__gcov_flush-terminate.test @@ -0,0 +1,12 @@ +XFAIL: * + +RUN: mkdir -p %t.d +RUN: cd %t.d + +RUN: %clang --coverage -o %t %S/Inputs/instrprof-gcov-__gcov_flush-terminate.c +RUN: test -f instrprof-gcov-__gcov_flush-terminate.gcno + +RUN: rm -f instrprof-gcov-__gcov_flush-terminate.gcda +RUN: %expect_crash %run %t +RUN: llvm-cov gcov instrprof-gcov-__gcov_flush-terminate.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-gcov-__gcov_flush-terminate.c.gcov %S/Inputs/instrprof-gcov-__gcov_flush-terminate.c.gcov diff --git a/test/profile/instrprof-gcov-exceptions.test b/test/profile/instrprof-gcov-exceptions.test new file mode 100644 index 000000000000..20ca47a9528b --- /dev/null +++ b/test/profile/instrprof-gcov-exceptions.test @@ -0,0 +1,21 @@ +RUN: mkdir -p %t.d +RUN: cd %t.d + +# Test with exceptions disabled. +RUN: %clangxx --coverage -o %t %S/Inputs/instrprof-gcov-exceptions.cpp -fno-exceptions +RUN: test -f instrprof-gcov-exceptions.gcno + +RUN: rm -f instrprof-gcov-exceptions.gcda +RUN: %run %t +RUN: llvm-cov gcov instrprof-gcov-exceptions.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-gcov-exceptions.cpp.gcov %S/Inputs/instrprof-gcov-exceptions.cpp.gcov + +# Test with exceptions enabled, the result in terms of line counts should be the same. +RUN: %clangxx --coverage -o %t %S/Inputs/instrprof-gcov-exceptions.cpp +RUN: test -f instrprof-gcov-exceptions.gcno + +RUN: rm -f instrprof-gcov-exceptions.gcda +RUN: %run %t +RUN: llvm-cov gcov instrprof-gcov-exceptions.gcda +# The result should be the same, not using XFAIL as only this part of the test is failing. +RUN: not FileCheck --match-full-lines --strict-whitespace --input-file instrprof-gcov-exceptions.cpp.gcov %S/Inputs/instrprof-gcov-exceptions.cpp.gcov diff --git a/test/profile/instrprof-gcov-multiple-bbs-single-line.test b/test/profile/instrprof-gcov-multiple-bbs-single-line.test new file mode 100644 index 000000000000..8839455189ee --- /dev/null +++ b/test/profile/instrprof-gcov-multiple-bbs-single-line.test @@ -0,0 +1,13 @@ +XFAIL: * + +RUN: mkdir -p %t.d +RUN: cd %t.d + +RUN: %clang --coverage -o %t %S/Inputs/instrprof-gcov-multiple-bbs-single-line.c +RUN: test -f instrprof-gcov-multiple-bbs-single-line.gcno + +RUN: rm -f instrprof-gcov-multiple-bbs-single-line.gcda +RUN: %run %t +RUN: llvm-cov gcov -b -c instrprof-gcov-multiple-bbs-single-line.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-gcov-multiple-bbs-single-line.c.gcov %S/Inputs/instrprof-gcov-multiple-bbs-single-line.c.gcov +RUN: rm instrprof-gcov-multiple-bbs-single-line.gcda diff --git a/test/profile/instrprof-gcov-two-objects.test b/test/profile/instrprof-gcov-two-objects.test new file mode 100644 index 000000000000..a53d51dce8ed --- /dev/null +++ b/test/profile/instrprof-gcov-two-objects.test @@ -0,0 +1,18 @@ +RUN: mkdir -p %t.d +RUN: cd %t.d + +RUN: %clang --coverage -o instrprof-shared-lib.o -c %S/Inputs/instrprof-shared-lib.c +RUN: test -f instrprof-shared-lib.gcno + +RUN: %clang --coverage -o instrprof-shared-main.o -c %S/Inputs/instrprof-shared-main.c +RUN: test -f instrprof-shared-main.gcno + +RUN: %clang --coverage -o %t instrprof-shared-main.o instrprof-shared-lib.o +RUN: test -f %t + +RUN: %run %t +RUN: llvm-cov gcov instrprof-shared-main.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-shared-main.c.gcov %S/Inputs/instrprof-shared-main.c.gcov +RUN: llvm-cov gcov instrprof-shared-lib.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-shared-lib.c.gcov %S/Inputs/instrprof-shared-lib_in-loop.c.gcov +RUN: rm instrprof-shared-main.gcda instrprof-shared-lib.gcda diff --git a/test/profile/instrprof-get-filename.c b/test/profile/instrprof-get-filename.c new file mode 100644 index 000000000000..031b75f12f3c --- /dev/null +++ b/test/profile/instrprof-get-filename.c @@ -0,0 +1,39 @@ +// Test __llvm_profile_get_filename. +// RUN: %clang_pgogen -O2 -o %t %s +// RUN: %run %t + +#include <stdio.h> +#include <string.h> + +const char *__llvm_profile_get_filename(); +void __llvm_profile_set_filename(const char *); + +int main(int argc, const char *argv[]) { + int i; + const char *filename; + const char *new_filename = "/path/to/test.profraw"; + + filename = __llvm_profile_get_filename(); + if (strncmp(filename, "default_", 8)) { + fprintf(stderr, + "Error: got filename %s, expected it to start with 'default_'\n", + filename); + return 1; + } + if (strcmp(filename + strlen(filename) - strlen(".profraw"), ".profraw")) { + fprintf(stderr, + "Error: got filename %s, expected it to end with '.profraw'\n", + filename); + return 1; + } + + __llvm_profile_set_filename(new_filename); + filename = __llvm_profile_get_filename(); + if (strcmp(filename, new_filename)) { + fprintf(stderr, "Error: got filename %s, expected '%s'\n", filename, + new_filename); + return 1; + } + + return 0; +} diff --git a/test/profile/instrprof-path.c b/test/profile/instrprof-path.c index 28ee8ad0a484..90cb1df198f0 100644 --- a/test/profile/instrprof-path.c +++ b/test/profile/instrprof-path.c @@ -12,7 +12,7 @@ #include <string.h> const char *__llvm_profile_get_path_prefix(); -void __llvm_profile_set_filanem(const char*); +void __llvm_profile_set_filename(const char*); int main(int argc, const char *argv[]) { int i; diff --git a/test/profile/instrprof-reset-counters.c b/test/profile/instrprof-reset-counters.c index e8892366bcfe..f15bc0d8e3a1 100644 --- a/test/profile/instrprof-reset-counters.c +++ b/test/profile/instrprof-reset-counters.c @@ -12,7 +12,7 @@ int main(void) { return 0; } void foo(int N) { - // CHECK-LABEL: define void @foo( + // CHECK-LABEL: define{{( dso_local)?}} void @foo( // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}, !prof ![[FOO:[0-9]+]] if (N) {} } diff --git a/test/profile/instrprof-shared-gcov-flush.test b/test/profile/instrprof-shared-gcov-flush.test new file mode 100644 index 000000000000..50292b6336c4 --- /dev/null +++ b/test/profile/instrprof-shared-gcov-flush.test @@ -0,0 +1,52 @@ +# This test fails on Mac (https://bugs.llvm.org/show_bug.cgi?id=38134) +XFAIL: darwin + +RUN: mkdir -p %t.d +RUN: cd %t.d + +RUN: %clang --coverage -o libfunc.so -fPIC -shared %S/Inputs/instrprof-shared-lib.c +RUN: test -f instrprof-shared-lib.gcno + +# Test the case where we exit abruptly after calling __gcov_flush, which means we don't write out the counters at exit. +RUN: %clang -DEXIT_ABRUPTLY -DSHARED_CALL_BEFORE_GCOV_FLUSH -DSHARED_CALL_AFTER_GCOV_FLUSH --coverage -o %t -L%t.d -rpath %t.d -lfunc %S/Inputs/instrprof-shared-main-gcov-flush.c +RUN: test -f instrprof-shared-main-gcov-flush.gcno + +RUN: %run %t +RUN: llvm-cov gcov instrprof-shared-main-gcov-flush.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-shared-main-gcov-flush.c.gcov %S/Inputs/instrprof-shared-main-gcov-flush_no-writeout.c.gcov +RUN: llvm-cov gcov instrprof-shared-lib.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-shared-lib.c.gcov %S/Inputs/instrprof-shared-lib.c.gcov +RUN: rm instrprof-shared-main-gcov-flush.gcda instrprof-shared-lib.gcda + +# Test the case where we exit normally and we have a call to the shared library function before __gcov_flush. +RUN: %clang -DSHARED_CALL_BEFORE_GCOV_FLUSH --coverage -o %t -L%t.d -rpath %t.d -lfunc %S/Inputs/instrprof-shared-main-gcov-flush.c +RUN: test -f instrprof-shared-main-gcov-flush.gcno + +RUN: %run %t +RUN: llvm-cov gcov instrprof-shared-main-gcov-flush.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-shared-main-gcov-flush.c.gcov %S/Inputs/instrprof-shared-main-gcov-flush_shared-call-before.c.gcov +RUN: llvm-cov gcov instrprof-shared-lib.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-shared-lib.c.gcov %S/Inputs/instrprof-shared-lib.c.gcov +RUN: rm instrprof-shared-main-gcov-flush.gcda instrprof-shared-lib.gcda + +# Test the case where we exit normally and we have a call to the shared library function after __gcov_flush. +RUN: %clang -DSHARED_CALL_AFTER_GCOV_FLUSH --coverage -o %t -L%t.d -rpath %t.d -lfunc %S/Inputs/instrprof-shared-main-gcov-flush.c +RUN: test -f instrprof-shared-main-gcov-flush.gcno + +RUN: %run %t +RUN: llvm-cov gcov instrprof-shared-main-gcov-flush.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-shared-main-gcov-flush.c.gcov %S/Inputs/instrprof-shared-main-gcov-flush_shared-call-after.c.gcov +RUN: llvm-cov gcov instrprof-shared-lib.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-shared-lib.c.gcov %S/Inputs/instrprof-shared-lib.c.gcov +RUN: rm instrprof-shared-main-gcov-flush.gcda instrprof-shared-lib.gcda + +# Test the case where we exit normally and we have calls to the shared library function before and after __gcov_flush. +RUN: %clang -DSHARED_CALL_BEFORE_GCOV_FLUSH -DSHARED_CALL_AFTER_GCOV_FLUSH --coverage -o %t -L%t.d -rpath %t.d -lfunc %S/Inputs/instrprof-shared-main-gcov-flush.c +RUN: test -f instrprof-shared-main-gcov-flush.gcno + +RUN: %run %t +RUN: llvm-cov gcov instrprof-shared-main-gcov-flush.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-shared-main-gcov-flush.c.gcov %S/Inputs/instrprof-shared-main-gcov-flush_shared-call-before-after.c.gcov +RUN: llvm-cov gcov instrprof-shared-lib.gcda +RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-shared-lib.c.gcov %S/Inputs/instrprof-shared-lib_called-twice.c.gcov +RUN: rm instrprof-shared-main-gcov-flush.gcda instrprof-shared-lib.gcda diff --git a/test/profile/instrprof-visibility.cpp b/test/profile/instrprof-visibility.cpp index 6fbba9defc56..bb533050e059 100644 --- a/test/profile/instrprof-visibility.cpp +++ b/test/profile/instrprof-visibility.cpp @@ -1,8 +1,8 @@ // RUN: %clangxx_profgen -fcoverage-mapping %S/Inputs/instrprof-visibility-helper.cpp -o %t %s // RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t // RUN: llvm-profdata merge %t.profraw -o %t.profdata -// RUN: llvm-profdata show --all-functions %t.profraw | FileCheck %s --check-prefix=PROFILE -// RUN: llvm-cov show %t -instr-profile=%t.profdata | FileCheck %s --check-prefix=COV +// RUN: llvm-profdata show --all-functions %t.profraw | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=PROFILE +// RUN: llvm-cov show %t -instr-profile=%t.profdata | FileCheck -allow-deprecated-dag-overlap %s --check-prefix=COV namespace { #define NO_WEAK diff --git a/test/sanitizer_common/CMakeLists.txt b/test/sanitizer_common/CMakeLists.txt index 8b210a08aa57..4e2c80390f71 100644 --- a/test/sanitizer_common/CMakeLists.txt +++ b/test/sanitizer_common/CMakeLists.txt @@ -4,15 +4,17 @@ 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|NetBSD") +if(CMAKE_SYSTEM_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|SunOS") list(APPEND SUPPORTED_TOOLS asan) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT ANDROID) +if(CMAKE_SYSTEM_NAME MATCHES "NetBSD" OR (CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT ANDROID)) list(APPEND SUPPORTED_TOOLS tsan) list(APPEND SUPPORTED_TOOLS msan) - list(APPEND SUPPORTED_TOOLS lsan) list(APPEND SUPPORTED_TOOLS ubsan) endif() +if(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT ANDROID) + list(APPEND SUPPORTED_TOOLS lsan) +endif() # Create a separate config for each tool we support. foreach(tool ${SUPPORTED_TOOLS}) diff --git a/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc b/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc new file mode 100644 index 000000000000..1a340edecdbe --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc @@ -0,0 +1,43 @@ +// RUN: %clangxx %collect_stack_traces -O0 %s -o %t + +// Alignment is not a power of 2: +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 17 2>&1 | FileCheck %s +// Size is not a multiple of alignment: +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 8 2>&1 | FileCheck %s +// Alignment is 0: +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 0 2>&1 | FileCheck %s + +// The same for allocator_may_return_null=1: +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 17 2>&1 | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL + +// REQUIRES: stable-runtime + +// UNSUPPORTED: android, ubsan + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +extern void *aligned_alloc(size_t alignment, size_t size); + +int main(int argc, char **argv) { + assert(argc == 2); + const int alignment = atoi(argv[1]); + + void *p = aligned_alloc(alignment, 100); + // CHECK: {{ERROR: .*Sanitizer: invalid alignment requested in aligned_alloc}} + // Handle a case when aligned_alloc is aliased by memalign. + // CHECK: {{#0 .*}}{{aligned_alloc|memalign}} + // CHECK: {{#1 .*main .*aligned_alloc-alignment.cc:}}[[@LINE-4]] + // CHECK: {{SUMMARY: .*Sanitizer: invalid-aligned-alloc-alignment}} + + // The NULL pointer is printed differently on different systems, while (long)0 + // is always the same. + fprintf(stderr, "errno: %d, p: %lx\n", errno, (long)p); + // CHECK-NULL: errno: 22, p: 0 + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc b/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc index 3c875c1793df..3013a3c3fd7d 100644 --- a/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc +++ b/test/sanitizer_common/TestCases/Linux/hard_rss_limit_mb_test.cc @@ -16,6 +16,9 @@ // XFAIL: msan // XFAIL: ubsan +// https://github.com/google/sanitizers/issues/981 +// UNSUPPORTED: android-26 + #include <string.h> #include <stdio.h> #include <unistd.h> diff --git a/test/sanitizer_common/TestCases/Linux/mmap64_test.c b/test/sanitizer_common/TestCases/Linux/mmap64_test.c new file mode 100644 index 000000000000..f4c009d846af --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/mmap64_test.c @@ -0,0 +1,13 @@ +// RUN: %clang %s -o %t && %run %t + +#define _LARGEFILE64_SOURCE 1 + +#include <assert.h> +#include <sys/mman.h> + +int main() { + char *buf = (char *)mmap64(0, 100000, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + assert(buf); + munmap(buf, 100000); +} diff --git a/test/sanitizer_common/TestCases/Linux/mmap_write_exec.cpp b/test/sanitizer_common/TestCases/Linux/mmap_write_exec.cpp new file mode 100644 index 000000000000..49495403c5a1 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/mmap_write_exec.cpp @@ -0,0 +1,37 @@ +// RUN: %clangxx %s -o %t +// RUN: %env_tool_opts=detect_write_exec=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_tool_opts=detect_write_exec=0 %run %t 2>&1 | FileCheck %s \ +// RUN: --check-prefix=CHECK-DISABLED +// ubsan and lsan do not install mmap interceptors UNSUPPORTED: ubsan, lsan + +// TODO: Fix option on Android, it hangs there for unknown reasons. +// XFAIL: android + +#include <stdio.h> +#include <sys/mman.h> + +int main(int argc, char **argv) { + char *p = (char *)mmap(0, 1024, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + // CHECK: WARNING: {{.*}}Sanitizer: writable-executable page usage + // CHECK: #{{[0-9]+.*}}main{{.*}}mmap_write_exec.cpp:[[@LINE-3]] + // CHECK: SUMMARY: {{.*}}Sanitizer: w-and-x-usage + + char *q = (char *)mmap(p, 64, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + (void)mprotect(q, 64, PROT_WRITE | PROT_EXEC); + // CHECK: WARNING: {{.*}}Sanitizer: writable-executable page usage + // CHECK: #{{[0-9]+.*}}main{{.*}}mmap_write_exec.cpp:[[@LINE-2]] + // CHECK: SUMMARY: {{.*}}Sanitizer: w-and-x-usage + + char *a = (char *)mmap(0, 1024, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + char *b = (char *)mmap(a, 64, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + (void)mprotect(q, 64, PROT_READ | PROT_EXEC); + // CHECK-NOT: Sanitizer + + printf("done\n"); + // CHECK-DISABLED-NOT: Sanitizer + // CHECK-DISABLED: done +} diff --git a/test/sanitizer_common/TestCases/Linux/name_to_handle_at.cc b/test/sanitizer_common/TestCases/Linux/name_to_handle_at.cc new file mode 100644 index 000000000000..47c6a18627a6 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/name_to_handle_at.cc @@ -0,0 +1,21 @@ +// RUN: %clangxx -O0 %s -o %t && %run %t +// UNSUPPORTED: android + +#include <assert.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/types.h> + +int main(int argc, char **argv) { + int mount_id; + struct file_handle *handle = reinterpret_cast<struct file_handle *>( + malloc(sizeof(*handle) + MAX_HANDLE_SZ)); + + handle->handle_bytes = MAX_HANDLE_SZ; + int res = name_to_handle_at(AT_FDCWD, argv[0], handle, &mount_id, 0); + assert(!res); + + free(handle); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Linux/pthread_mutex.cc b/test/sanitizer_common/TestCases/Linux/pthread_mutex.cc new file mode 100644 index 000000000000..610958143b47 --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/pthread_mutex.cc @@ -0,0 +1,34 @@ +// RUN: %clangxx -O1 %s -o %t && %run %t +// RUN: %clangxx -O1 -DUSE_GLIBC %s -o %t && %run %t +// UNSUPPORTED: android + +#include <pthread.h> + +#ifdef USE_GLIBC +extern "C" int __pthread_mutex_lock(pthread_mutex_t *__mutex); +extern "C" int __pthread_mutex_unlock(pthread_mutex_t *__mutex); +#define LOCK __pthread_mutex_lock +#define UNLOCK __pthread_mutex_unlock +#else +#define LOCK pthread_mutex_lock +#define UNLOCK pthread_mutex_unlock +#endif + +pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; +int x; + +static void *Start(void *arg) { + LOCK(&m); + ++x; + UNLOCK(&m); + return nullptr; +} + +int main() { + pthread_t threads[2] = {}; + for (pthread_t &t : threads) + pthread_create(&t, 0, &Start, 0); + for (pthread_t &t : threads) + pthread_join(t, 0); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc b/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc new file mode 100644 index 000000000000..537c57e1a69f --- /dev/null +++ b/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc @@ -0,0 +1,47 @@ +// RUN: %clangxx %collect_stack_traces -O0 %s -o %t +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t m1 2>&1 | FileCheck %s +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t m1 2>&1 | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t psm1 2>&1 | FileCheck %s +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t psm1 2>&1 | FileCheck %s --check-prefix=CHECK-NULL + +// REQUIRES: stable-runtime + +// UNSUPPORTED: android, freebsd, netbsd, ubsan + +// Checks that pvalloc overflows are caught. If the allocator is allowed to +// return null, the errno should be set to ENOMEM. + +#include <assert.h> +#include <errno.h> +#include <malloc.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +int main(int argc, char *argv[]) { + assert(argc == 2); + const char *action = argv[1]; + + const size_t page_size = sysconf(_SC_PAGESIZE); + + void *p = nullptr; + if (!strcmp(action, "m1")) { + p = pvalloc((uintptr_t)-1); + } else if (!strcmp(action, "psm1")) { + p = pvalloc((uintptr_t)-(page_size - 1)); + } else { + assert(0); + } + // CHECK: {{ERROR: .*Sanitizer: pvalloc parameters overflow: size .* rounded up to system page size .* cannot be represented in type size_t}} + // CHECK: {{#0 .*pvalloc}} + // CHECK: {{#1 .*main .*pvalloc-overflow.cc:}} + // CHECK: {{SUMMARY: .*Sanitizer: pvalloc-overflow}} + + // The NULL pointer is printed differently on different systems, while (long)0 + // is always the same. + fprintf(stderr, "errno: %d, p: %lx\n", errno, (long)p); + // CHECK-NULL: errno: 12, p: 0 + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc b/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc index 2ee809547530..f7d8b4d64016 100644 --- a/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc +++ b/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc @@ -15,6 +15,10 @@ // XFAIL: tsan // XFAIL: msan // XFAIL: ubsan + +// https://github.com/google/sanitizers/issues/981 +// UNSUPPORTED: android-26 + #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -65,4 +69,4 @@ int main() { // CHECK_MAY_RETURN_0: allocating 128 times // CHECK_MAY_RETURN_0: Some of the malloc calls returned non-null: 128 // CHECK_MAY_RETURN_0: allocating 256 times -// CHECK_MAY_RETURN_0: allocator is terminating the process instead of returning +// CHECK_MAY_RETURN_0: {{SUMMARY: .*Sanitizer: rss-limit-exceeded}} diff --git a/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc b/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc index c3a656022897..0ffb346ebb45 100644 --- a/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc +++ b/test/sanitizer_common/TestCases/Linux/sysconf_interceptor_bypass_test.cc @@ -1,12 +1,14 @@ // RUN: %clangxx -O2 %s -o %t && %run %t 2>&1 | FileCheck %s -// XFAIL: android - #include <stdio.h> +#if !defined(__GLIBC_PREREQ) +#define __GLIBC_PREREQ(a, b) 0 +#endif + // getauxval() used instead of sysconf() in GetPageSize() is defined starting // glbc version 2.16. -#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 16) +#if __GLIBC_PREREQ(2, 16) extern "C" long sysconf(int name) { fprintf(stderr, "sysconf wrapper called\n"); return 0; diff --git a/test/sanitizer_common/TestCases/NetBSD/faccessat.cc b/test/sanitizer_common/TestCases/NetBSD/faccessat.cc new file mode 100644 index 000000000000..ae8be1962b8c --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/faccessat.cc @@ -0,0 +1,6 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <fcntl.h> +#include <unistd.h> + +int main(void) { return faccessat(AT_FDCWD, "/root", F_OK, 0); } diff --git a/test/sanitizer_common/TestCases/NetBSD/getgrouplist.cc b/test/sanitizer_common/TestCases/NetBSD/getgrouplist.cc new file mode 100644 index 000000000000..49655542ec6d --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/getgrouplist.cc @@ -0,0 +1,29 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <stdlib.h> +#include <unistd.h> +#include <grp.h> + +int main(void) { + gid_t *groups; + gid_t nobody; + int ngroups; + + ngroups = sysconf(_SC_NGROUPS_MAX); + groups = (gid_t *)malloc(ngroups * sizeof(gid_t)); + if (!groups) + exit(1); + + if (gid_from_group("nobody", &nobody) == -1) + exit(1); + + if (getgrouplist("nobody", nobody, groups, &ngroups)) + exit(1); + + if (groups && ngroups) { + free(groups); + exit(0); + } + + return -1; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/getgroupmembership.cc b/test/sanitizer_common/TestCases/NetBSD/getgroupmembership.cc new file mode 100644 index 000000000000..ee27ad6cf365 --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/getgroupmembership.cc @@ -0,0 +1,30 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <stdlib.h> +#include <unistd.h> +#include <grp.h> + +int main(void) { + gid_t *groups; + gid_t nobody; + int ngroups; + int maxgrp; + + maxgrp = sysconf(_SC_NGROUPS_MAX); + groups = (gid_t *)malloc(maxgrp * sizeof(gid_t)); + if (!groups) + exit(1); + + if (gid_from_group("nobody", &nobody) == -1) + exit(1); + + if (getgroupmembership("nobody", nobody, groups, maxgrp, &ngroups)) + exit(1); + + if (groups && ngroups) { + free(groups); + exit(0); + } + + return -1; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/gid_from_group.cc b/test/sanitizer_common/TestCases/NetBSD/gid_from_group.cc new file mode 100644 index 000000000000..c6a9bc97c1e8 --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/gid_from_group.cc @@ -0,0 +1,16 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <grp.h> +#include <stdlib.h> + +int main(void) { + gid_t nobody; + + if (gid_from_group("nobody", &nobody) == -1) + exit(1); + + if (nobody) + exit(0); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/group_from_gid.cc b/test/sanitizer_common/TestCases/NetBSD/group_from_gid.cc new file mode 100644 index 000000000000..eb39da7b2b50 --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/group_from_gid.cc @@ -0,0 +1,17 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <grp.h> +#include <stdlib.h> +#include <string.h> + +int main(void) { + const char *nobody; + + if (!(nobody = group_from_gid(0, 0))) + exit(1); + + if (strlen(nobody)) + exit(0); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/lit.local.cfg b/test/sanitizer_common/TestCases/NetBSD/lit.local.cfg new file mode 100644 index 000000000000..94023561ffe3 --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/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 ['NetBSD']: + config.unsupported = True diff --git a/test/sanitizer_common/TestCases/NetBSD/netent.cc b/test/sanitizer_common/TestCases/NetBSD/netent.cc new file mode 100644 index 000000000000..b574a931082c --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/netent.cc @@ -0,0 +1,84 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s + +#include <inttypes.h> +#include <netdb.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#define STRING_OR_NULL(x) ((x) ? (x) : "null") + +void test1() { + struct netent *ntp = getnetent(); + + printf("%s ", ntp->n_name); + + for (char **cp = ntp->n_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d ", ntp->n_addrtype); + printf("%" PRIu32 "\n", ntp->n_net); + + endnetent(); +} + +void test2() { + struct netent *ntp = getnetbyname("loopback"); + + printf("%s ", ntp->n_name); + + for (char **cp = ntp->n_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d ", ntp->n_addrtype); + printf("%" PRIu32 "\n", ntp->n_net); + + endnetent(); +} + +void test3() { + struct netent *ntp = getnetbyaddr(127, 2); + + printf("%s ", ntp->n_name); + + for (char **cp = ntp->n_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d ", ntp->n_addrtype); + printf("%" PRIu32 "\n", ntp->n_net); + + endnetent(); +} + +void test4() { + setnetent(1); + + struct netent *ntp = getnetent(); + + printf("%s ", ntp->n_name); + + for (char **cp = ntp->n_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d ", ntp->n_addrtype); + printf("%" PRIu32 "\n", ntp->n_net); + + endnetent(); +} + +int main(void) { + printf("netent\n"); + + test1(); + test2(); + test3(); + test4(); + + // CHECK: netent + // CHECK: loopback 2 127 + // CHECK: loopback 2 127 + // CHECK: loopback 2 127 + // CHECK: loopback 2 127 + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/paccept.cc b/test/sanitizer_common/TestCases/NetBSD/paccept.cc new file mode 100644 index 000000000000..7d2eb4e85596 --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/paccept.cc @@ -0,0 +1,74 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <signal.h> +#include <stdlib.h> +#include <unistd.h> + +int main(void) { + int child; + int fd, sfd; + socklen_t len; + struct sockaddr_in server = {}, client = {}; + sigset_t set; + + child = fork(); + if (child == 0) { + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + _exit(1); + + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(2222); + + if (connect(fd, (struct sockaddr *)&server, sizeof(server)) == -1) + _exit(1); + + close(fd); + + _exit(0); + } + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) { + kill(child, SIGKILL); + wait(NULL); + exit(1); + } + + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = htons(2222); + + if (bind(fd, (const struct sockaddr *)&server, sizeof(server)) == -1) { + kill(child, SIGKILL); + wait(NULL); + exit(1); + } + + listen(fd, 3); + + if (sigemptyset(&set) == -1) { + kill(child, SIGKILL); + wait(NULL); + exit(1); + } + + len = sizeof(client); + sfd = paccept(fd, (struct sockaddr *)&client, &len, &set, SOCK_NONBLOCK); + if (sfd == -1) { + kill(child, SIGKILL); + wait(NULL); + exit(1); + } + + wait(NULL); + + close(sfd); + close(fd); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/protoent.cc b/test/sanitizer_common/TestCases/NetBSD/protoent.cc new file mode 100644 index 000000000000..c88c6f904a49 --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/protoent.cc @@ -0,0 +1,89 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s + +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> + +#define STRING_OR_NULL(x) ((x) ? (x) : "null") + +void test1() { + struct protoent *ptp = getprotoent(); + + printf("%s ", STRING_OR_NULL(ptp->p_name)); + + for (char **cp = ptp->p_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d\n", ptp->p_proto); + endprotoent(); +} + +void test2() { + struct protoent *ptp = getprotobyname("icmp"); + + printf("%s ", STRING_OR_NULL(ptp->p_name)); + + for (char **cp = ptp->p_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d\n", ptp->p_proto); + endprotoent(); +} + +void test3() { + struct protoent *ptp = getprotobynumber(1); + + printf("%s ", STRING_OR_NULL(ptp->p_name)); + + for (char **cp = ptp->p_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d\n", ptp->p_proto); + endprotoent(); +} + +void test4() { + setprotoent(1); + struct protoent *ptp = getprotobynumber(1); + + ptp = getprotobynumber(2); + + printf("%s ", STRING_OR_NULL(ptp->p_name)); + + for (char **cp = ptp->p_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d\n", ptp->p_proto); + endprotoent(); +} + +void test5() { + struct protoent *ptp = getprotobyname("ttp"); + + printf("%s ", STRING_OR_NULL(ptp->p_name)); + + for (char **cp = ptp->p_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d\n", ptp->p_proto); + endprotoent(); +} + +int main(void) { + printf("protoent\n"); + + test1(); + test2(); + test3(); + test4(); + test5(); + + // CHECK: protoent + // CHECK: hopopt HOPOPT 0 + // CHECK: icmp ICMP 1 + // CHECK: icmp ICMP 1 + // CHECK: igmp IGMP 2 + // CHECK: ttp TTP iptm IPTM 84 + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/strmode.cc b/test/sanitizer_common/TestCases/NetBSD/strmode.cc new file mode 100644 index 000000000000..b8d7d8ccf5a2 --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/strmode.cc @@ -0,0 +1,20 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> + +int main(void) { + struct stat st; + char modep[15]; + + if (stat("/etc/hosts", &st)) + exit(1); + + strmode(st.st_mode, modep); + + printf("%s\n", modep); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/ttyent.cc b/test/sanitizer_common/TestCases/NetBSD/ttyent.cc new file mode 100644 index 000000000000..73bc0a5da56b --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/ttyent.cc @@ -0,0 +1,70 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s + +#include <stdio.h> +#include <stdlib.h> +#include <ttyent.h> + +#define STRING_OR_NULL(x) ((x) ? (x) : "null") + +void test1() { + struct ttyent *typ = getttyent(); + + printf("%s %s %s %d %s %s %s\n", STRING_OR_NULL(typ->ty_name), + STRING_OR_NULL(typ->ty_getty), STRING_OR_NULL(typ->ty_type), + typ->ty_status, STRING_OR_NULL(typ->ty_window), + STRING_OR_NULL(typ->ty_comment), STRING_OR_NULL(typ->ty_class)); + + endttyent(); +} + +void test2() { + struct ttyent *typ = getttynam("console"); + + printf("%s %s %s %d %s %s %s\n", STRING_OR_NULL(typ->ty_name), + STRING_OR_NULL(typ->ty_getty), STRING_OR_NULL(typ->ty_type), + typ->ty_status, STRING_OR_NULL(typ->ty_window), + STRING_OR_NULL(typ->ty_comment), STRING_OR_NULL(typ->ty_class)); + + endttyent(); +} + +void test3() { + if (!setttyent()) + exit(1); + + struct ttyent *typ = getttyent(); + + printf("%s %s %s %d %s %s %s\n", STRING_OR_NULL(typ->ty_name), + STRING_OR_NULL(typ->ty_getty), STRING_OR_NULL(typ->ty_type), + typ->ty_status, STRING_OR_NULL(typ->ty_window), + STRING_OR_NULL(typ->ty_comment), STRING_OR_NULL(typ->ty_class)); + + endttyent(); +} + +void test4() { + if (!setttyentpath(_PATH_TTYS)) + exit(1); + + struct ttyent *typ = getttyent(); + + printf("%s %s %s %d %s %s %s\n", STRING_OR_NULL(typ->ty_name), + STRING_OR_NULL(typ->ty_getty), STRING_OR_NULL(typ->ty_type), + typ->ty_status, STRING_OR_NULL(typ->ty_window), + STRING_OR_NULL(typ->ty_comment), STRING_OR_NULL(typ->ty_class)); + + endttyent(); +} + +int main(void) { + printf("ttyent\n"); + + test1(); + test2(); + test3(); + test4(); + + // CHECK: ttyent + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/uid_from_user.cc b/test/sanitizer_common/TestCases/NetBSD/uid_from_user.cc new file mode 100644 index 000000000000..4cc1366aad4b --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/uid_from_user.cc @@ -0,0 +1,16 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <pwd.h> +#include <stdlib.h> + +int main(void) { + uid_t nobody; + + if (uid_from_user("nobody", &nobody) == -1) + exit(1); + + if (nobody) + exit(0); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/NetBSD/user_from_uid.cc b/test/sanitizer_common/TestCases/NetBSD/user_from_uid.cc new file mode 100644 index 000000000000..bb098525a476 --- /dev/null +++ b/test/sanitizer_common/TestCases/NetBSD/user_from_uid.cc @@ -0,0 +1,17 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <pwd.h> +#include <stdlib.h> +#include <string.h> + +int main(void) { + const char *nobody; + + if (!(nobody = user_from_uid(0, 0))) + exit(1); + + if (strlen(nobody)) + exit(0); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/access.cc b/test/sanitizer_common/TestCases/Posix/access.cc new file mode 100644 index 000000000000..8623645f8bdf --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/access.cc @@ -0,0 +1,5 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <unistd.h> + +int main(void) { return access("/dev/null", F_OK); } diff --git a/test/sanitizer_common/TestCases/Posix/devname.cc b/test/sanitizer_common/TestCases/Posix/devname.cc new file mode 100644 index 000000000000..da4bb8853a12 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/devname.cc @@ -0,0 +1,23 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: linux, solaris + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> + +int main(void) { + struct stat st; + char *name; + + if (stat("/dev/null", &st)) + exit(1); + + if (!(name = devname(st.st_rdev, S_ISCHR(st.st_mode) ? S_IFCHR : S_IFBLK))) + exit(1); + + printf("%s\n", name); + + // CHECK: null + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/devname_r.cc b/test/sanitizer_common/TestCases/Posix/devname_r.cc new file mode 100644 index 000000000000..826b7c92ef2f --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/devname_r.cc @@ -0,0 +1,28 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: linux, solaris + +#include <sys/cdefs.h> +#include <sys/stat.h> + +#include <stdio.h> +#include <stdlib.h> + +int main(void) { + struct stat st; + char name[100]; + mode_t type; + + if (stat("/dev/null", &st)) + exit(1); + + type = S_ISCHR(st.st_mode) ? S_IFCHR : S_IFBLK; + + if (!devname_r(st.st_rdev, type, name, sizeof(name))) + exit(1); + + printf("%s\n", name); + + // CHECK: null + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/fgetln.cc b/test/sanitizer_common/TestCases/Posix/fgetln.cc new file mode 100644 index 000000000000..e98cf449a272 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/fgetln.cc @@ -0,0 +1,24 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t +// UNSUPPORTED: linux + +#include <stdio.h> +#include <stdlib.h> + +int main(void) { + FILE *fp; + size_t len; + char *s; + + fp = fopen("/etc/hosts", "r"); + if (!fp) + exit(1); + + s = fgetln(fp, &len); + + printf("%.*s\n", (int)len, s); + + if (fclose(fp) == EOF) + exit(1); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/fgets.cc b/test/sanitizer_common/TestCases/Posix/fgets.cc new file mode 100644 index 000000000000..8dde5cd1a84f --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/fgets.cc @@ -0,0 +1,20 @@ +// RUN: %clangxx -g %s -o %t && %run %t + +#include <stdio.h> + +int main(int argc, char **argv) { + FILE *fp; + char buf[2]; + char *s; + + fp = fopen(argv[0], "r"); + if (!fp) + return 1; + + s = fgets(buf, sizeof(buf), fp); + if (!s) + return 2; + + fclose(fp); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/fputs_puts.cc b/test/sanitizer_common/TestCases/Posix/fputs_puts.cc new file mode 100644 index 000000000000..8e8f7d384e8c --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/fputs_puts.cc @@ -0,0 +1,18 @@ +// RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s +// CHECK: {{^foobar$}} + +#include <stdio.h> + +int main(void) { + int r; + + r = fputs("foo", stdout); + if (r < 0) + return 1; + + r = puts("bar"); + if (r < 0) + return 1; + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/getpass.cc b/test/sanitizer_common/TestCases/Posix/getpass.cc index b91a3d7d5264..bf198eff91d2 100644 --- a/test/sanitizer_common/TestCases/Posix/getpass.cc +++ b/test/sanitizer_common/TestCases/Posix/getpass.cc @@ -5,13 +5,19 @@ #include <assert.h> #include <stdio.h> -#include <unistd.h> #include <string.h> #if __linux__ #include <pty.h> +#elif defined(__FreeBSD__) +#include <libutil.h> +#include <pwd.h> +#include <sys/ioctl.h> +#include <sys/termios.h> +#include <sys/types.h> #else #include <util.h> #endif +#include <unistd.h> int main (int argc, char** argv) diff --git a/test/sanitizer_common/TestCases/Posix/illegal_read_test.cc b/test/sanitizer_common/TestCases/Posix/illegal_read_test.cc new file mode 100644 index 000000000000..9615d7132da5 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/illegal_read_test.cc @@ -0,0 +1,15 @@ +// Test that there was an illegal READ memory access. +// RUN: %clangxx -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// REQUIRES: stable-runtime +// XFAIL: powerpc64, s390x + +volatile int *null = 0; +volatile int a; + +int main(int argc, char **argv) { + a = *null; + return 0; +} + +// CHECK: The signal is caused by a READ memory access. diff --git a/test/sanitizer_common/TestCases/Posix/illegal_write_test.cc b/test/sanitizer_common/TestCases/Posix/illegal_write_test.cc new file mode 100644 index 000000000000..13d1c6a06905 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/illegal_write_test.cc @@ -0,0 +1,14 @@ +// Test that there was an illegal WRITE memory access. +// RUN: %clangxx -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// REQUIRES: stable-runtime +// XFAIL: powerpc64, s390x + +volatile int *null = 0; + +int main(int argc, char **argv) { + *null = 0; + return 0; +} + +// CHECK: The signal is caused by a WRITE memory access. diff --git a/test/sanitizer_common/TestCases/Posix/lstat.cc b/test/sanitizer_common/TestCases/Posix/lstat.cc new file mode 100644 index 000000000000..37237d82102c --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/lstat.cc @@ -0,0 +1,16 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <stdlib.h> +#include <sys/stat.h> + +int main(void) { + struct stat st; + + if (lstat("/dev/null", &st)) + exit(1); + + if (!S_ISCHR(st.st_mode)) + exit(1); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/mmap_test.c b/test/sanitizer_common/TestCases/Posix/mmap_test.c new file mode 100644 index 000000000000..3c272f95a015 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/mmap_test.c @@ -0,0 +1,11 @@ +// RUN: %clang %s -o %t && %run %t + +#include <assert.h> +#include <sys/mman.h> + +int main() { + char *buf = (char *)mmap(0, 100000, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + assert(buf); + munmap(buf, 100000); +} diff --git a/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc b/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc new file mode 100644 index 000000000000..7729057d2deb --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc @@ -0,0 +1,47 @@ +// RUN: %clangxx %collect_stack_traces -O0 %s -o %t + +// Alignment is not a power of two: +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 17 2>&1 | FileCheck %s +// Alignment is not a power of two, although is a multiple of sizeof(void*): +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 24 2>&1 | FileCheck %s +// Alignment is not a multiple of sizeof(void*), although is a power of 2: +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 2 2>&1 | FileCheck %s +// Alignment is 0: +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 0 2>&1 | FileCheck %s + +// The same for allocator_may_return_null=1: +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 17 2>&1 | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 24 2>&1 | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL + +// REQUIRES: stable-runtime + +// UNSUPPORTED: ubsan + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +int main(int argc, char **argv) { + assert(argc == 2); + const int alignment = atoi(argv[1]); + + void* const kInitialPtrValue = reinterpret_cast<void*>(0x2a); + void *p = kInitialPtrValue; + + errno = 0; + int res = posix_memalign(&p, alignment, 100); + // CHECK: {{ERROR: .*Sanitizer: invalid alignment requested in posix_memalign}} + // CHECK: {{#0 .*posix_memalign}} + // CHECK: {{#1 .*main .*posix_memalign-alignment.cc:}}[[@LINE-3]] + // CHECK: {{SUMMARY: .*Sanitizer: invalid-posix-memalign-alignment}} + + // The NULL pointer is printed differently on different systems, while (long)0 + // is always the same. + fprintf(stderr, "errno: %d, res: %d, p: %lx\n", errno, res, (long)p); + // CHECK-NULL: errno: 0, res: 22, p: 2a + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/readlink.c b/test/sanitizer_common/TestCases/Posix/readlink.c new file mode 100644 index 000000000000..ef0a4fe358b0 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/readlink.c @@ -0,0 +1,26 @@ +// RUN: %clang -O0 %s -o %t && %run %t + +#include <assert.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> + +int main(int argc, char **argv) { + char symlink_path[PATH_MAX]; + snprintf(symlink_path, sizeof(symlink_path), "%s_%d.symlink", argv[0], + getpid()); + remove(symlink_path); + int res = symlink(argv[0], symlink_path); + assert(!res); + + char readlink_path[PATH_MAX]; + ssize_t res2 = readlink(symlink_path, readlink_path, sizeof(readlink_path)); + assert(res2 >= 0); + readlink_path[res2] = '\0'; + assert(!strcmp(readlink_path, argv[0])); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/readlinkat.c b/test/sanitizer_common/TestCases/Posix/readlinkat.c new file mode 100644 index 000000000000..0afb5efe6b5f --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/readlinkat.c @@ -0,0 +1,26 @@ +// RUN: %clang -O0 %s -o %t && %run %t + +#include <assert.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +int main(int argc, char **argv) { + char symlink_path[PATH_MAX]; + snprintf(symlink_path, sizeof(symlink_path), "%s_%d.symlink", argv[0], + getpid()); + remove(symlink_path); + int res = symlink(argv[0], symlink_path); + assert(!res); + + char readlinkat_path[PATH_MAX]; + int res2 = readlinkat(AT_FDCWD, symlink_path, readlinkat_path, + sizeof(readlinkat_path)); + assert(res2 >= 0); + readlinkat_path[res2] = '\0'; + assert(!strcmp(readlinkat_path, argv[0])); + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc b/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc index 8d2db364114a..54272b017504 100644 --- a/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc +++ b/test/sanitizer_common/TestCases/Posix/sanitizer_set_death_callback_test.cc @@ -2,12 +2,6 @@ // REQUIRES: stable-runtime -// For standalone LSan on x86 we have a problem: compiler spills the address -// of allocated at line 42 memory thus memory block allocated in Leak() function -// ends up to be classified as reachable despite the fact we zero out 'sink' at -// the last line of main function. The problem doesn't reproduce with ASan because -// quarantine prohibits memory block reuse for different allocations. -// XFAIL: lsan-x86 // XFAIL: ubsan #include <sanitizer/common_interface_defs.h> @@ -31,7 +25,10 @@ void MaybeInit(int *uninitialized) { __attribute__((noinline)) void Leak() { - sink = new char[100]; // trigger lsan report. + // Trigger lsan report. Two attempts in case the address of the first + // allocation remained on the stack. + sink = new char[100]; + sink = new char[100]; } int main(int argc, char **argv) { diff --git a/test/sanitizer_common/TestCases/Posix/strlcat.cc b/test/sanitizer_common/TestCases/Posix/strlcat.cc new file mode 100644 index 000000000000..bdabada76aa7 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/strlcat.cc @@ -0,0 +1,54 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +// UNSUPPORTED: linux + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void test1() { + const char src[] = "abc"; + char dst[7] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void test2() { + const char src[] = "abc"; + char dst[7] = {0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void test3() { + const char src[] = "abc"; + char dst[4] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void test4() { + const char src[] = ""; + char dst[4] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu\n", dst, len); +} + +int main(void) { + test1(); + test2(); + test3(); + test4(); + + // CHECK: xyzabc 6 abc 3 xyz 3 xyz 3 + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/strlcpy.cc b/test/sanitizer_common/TestCases/Posix/strlcpy.cc new file mode 100644 index 000000000000..83053911d965 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/strlcpy.cc @@ -0,0 +1,54 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +// UNSUPPORTED: linux + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void test1() { + const char src[] = "abc"; + char dst[7] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcpy(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void test2() { + const char src[] = "abc"; + char dst[7] = {0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void test3() { + const char src[] = "abc"; + char dst[4] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu ", dst, len); +} + +void test4() { + const char src[] = ""; + char dst[4] = {'x', 'y', 'z', 0}; + size_t len; + + len = strlcat(dst, src, sizeof(dst)); + printf("%s %zu\n", dst, len); +} + +int main(void) { + test1(); + test2(); + test3(); + test4(); + + // CHECK: abc 3 abc 3 xyz 3 0 + + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/strxfrm.c b/test/sanitizer_common/TestCases/Posix/strxfrm.c new file mode 100644 index 000000000000..c28eb65b7d4f --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/strxfrm.c @@ -0,0 +1,20 @@ +// RUN: %clang -O0 %s -o %t && %run %t +// UNSUPPORTED: darwin + +#include <assert.h> +#include <locale.h> +#include <wchar.h> + +int main(int argc, char **argv) { + char q[10]; + size_t n = strxfrm(q, "abcdef", sizeof(q)); + assert(n < sizeof(q)); + + char q2[10]; + locale_t loc = newlocale(LC_ALL_MASK, "", (locale_t)0); + n = strxfrm_l(q2, L"qwerty", sizeof(q), loc); + assert(n < sizeof(q2)); + + freelocale(loc); + return 0; +} diff --git a/test/sanitizer_common/TestCases/Posix/wcsxfrm.c b/test/sanitizer_common/TestCases/Posix/wcsxfrm.c new file mode 100644 index 000000000000..3e349c75f409 --- /dev/null +++ b/test/sanitizer_common/TestCases/Posix/wcsxfrm.c @@ -0,0 +1,20 @@ +// RUN: %clang -O0 %s -o %t && %run %t +// UNSUPPORTED: darwin + +#include <assert.h> +#include <locale.h> +#include <wchar.h> + +int main(int argc, char **argv) { + wchar_t q[10]; + size_t n = wcsxfrm(q, L"abcdef", sizeof(q) / sizeof(wchar_t)); + assert(n < sizeof(q)); + + wchar_t q2[10]; + locale_t loc = newlocale(LC_ALL_MASK, "", (locale_t)0); + n = wcsxfrm_l(q2, L"qwerty", sizeof(q) / sizeof(wchar_t), loc); + assert(n < sizeof(q2)); + + freelocale(loc); + return 0; +} diff --git a/test/sanitizer_common/TestCases/allocator_returns_null.cc b/test/sanitizer_common/TestCases/allocator_returns_null.cc new file mode 100644 index 000000000000..9ecdfef9ffcd --- /dev/null +++ b/test/sanitizer_common/TestCases/allocator_returns_null.cc @@ -0,0 +1,114 @@ +// Test the behavior of malloc/calloc/realloc/new when the allocation size +// exceeds the sanitizer's allocator max allowed one. +// By default (allocator_may_return_null=0) the process should crash. With +// allocator_may_return_null=1 the allocator should return nullptr and set errno +// to the appropriate error code. +// +// RUN: %clangxx -O0 %s -o %t +// RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-mCRASH +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t malloc 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-cCRASH +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t calloc 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-coCRASH +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t calloc-overflow 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-rCRASH +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t realloc 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-mrCRASH +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t realloc-after-malloc 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t new 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH +// RUN: %env_tool_opts=allocator_may_return_null=1 not %run %t new 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH-OOM +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NULL + +// TODO(alekseyshl): win32 is disabled due to failing errno tests, fix it there. +// UNSUPPORTED: ubsan, win32 + +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits> +#include <new> + +int main(int argc, char **argv) { + assert(argc == 2); + const char *action = argv[1]; + fprintf(stderr, "%s:\n", action); + + // The maximum value of all supported sanitizers (search for + // kMaxAllowedMallocSize). For ASan + LSan, ASan limit is used. + static const size_t kMaxAllowedMallocSizePlusOne = +#if __LP64__ || defined(_WIN64) + (1ULL << 40) + 1; +#else + (3UL << 30) + 1; +#endif + + void *x = nullptr; + if (!strcmp(action, "malloc")) { + x = malloc(kMaxAllowedMallocSizePlusOne); + } else if (!strcmp(action, "calloc")) { + x = calloc((kMaxAllowedMallocSizePlusOne / 4) + 1, 4); + } else if (!strcmp(action, "calloc-overflow")) { + volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max(); + size_t kArraySize = 4096; + volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10; + x = calloc(kArraySize, kArraySize2); + } else if (!strcmp(action, "realloc")) { + x = realloc(0, kMaxAllowedMallocSizePlusOne); + } else if (!strcmp(action, "realloc-after-malloc")) { + char *t = (char*)malloc(100); + *t = 42; + x = realloc(t, kMaxAllowedMallocSizePlusOne); + assert(*t == 42); + free(t); + } else if (!strcmp(action, "new")) { + x = operator new(kMaxAllowedMallocSizePlusOne); + } else if (!strcmp(action, "new-nothrow")) { + x = operator new(kMaxAllowedMallocSizePlusOne, std::nothrow); + } else { + assert(0); + } + + // The NULL pointer is printed differently on different systems, while (long)0 + // is always the same. + fprintf(stderr, "errno: %d, x: %lx\n", errno, (long)x); + + return 0; +} + +// CHECK-mCRASH: malloc: +// CHECK-mCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} +// CHECK-cCRASH: calloc: +// CHECK-cCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} +// CHECK-coCRASH: calloc-overflow: +// CHECK-coCRASH: {{SUMMARY: .*Sanitizer: calloc-overflow}} +// CHECK-rCRASH: realloc: +// CHECK-rCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} +// CHECK-mrCRASH: realloc-after-malloc: +// CHECK-mrCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} +// CHECK-nCRASH: new: +// CHECK-nCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} +// CHECK-nCRASH-OOM: new: +// CHECK-nCRASH-OOM: {{SUMMARY: .*Sanitizer: out-of-memory}} +// CHECK-nnCRASH: new-nothrow: +// CHECK-nnCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}} + +// CHECK-NULL: {{malloc|calloc|calloc-overflow|realloc|realloc-after-malloc|new-nothrow}} +// CHECK-NULL: errno: 12, x: 0 diff --git a/test/sanitizer_common/TestCases/ctype.c b/test/sanitizer_common/TestCases/ctype.c new file mode 100644 index 000000000000..37e0af89be6d --- /dev/null +++ b/test/sanitizer_common/TestCases/ctype.c @@ -0,0 +1,89 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 | FileCheck %s + +#include <ctype.h> +#include <limits.h> +#include <locale.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> + +void check_ctype(void) { + unsigned char c; + volatile size_t i = 0; /* a dummy variable to prevent optimizing code out */ + + for (c = 0; c < UCHAR_MAX; c++) + i += !!isalpha(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isascii(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isblank(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!iscntrl(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isdigit(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isgraph(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!islower(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isprint(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!ispunct(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isspace(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isupper(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isxdigit(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!isalnum(c); + + for (c = 0; c < UCHAR_MAX; c++) + i += !!tolower(c); + for (c = 0; c < UCHAR_MAX; c++) + i += !!toupper(c); + + i += !!isalpha(EOF); + i += !!isascii(EOF); + i += !!isblank(EOF); + i += !!iscntrl(EOF); + i += !!isdigit(EOF); + i += !!isgraph(EOF); + i += !!islower(EOF); + i += !!isprint(EOF); + i += !!ispunct(EOF); + i += !!isspace(EOF); + i += !!isupper(EOF); + i += !!isxdigit(EOF); + i += !!isalnum(EOF); + + i += !!tolower(EOF); + i += !!toupper(EOF); + + if (i) + return; + else + return; +} + +int main(int argc, char **argv) { + check_ctype(); + + setlocale(LC_ALL, ""); + + check_ctype(); + + setlocale(LC_ALL, "en_US.UTF-8"); + + check_ctype(); + + setlocale(LC_CTYPE, "pl_PL.UTF-8"); + + check_ctype(); + + printf("OK\n"); + + // CHECK: OK + + return 0; +} diff --git a/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc b/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc index 69ccb7234fab..0591d356f136 100644 --- a/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc +++ b/test/sanitizer_common/TestCases/get_module_and_offset_for_pc.cc @@ -1,5 +1,6 @@ -// RUN: %clangxx -DSHARED %s -shared -o %T/get_module_and_offset_for_pc.so -fPIC -// RUN: %clangxx -DSO_DIR=\"%T\" -O0 %s -ldl -o %t +// RUN: mkdir -p %t-dir +// RUN: %clangxx -DSHARED %s -shared -o %t-dir/get_module_and_offset_for_pc.so -fPIC +// RUN: %clangxx -DSO_DIR=\"%t-dir\" -O0 %s -ldl -o %t // RUN: %run %t 2>&1 | FileCheck %s // UNSUPPORTED: i386-darwin diff --git a/test/sanitizer_common/ios_commands/iossim_prepare.py b/test/sanitizer_common/ios_commands/iossim_prepare.py new file mode 100755 index 000000000000..4b618fe9de8a --- /dev/null +++ b/test/sanitizer_common/ios_commands/iossim_prepare.py @@ -0,0 +1,5 @@ +#!/usr/bin/python + +import os, sys, subprocess, json + +print(json.dumps({"env": {}})) diff --git a/test/sanitizer_common/lit.common.cfg b/test/sanitizer_common/lit.common.cfg index c7a1682f7404..1b347bf2bbac 100644 --- a/test/sanitizer_common/lit.common.cfg +++ b/test/sanitizer_common/lit.common.cfg @@ -6,6 +6,7 @@ config.test_source_root = os.path.join(os.path.dirname(__file__), "TestCases") config.name = "SanitizerCommon-" + config.name_suffix default_tool_options = [] +collect_stack_traces = "" if config.tool_name == "asan": tool_cflags = ["-fsanitize=address"] tool_options = "ASAN_OPTIONS" @@ -15,6 +16,7 @@ elif config.tool_name == "tsan": elif config.tool_name == "msan": tool_cflags = ["-fsanitize=memory"] tool_options = "MSAN_OPTIONS" + collect_stack_traces = "-fsanitize-memory-track-origins" elif config.tool_name == "lsan": tool_cflags = ["-fsanitize=leak"] tool_options = "LSAN_OPTIONS" @@ -52,6 +54,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( ("%collect_stack_traces", collect_stack_traces) ) config.substitutions.append( ("%tool_name", config.tool_name) ) config.substitutions.append( ("%tool_options", tool_options) ) config.substitutions.append( ('%env_tool_opts=', @@ -59,5 +62,5 @@ config.substitutions.append( ('%env_tool_opts=', config.suffixes = ['.c', '.cc', '.cpp'] -if config.host_os not in ['Linux', 'Darwin']: +if config.host_os not in ['Linux', 'Darwin', 'NetBSD', 'FreeBSD']: config.unsupported = True diff --git a/test/scudo/aligned-new.cpp b/test/scudo/aligned-new.cpp new file mode 100644 index 000000000000..0a10ae188c92 --- /dev/null +++ b/test/scudo/aligned-new.cpp @@ -0,0 +1,86 @@ +// RUN: %clangxx_scudo -std=c++1z -faligned-allocation %s -o %t +// RUN: %run %t valid 2>&1 +// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1 +// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t invalid 2>&1 | FileCheck %s + +// Tests that the C++17 aligned new/delete operators are working as expected. +// Currently we do not check the consistency of the alignment on deallocation, +// so this just tests that the APIs work. + +#include <assert.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +// Define all new/delete to not depend on the version provided by the platform. + +namespace std { +struct nothrow_t {}; +static const nothrow_t nothrow; +enum class align_val_t : size_t {}; +} // namespace std + +void *operator new(size_t); +void *operator new[](size_t); +void *operator new(size_t, std::nothrow_t const&); +void *operator new[](size_t, std::nothrow_t const&); +void *operator new(size_t, std::align_val_t); +void *operator new[](size_t, std::align_val_t); +void *operator new(size_t, std::align_val_t, std::nothrow_t const&); +void *operator new[](size_t, std::align_val_t, std::nothrow_t const&); + +void operator delete(void*) throw(); +void operator delete[](void*) throw(); +void operator delete(void*, std::nothrow_t const&); +void operator delete[](void*, std::nothrow_t const&); +void operator delete(void*, size_t) throw(); +void operator delete[](void*, size_t) throw(); +void operator delete(void*, std::align_val_t) throw(); +void operator delete[](void*, std::align_val_t) throw(); +void operator delete(void*, std::align_val_t, std::nothrow_t const&); +void operator delete[](void*, std::align_val_t, std::nothrow_t const&); +void operator delete(void*, size_t, std::align_val_t) throw(); +void operator delete[](void*, size_t, std::align_val_t) throw(); + +template<typename T> +inline T* break_optimization(T *arg) { + __asm__ __volatile__("" : : "r" (arg) : "memory"); + return arg; +} + +struct S12 { int a, b, c; }; +struct alignas(128) S12_128 { int a, b, c; }; +struct alignas(256) S12_256 { int a, b, c; }; +struct alignas(512) S1024_512 { char a[1024]; }; +struct alignas(1024) S1024_1024 { char a[1024]; }; + +int main(int argc, char **argv) { + assert(argc == 2); + + if (!strcmp(argv[1], "valid")) { + // Standard use case. + delete break_optimization(new S12); + delete break_optimization(new S12_128); + delete[] break_optimization(new S12_128[4]); + delete break_optimization(new S12_256); + delete break_optimization(new S1024_512); + delete[] break_optimization(new S1024_512[4]); + delete break_optimization(new S1024_1024); + + // Call directly the aligned versions of the operators. + const size_t alignment = 1U << 8; + void *p = operator new(1, static_cast<std::align_val_t>(alignment)); + assert((reinterpret_cast<uintptr_t>(p) & (alignment - 1)) == 0); + operator delete(p, static_cast<std::align_val_t>(alignment)); + } + if (!strcmp(argv[1], "invalid")) { + // Alignment must be a power of 2. + const size_t alignment = (1U << 8) - 1; + void *p = operator new(1, static_cast<std::align_val_t>(alignment), + std::nothrow); + // CHECK: Scudo ERROR: invalid allocation alignment + assert(!p); + } + + return 0; +} diff --git a/test/scudo/alignment.c b/test/scudo/alignment.c index 6235d50608db..4e2dc1af03b1 100644 --- a/test/scudo/alignment.c +++ b/test/scudo/alignment.c @@ -20,4 +20,4 @@ int main(int argc, char **argv) return 0; } -// CHECK: ERROR: attempted to deallocate a chunk not properly aligned +// CHECK: ERROR: misaligned pointer when deallocating address diff --git a/test/scudo/double-free.cpp b/test/scudo/double-free.cpp index 56118038cf1f..de6c90f1cced 100644 --- a/test/scudo/double-free.cpp +++ b/test/scudo/double-free.cpp @@ -2,7 +2,6 @@ // RUN: not %run %t malloc 2>&1 | FileCheck %s // RUN: not %run %t new 2>&1 | FileCheck %s // RUN: not %run %t newarray 2>&1 | FileCheck %s -// RUN: not %run %t memalign 2>&1 | FileCheck %s // Tests double-free error on pointers allocated with different allocation // functions. @@ -32,13 +31,6 @@ int main(int argc, char **argv) delete[] p; delete[] p; } - if (!strcmp(argv[1], "memalign")) { - void *p = nullptr; - posix_memalign(&p, 0x100, sizeof(int)); - assert(p); - free(p); - free(p); - } return 0; } diff --git a/test/scudo/fsanitize.c b/test/scudo/fsanitize.c new file mode 100644 index 000000000000..7e5d5451f726 --- /dev/null +++ b/test/scudo/fsanitize.c @@ -0,0 +1,28 @@ +// Test various -fsanitize= additional flags combinations. + +// RUN: %clang_scudo %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s + +// RUN: %clang_scudo -shared-libsan %s -o %t +// RUN: env LD_LIBRARY_PATH=`dirname %shared_libscudo`:$LD_LIBRARY_PATH not %run %t 2>&1 | FileCheck %s +// RUN: %clang_scudo -shared-libsan -fsanitize-minimal-runtime %s -o %t +// RUN: env LD_LIBRARY_PATH=`dirname %shared_minlibscudo`:$LD_LIBRARY_PATH not %run %t 2>&1 | FileCheck %s + +// RUN: %clang_scudo -static-libsan %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s +// RUN: %clang_scudo -static-libsan -fsanitize-minimal-runtime %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s + +#include <assert.h> +#include <stdlib.h> + +int main(int argc, char *argv[]) { + unsigned long *p = (unsigned long *)malloc(sizeof(unsigned long)); + assert(p); + *p = 0; + free(p); + free(p); + return 0; +} + +// CHECK: ERROR: invalid chunk state diff --git a/test/scudo/interface.cpp b/test/scudo/interface.cpp index 73ea0a738e43..ec7375193e12 100644 --- a/test/scudo/interface.cpp +++ b/test/scudo/interface.cpp @@ -4,7 +4,6 @@ // RUN: %run %t heap-size 2>&1 // RUN: %env_scudo_opts="allocator_may_return_null=1" %run %t soft-limit 2>&1 // RUN: %env_scudo_opts="allocator_may_return_null=1" not %run %t hard-limit 2>&1 -// UNSUPPORTED: armhf-linux // Tests that the sanitizer interface functions behave appropriately. @@ -51,8 +50,11 @@ int main(int argc, char **argv) // Verifies that setting the soft RSS limit at runtime works as expected. std::vector<void *> pointers; size_t size = 1 << 19; // 512Kb - for (int i = 0; i < 5; i++) - pointers.push_back(malloc(size)); + for (int i = 0; i < 5; i++) { + void *p = malloc(size); + memset(p, 0, size); + pointers.push_back(p); + } // Set the soft RSS limit to 1Mb. __scudo_set_rss_limit(1, 0); usleep(20000); @@ -74,8 +76,11 @@ int main(int argc, char **argv) // Verifies that setting the hard RSS limit at runtime works as expected. std::vector<void *> pointers; size_t size = 1 << 19; // 512Kb - for (int i = 0; i < 5; i++) - pointers.push_back(malloc(size)); + for (int i = 0; i < 5; i++) { + void *p = malloc(size); + memset(p, 0, size); + pointers.push_back(p); + } // Set the hard RSS limit to 1Mb __scudo_set_rss_limit(1, 1); usleep(20000); diff --git a/test/scudo/lit.cfg b/test/scudo/lit.cfg index 028bf721b89e..df78d5f9d6ad 100644 --- a/test/scudo/lit.cfg +++ b/test/scudo/lit.cfg @@ -8,16 +8,12 @@ config.name = 'Scudo' + config.name_suffix # Setup source root. config.test_source_root = os.path.dirname(__file__) -# Path to the shared & static libraries -shared_libscudo = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo-%s.so" % config.target_arch) -static_libscudo = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo-%s.a" % config.target_arch) -static_libscudo_cxx = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo_cxx-%s.a" % config.target_arch) - -whole_archive = "-Wl,-whole-archive %s -Wl,-no-whole-archive " % static_libscudo -whole_archive_cxx = "-Wl,-whole-archive %s -Wl,-no-whole-archive " % static_libscudo_cxx +# Path to the shared library +shared_libscudo = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo%s.so" % config.target_suffix) +shared_minlibscudo = os.path.join(config.compiler_rt_libdir, "libclang_rt.scudo_minimal-%s.so" % config.target_arch) # Test suffixes. -config.suffixes = ['.c', '.cc', '.cpp'] +config.suffixes = ['.c', '.cc', '.cpp', '.test'] # C & CXX flags. c_flags = ([config.target_cflags] + @@ -35,14 +31,17 @@ if not config.android: cxx_flags = (c_flags + config.cxx_mode_flags + ["-std=c++11"]) -def build_invocation(compile_flags): +scudo_flags = ["-fsanitize=scudo"] + +def build_invocation(compile_flags): return " " + " ".join([config.clang] + compile_flags) + " " -# Add clang substitutions. +# Add substitutions. config.substitutions.append(("%clang ", build_invocation(c_flags))) -config.substitutions.append(("%clang_scudo ", build_invocation(c_flags) + whole_archive)) -config.substitutions.append(("%clangxx_scudo ", build_invocation(cxx_flags) + whole_archive + whole_archive_cxx)) +config.substitutions.append(("%clang_scudo ", build_invocation(c_flags + scudo_flags))) +config.substitutions.append(("%clangxx_scudo ", build_invocation(cxx_flags + scudo_flags))) config.substitutions.append(("%shared_libscudo", shared_libscudo)) +config.substitutions.append(("%shared_minlibscudo", shared_minlibscudo)) # Platform-specific default SCUDO_OPTIONS for lit tests. default_scudo_opts = '' diff --git a/test/scudo/memalign.c b/test/scudo/memalign.c index 1fe6e3ec7eed..675f53415193 100644 --- a/test/scudo/memalign.c +++ b/test/scudo/memalign.c @@ -1,7 +1,10 @@ // RUN: %clang_scudo %s -o %t -// RUN: %run %t valid 2>&1 -// RUN: not %run %t invalid 2>&1 -// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1 +// RUN: %run %t valid 2>&1 +// RUN: not %run %t invalid 2>&1 | FileCheck --check-prefix=CHECK-align %s +// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1 +// RUN: not %run %t double-free 2>&1 | FileCheck --check-prefix=CHECK-double-free %s +// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t realloc 2>&1 | FileCheck --check-prefix=CHECK-realloc %s +// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t realloc 2>&1 // Tests that the various aligned allocation functions work as intended. Also // tests for the condition where the alignment is not a power of 2. @@ -51,6 +54,7 @@ int main(int argc, char **argv) // For larger alignment, reduce the number of allocations to avoid running // out of potential addresses (on 32-bit). for (int i = 19; i <= 24; i++) { + alignment = 1U << i; for (int k = 0; k < 3; k++) { p = memalign(alignment, 0x1000 - (2 * sizeof(void *) * k)); assert(p); @@ -62,6 +66,7 @@ int main(int argc, char **argv) if (!strcmp(argv[1], "invalid")) { // Alignment is not a power of 2. p = memalign(alignment - 1, size); + // CHECK-align: Scudo ERROR: invalid allocation alignment assert(!p); // Size is not a multiple of alignment. p = aligned_alloc(alignment, size >> 1); @@ -77,5 +82,22 @@ int main(int argc, char **argv) assert(p == p_unchanged); assert(err == EINVAL); } + if (!strcmp(argv[1], "double-free")) { + void *p = NULL; + posix_memalign(&p, 0x100, sizeof(int)); + assert(p); + free(p); + free(p); + } + if (!strcmp(argv[1], "realloc")) { + // We cannot reallocate a memalign'd chunk. + void *p = memalign(16, 16); + assert(p); + p = realloc(p, 32); + free(p); + } return 0; } + +// CHECK-double-free: ERROR: invalid chunk state +// CHECK-realloc: ERROR: allocation type mismatch when reallocating address diff --git a/test/scudo/mismatch.cpp b/test/scudo/mismatch.cpp index b49e0ea46f12..b794f66d8a4e 100644 --- a/test/scudo/mismatch.cpp +++ b/test/scudo/mismatch.cpp @@ -1,18 +1,13 @@ // RUN: %clangxx_scudo %s -o %t -// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t mallocdel 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s -// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t mallocdel 2>&1 -// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t newfree 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s -// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t newfree 2>&1 -// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t memaligndel 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s -// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t memaligndel 2>&1 -// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t memalignrealloc 2>&1 | FileCheck --check-prefix=CHECK-realloc %s -// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t memalignrealloc 2>&1 +// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t mallocdel 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s +// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t mallocdel 2>&1 +// RUN: %env_scudo_opts=DeallocationTypeMismatch=1 not %run %t newfree 2>&1 | FileCheck --check-prefix=CHECK-dealloc %s +// RUN: %env_scudo_opts=DeallocationTypeMismatch=0 %run %t newfree 2>&1 // Tests that type mismatches between allocation and deallocation functions are // caught when the related option is set. #include <assert.h> -#include <malloc.h> #include <stdlib.h> #include <string.h> @@ -29,17 +24,6 @@ int main(int argc, char **argv) assert(p); free((void *)p); } - if (!strcmp(argv[1], "memaligndel")) { - int *p = (int *)memalign(16, 16); - assert(p); - delete p; - } - if (!strcmp(argv[1], "memalignrealloc")) { - void *p = memalign(16, 16); - assert(p); - p = realloc(p, 32); - free(p); - } return 0; } diff --git a/test/scudo/preload.cpp b/test/scudo/preload.cpp index b41a70e472b3..7fa8df4c6931 100644 --- a/test/scudo/preload.cpp +++ b/test/scudo/preload.cpp @@ -1,7 +1,8 @@ // Test that the preloaded runtime works without linking the static library. // RUN: %clang %s -lstdc++ -o %t -// RUN: env LD_PRELOAD=%shared_libscudo not %run %t 2>&1 | FileCheck %s +// RUN: env LD_PRELOAD=%shared_libscudo not %run %t 2>&1 | FileCheck %s +// RUN: env LD_PRELOAD=%shared_minlibscudo not %run %t 2>&1 | FileCheck %s // This way of setting LD_PRELOAD does not work with Android test runner. // REQUIRES: !android diff --git a/test/scudo/random_shuffle.cpp b/test/scudo/random_shuffle.cpp index f886cb1504e1..b493a292944c 100644 --- a/test/scudo/random_shuffle.cpp +++ b/test/scudo/random_shuffle.cpp @@ -1,12 +1,12 @@ // RUN: %clangxx_scudo %s -o %t -// RUN: rm -rf %T/random_shuffle_tmp_dir -// RUN: mkdir %T/random_shuffle_tmp_dir -// RUN: %run %t 100 > %T/random_shuffle_tmp_dir/out1 -// RUN: %run %t 100 > %T/random_shuffle_tmp_dir/out2 -// RUN: %run %t 10000 > %T/random_shuffle_tmp_dir/out1 -// RUN: %run %t 10000 > %T/random_shuffle_tmp_dir/out2 -// RUN: not diff %T/random_shuffle_tmp_dir/out? -// RUN: rm -rf %T/random_shuffle_tmp_dir +// RUN: rm -rf %t-dir/random_shuffle_tmp_dir +// RUN: mkdir -p %t-dir/random_shuffle_tmp_dir +// RUN: %run %t 100 > %t-dir/random_shuffle_tmp_dir/out1 +// RUN: %run %t 100 > %t-dir/random_shuffle_tmp_dir/out2 +// RUN: %run %t 10000 > %t-dir/random_shuffle_tmp_dir/out1 +// RUN: %run %t 10000 > %t-dir/random_shuffle_tmp_dir/out2 +// RUN: not diff %t-dir/random_shuffle_tmp_dir/out? +// RUN: rm -rf %t-dir/random_shuffle_tmp_dir // Tests that the allocator shuffles the chunks before returning to the user. diff --git a/test/scudo/realloc.cpp b/test/scudo/realloc.cpp index 254c67a2cca4..26f6373b918e 100644 --- a/test/scudo/realloc.cpp +++ b/test/scudo/realloc.cpp @@ -1,6 +1,6 @@ // RUN: %clangxx_scudo %s -lstdc++ -o %t -// RUN: %run %t pointers 2>&1 -// RUN: %run %t contents 2>&1 +// RUN: %run %t pointers 2>&1 +// RUN: %run %t contents 2>&1 // RUN: %run %t usablesize 2>&1 // Tests that our reallocation function returns the same pointer when the @@ -15,6 +15,8 @@ #include <vector> +#include <sanitizer/allocator_interface.h> + int main(int argc, char **argv) { void *p, *old_p; @@ -35,7 +37,7 @@ int main(int argc, char **argv) if (p) free(p); size += 16; p = malloc(size); - usable_size = malloc_usable_size(p); + usable_size = __sanitizer_get_allocated_size(p); assert(usable_size >= size); } while (usable_size == size); for (int i = 0; i < usable_size; i++) @@ -56,7 +58,7 @@ int main(int argc, char **argv) if (!strcmp(argv[1], "pointers")) { old_p = p = realloc(nullptr, size); assert(p); - size = malloc_usable_size(p); + size = __sanitizer_get_allocated_size(p); // Our realloc implementation will return the same pointer if the size // requested is lower than or equal to the usable size of the associated // chunk. diff --git a/test/scudo/sized-delete.cpp b/test/scudo/sized-delete.cpp index 85df05e2f809..81151b097481 100644 --- a/test/scudo/sized-delete.cpp +++ b/test/scudo/sized-delete.cpp @@ -38,4 +38,4 @@ int main(int argc, char **argv) return 0; } -// CHECK: ERROR: invalid sized delete on chunk at address +// CHECK: ERROR: invalid sized delete when deallocating address diff --git a/test/scudo/sizes.cpp b/test/scudo/sizes.cpp index 73fc71f25c54..f7ccbebedc30 100644 --- a/test/scudo/sizes.cpp +++ b/test/scudo/sizes.cpp @@ -1,11 +1,11 @@ // RUN: %clangxx_scudo %s -lstdc++ -o %t -// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s +// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-max // RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t malloc 2>&1 -// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s +// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-calloc // RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t calloc 2>&1 -// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new 2>&1 | FileCheck %s -// RUN: %env_scudo_opts=allocator_may_return_null=1 not %run %t new 2>&1 | FileCheck %s -// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 | FileCheck %s +// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new 2>&1 | FileCheck %s --check-prefix=CHECK-max +// RUN: %env_scudo_opts=allocator_may_return_null=1 not %run %t new 2>&1 | FileCheck %s --check-prefix=CHECK-oom +// RUN: %env_scudo_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 | FileCheck %s --check-prefix=CHECK-max // RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1 // RUN: %run %t usable 2>&1 @@ -21,10 +21,10 @@ #include <limits> #include <new> +#include <sanitizer/allocator_interface.h> + int main(int argc, char **argv) { assert(argc == 2); - const char *action = argv[1]; - fprintf(stderr, "%s:\n", action); #if __LP64__ || defined(_WIN64) static const size_t kMaxAllowedMallocSize = 1ULL << 40; @@ -34,32 +34,32 @@ int main(int argc, char **argv) { static const size_t kChunkHeaderSize = 8; #endif - if (!strcmp(action, "malloc")) { + if (!strcmp(argv[1], "malloc")) { void *p = malloc(kMaxAllowedMallocSize); assert(!p); p = malloc(kMaxAllowedMallocSize - kChunkHeaderSize); assert(!p); - } else if (!strcmp(action, "calloc")) { + } else if (!strcmp(argv[1], "calloc")) { // Trigger an overflow in calloc. size_t size = std::numeric_limits<size_t>::max(); void *p = calloc((size / 0x1000) + 1, 0x1000); assert(!p); - } else if (!strcmp(action, "new")) { + } else if (!strcmp(argv[1], "new")) { void *p = operator new(kMaxAllowedMallocSize); assert(!p); - } else if (!strcmp(action, "new-nothrow")) { + } else if (!strcmp(argv[1], "new-nothrow")) { void *p = operator new(kMaxAllowedMallocSize, std::nothrow); assert(!p); - } else if (!strcmp(action, "usable")) { + } else if (!strcmp(argv[1], "usable")) { // Playing with the actual usable size of a chunk. void *p = malloc(1007); assert(p); - size_t size = malloc_usable_size(p); + size_t size = __sanitizer_get_allocated_size(p); assert(size >= 1007); memset(p, 'A', size); p = realloc(p, 2014); assert(p); - size = malloc_usable_size(p); + size = __sanitizer_get_allocated_size(p); assert(size >= 2014); memset(p, 'B', size); free(p); @@ -70,4 +70,6 @@ int main(int argc, char **argv) { return 0; } -// CHECK: allocator is terminating the process +// CHECK-max: {{Scudo ERROR: requested allocation size .* exceeds maximum supported size}} +// CHECK-oom: Scudo ERROR: allocator is out of memory +// CHECK-calloc: Scudo ERROR: calloc parameters overflow diff --git a/test/scudo/stats.c b/test/scudo/stats.c new file mode 100644 index 000000000000..e7cc78ff0d49 --- /dev/null +++ b/test/scudo/stats.c @@ -0,0 +1,21 @@ +// RUN: %clang_scudo %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +// Tests that the allocator stats printing function exists and outputs +// "something". Currently that "something" is fairly nebulous, as the 32-bit +// primary doesn't output anything, and for the 64-bit one it's highly dependent +// on the size class map and potential library allocations. So keep it very +// generic for now. + +#include <stdlib.h> + +#include <sanitizer/scudo_interface.h> + +int main(int argc, char **argv) +{ + free(malloc(1U)); + __scudo_print_stats(); + return 0; +} + +// CHECK: Stats: diff --git a/test/scudo/symbols.test b/test/scudo/symbols.test new file mode 100644 index 000000000000..0425e62ba6af --- /dev/null +++ b/test/scudo/symbols.test @@ -0,0 +1,8 @@ +UNSUPPORTED: android + +Verify that various functions are *not* present in the minimal binary. Presence +of those symbols in the minimal runtime would mean that the split code made it +back into the core Sanitizer runtime library. + +RUN: nm %shared_minlibscudo | not grep Symbolizer +RUN: nm %shared_minlibscudo | not grep Coverage diff --git a/test/scudo/valloc.c b/test/scudo/valloc.c index 132c4f280220..605b9c4d4b9d 100644 --- a/test/scudo/valloc.c +++ b/test/scudo/valloc.c @@ -1,8 +1,8 @@ // RUN: %clang_scudo %s -o %t // RUN: %run %t valid 2>&1 -// RUN: not %run %t invalid 2>&1 +// RUN: not %run %t invalid 2>&1 | FileCheck %s // RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1 -// UNSUPPORTED: android, armhf-linux +// UNSUPPORTED: android // Tests that valloc and pvalloc work as intended. @@ -54,6 +54,7 @@ int main(int argc, char **argv) if (!strcmp(argv[1], "invalid")) { // Size passed to pvalloc overflows when rounded up. p = pvalloc((size_t)-1); + // CHECK: Scudo ERROR: pvalloc parameters overflow assert(!p); assert(errno == ENOMEM); errno = 0; diff --git a/test/shadowcallstack/CMakeLists.txt b/test/shadowcallstack/CMakeLists.txt new file mode 100644 index 000000000000..ab2b18819d49 --- /dev/null +++ b/test/shadowcallstack/CMakeLists.txt @@ -0,0 +1,21 @@ +set(TEST_ARCH ${SHADOWCALLSTACK_SUPPORTED_ARCH}) + +set(SHADOWCALLSTACK_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(SHADOWCALLSTACK_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) + +set(SHADOWCALLSTACK_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) + +foreach(arch ${SHADOWCALLSTACK_SUPPORTED_ARCH}) + set(SANITIZER_COMMON_TEST_TARGET_ARCH ${arch}) + get_test_cc_for_arch(${arch} + SHADOWSTACK_TEST_TARGET_CC SHADOWSTACK_TEST_TARGET_CFLAGS) + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/${arch}/lit.site.cfg) + list(APPEND SHADOWCALLSTACK_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${arch}) +endforeach() + +add_lit_testsuite(check-shadowcallstack "Running the ShadowCallStack tests" + ${SHADOWCALLSTACK_TESTSUITES} + DEPENDS ${SANITIZER_COMMON_LIT_TEST_DEPS}) +set_target_properties(check-shadowcallstack PROPERTIES FOLDER "Compiler-RT Misc") diff --git a/test/shadowcallstack/init.c b/test/shadowcallstack/init.c new file mode 100644 index 000000000000..a406e1b140fc --- /dev/null +++ b/test/shadowcallstack/init.c @@ -0,0 +1,12 @@ +// RUN: %clang_scs %s -o %t +// RUN: %run %t + +// Basic smoke test for the runtime + +#include "libc_support.h" +#include "minimal_runtime.h" + +int scs_main(void) { + scs_fputs_stdout("In main.\n"); + return 0; +} diff --git a/test/shadowcallstack/libc_support.h b/test/shadowcallstack/libc_support.h new file mode 100644 index 000000000000..5d89aab645a9 --- /dev/null +++ b/test/shadowcallstack/libc_support.h @@ -0,0 +1,41 @@ +// This header provides replacements for certain libc functions. It is necessary +// in order to safely run the tests on aarch64, because the system libc might +// not have been compiled with -ffixed-x18. + +#pragma once + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + +#ifdef __aarch64__ + +size_t scs_strlen(const char *p) { + size_t retval = 0; + while (*p++) + retval++; + return retval; +} + +// We mark this function as noinline to make sure that its callers do not +// become leaf functions as a result of inlining. This is because we want to +// make sure that we generate the correct code for non-leaf functions. + +__attribute__((noinline)) void scs_fputs_stdout(const char *p) { + __asm__ __volatile__( + "mov x0, #1\n" // stdout + "mov x1, %0\n" + "mov x2, %1\n" + "mov x8, #64\n" // write + "svc #0\n" ::"r"(p), + "r"(scs_strlen(p)) + : "x0", "x1", "x2", "x8"); +} + +#else + +__attribute__((noinline)) void scs_fputs_stdout(const char *p) { + fputs(p, stdout); +} + +#endif diff --git a/test/shadowcallstack/lit.cfg b/test/shadowcallstack/lit.cfg new file mode 100644 index 000000000000..313cd2b8eff3 --- /dev/null +++ b/test/shadowcallstack/lit.cfg @@ -0,0 +1,23 @@ +# -*- Python -*- + +import os + +# Setup config name. +config.name = 'ShadowCallStack' + +# 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_noscs ", config.clang + ' -O0 -fno-sanitize=shadow-call-stack ' + config.target_cflags + ' ') ) + +scs_arch_cflags = config.target_cflags +if config.target_arch == 'aarch64': + scs_arch_cflags += ' -ffixed-x18 ' +config.substitutions.append( ("%clang_scs ", config.clang + ' -O0 -fsanitize=shadow-call-stack ' + scs_arch_cflags + ' ') ) + +if config.host_os not in ['Linux'] or config.target_arch not in ['x86_64', 'aarch64']: + config.unsupported = True diff --git a/test/shadowcallstack/lit.site.cfg.in b/test/shadowcallstack/lit.site.cfg.in new file mode 100644 index 000000000000..aa8913e84cb8 --- /dev/null +++ b/test/shadowcallstack/lit.site.cfg.in @@ -0,0 +1,12 @@ +@LIT_SITE_CFG_IN_HEADER@ + +# Tool-specific config options. +config.name_suffix = "@SHADOWCALLSTACK_TEST_CONFIG_SUFFIX@" +config.target_cflags = "@SHADOWCALLSTACK_TEST_TARGET_CFLAGS@" +config.target_arch = "@SHADOWCALLSTACK_TEST_TARGET_ARCH@" + +# 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, "@SHADOWCALLSTACK_LIT_SOURCE_DIR@/lit.cfg") diff --git a/test/shadowcallstack/minimal_runtime.h b/test/shadowcallstack/minimal_runtime.h new file mode 100644 index 000000000000..f36fa5a7d245 --- /dev/null +++ b/test/shadowcallstack/minimal_runtime.h @@ -0,0 +1,43 @@ +// A shadow call stack runtime is not yet included with compiler-rt, provide a +// minimal runtime to allocate a shadow call stack and assign an +// architecture-specific register to point at it. + +#pragma once + +#ifdef __x86_64__ +#include <asm/prctl.h> +int arch_prctl(int code, void *addr); +#endif +#include <stdlib.h> +#include <sys/mman.h> +#include <sys/prctl.h> + +#include "libc_support.h" + +__attribute__((no_sanitize("shadow-call-stack"))) +static void __shadowcallstack_init() { + void *stack = mmap(NULL, 8192, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (stack == MAP_FAILED) + abort(); + +#if defined(__x86_64__) + if (arch_prctl(ARCH_SET_GS, stack)) + abort(); +#elif defined(__aarch64__) + __asm__ __volatile__("mov x18, %0" ::"r"(stack)); +#else +#error Unsupported platform +#endif +} + +int scs_main(void); + +__attribute__((no_sanitize("shadow-call-stack"))) int main(void) { + __shadowcallstack_init(); + + // We can't simply return scs_main() because scs_main might have corrupted our + // return address for testing purposes (see overflow.c), so we need to exit + // ourselves. + exit(scs_main()); +} diff --git a/test/shadowcallstack/overflow-aarch64.c b/test/shadowcallstack/overflow-aarch64.c new file mode 100644 index 000000000000..8da798164fe7 --- /dev/null +++ b/test/shadowcallstack/overflow-aarch64.c @@ -0,0 +1,5 @@ +// See overflow.c for a description. + +// REQUIRES: aarch64-target-arch +// RUN: %clang_scs %S/overflow.c -o %t -DITERATIONS=12 +// RUN: %run %t | FileCheck %S/overflow.c diff --git a/test/shadowcallstack/overflow-x86_64.c b/test/shadowcallstack/overflow-x86_64.c new file mode 100644 index 000000000000..38bb13a969a3 --- /dev/null +++ b/test/shadowcallstack/overflow-x86_64.c @@ -0,0 +1,5 @@ +// See overflow.c for a description. + +// REQUIRES: x86_64-target-arch +// RUN: %clang_scs %S/overflow.c -o %t -DITERATIONS=12 +// RUN: not --crash %run %t diff --git a/test/shadowcallstack/overflow.c b/test/shadowcallstack/overflow.c new file mode 100644 index 000000000000..8c3d50c5917f --- /dev/null +++ b/test/shadowcallstack/overflow.c @@ -0,0 +1,39 @@ +// Test that a stack overflow fails as expected + +// RUN: %clang_noscs %s -o %t -DITERATIONS=3 +// RUN: %run %t | FileCheck %s +// RUN: %clang_noscs %s -o %t -DITERATIONS=12 +// RUN: %run %t | FileCheck -check-prefix=OVERFLOW_SUCCESS %s + +// RUN: %clang_scs %s -o %t -DITERATIONS=3 +// RUN: %run %t | FileCheck %s + +// The behavioral check for SCS + overflow lives in the tests overflow-x86_64.c +// and overflow-aarch64.c. This is because the expected behavior is different +// between the two platforms. On x86_64 we crash because the comparison between +// the shadow call stack and the regular stack fails. On aarch64 there is no +// comparison, we just load the return address from the shadow call stack. So we +// just expect not to see the output from print_and_exit. + +#include <stdio.h> +#include <stdlib.h> + +#include "minimal_runtime.h" + +void print_and_exit(void) { +// CHECK-NOT: Stack overflow successful. +// OVERFLOW_SUCCESS: Stack overflow successful. + scs_fputs_stdout("Stack overflow successful.\n"); + exit(0); +} + +int scs_main(void) +{ + void *addrs[4]; + for (int i = 0; i < ITERATIONS; i++) + addrs[i] = &print_and_exit; + + scs_fputs_stdout("Returning.\n"); + + return 0; +} diff --git a/test/tsan/CMakeLists.txt b/test/tsan/CMakeLists.txt index 2b1d3004b1de..ba0fd9f23a33 100644 --- a/test/tsan/CMakeLists.txt +++ b/test/tsan/CMakeLists.txt @@ -24,10 +24,7 @@ if(APPLE) endif() foreach(arch ${TSAN_TEST_ARCH}) - set(TSAN_TEST_IOS "0") - pythonize_bool(TSAN_TEST_IOS) - set(TSAN_TEST_IOSSIM "0") - pythonize_bool(TSAN_TEST_IOSSIM) + set(TSAN_TEST_APPLE_PLATFORM "osx") set(TSAN_TEST_TARGET_ARCH ${arch}) string(TOLOWER "-${arch}" TSAN_TEST_CONFIG_SUFFIX) @@ -51,15 +48,12 @@ if(APPLE) set(EXCLUDE_FROM_ALL ON) set(TSAN_TEST_TARGET_CC ${COMPILER_RT_TEST_COMPILER}) - set(TSAN_TEST_IOS "1") - pythonize_bool(TSAN_TEST_IOS) + set(TSAN_TEST_APPLE_PLATFORM "iossim") set(arch "x86_64") - set(TSAN_TEST_IOSSIM "1") - pythonize_bool(TSAN_TEST_IOSSIM) set(TSAN_TEST_TARGET_ARCH ${arch}) set(TSAN_TEST_TARGET_CFLAGS "-arch ${arch} -isysroot ${DARWIN_iossim_SYSROOT} ${COMPILER_RT_TEST_COMPILER_CFLAGS}") - set(TSAN_TEST_CONFIG_SUFFIX "-${arch}-iossim") + set(TSAN_TEST_CONFIG_SUFFIX "-${arch}-${TSAN_TEST_APPLE_PLATFORM}") string(TOUPPER ${arch} ARCH_UPPER_CASE) set(CONFIG_NAME "IOSSim${ARCH_UPPER_CASE}Config") configure_lit_site_cfg( @@ -70,12 +64,11 @@ if(APPLE) ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/ DEPENDS ${TSAN_TEST_DEPS}) + set(TSAN_TEST_APPLE_PLATFORM "ios") set(arch "arm64") - set(TSAN_TEST_IOSSIM "0") - pythonize_bool(TSAN_TEST_IOSSIM) set(TSAN_TEST_TARGET_ARCH ${arch}) set(TSAN_TEST_TARGET_CFLAGS "-arch ${arch} -isysroot ${DARWIN_ios_SYSROOT} ${COMPILER_RT_TEST_COMPILER_CFLAGS}") - set(TSAN_TEST_CONFIG_SUFFIX "-${arch}-ios") + set(TSAN_TEST_CONFIG_SUFFIX "-${arch}-${TSAN_TEST_APPLE_PLATFORM}") string(TOUPPER ${arch} ARCH_UPPER_CASE) set(CONFIG_NAME "IOS${ARCH_UPPER_CASE}Config") configure_lit_site_cfg( diff --git a/test/tsan/Darwin/external-swift-debugging.cc b/test/tsan/Darwin/external-swift-debugging.cc new file mode 100644 index 000000000000..603734e5d035 --- /dev/null +++ b/test/tsan/Darwin/external-swift-debugging.cc @@ -0,0 +1,68 @@ +// RUN: %clangxx_tsan %s -o %t +// RUN: %deflake %run %t 2>&1 | FileCheck %s + +#include <thread> + +#import "../test.h" + + +extern "C" { +int __tsan_get_report_data(void *report, const char **description, int *count, + int *stack_count, int *mop_count, int *loc_count, + int *mutex_count, int *thread_count, + int *unique_tid_count, void **sleep_trace, + unsigned long trace_size); +int __tsan_get_report_tag(void *report, unsigned long *tag); +} + +__attribute__((no_sanitize("thread"), noinline)) +void ExternalWrite(void *addr) { + void *kSwiftAccessRaceTag = (void *)0x1; + __tsan_external_write(addr, nullptr, kSwiftAccessRaceTag); +} + +int main(int argc, char *argv[]) { + barrier_init(&barrier, 2); + fprintf(stderr, "Start.\n"); + // CHECK: Start. + + void *opaque_object = malloc(16); + std::thread t1([opaque_object] { + ExternalWrite(opaque_object); + barrier_wait(&barrier); + }); + std::thread t2([opaque_object] { + barrier_wait(&barrier); + ExternalWrite(opaque_object); + }); + // CHECK: WARNING: ThreadSanitizer: Swift access race + // CHECK: Modifying access of Swift variable at {{.*}} by thread {{.*}} + // CHECK: Previous modifying access of Swift variable at {{.*}} by thread {{.*}} + // CHECK: SUMMARY: ThreadSanitizer: Swift access race + t1.join(); + t2.join(); + + fprintf(stderr, "Done.\n"); +} + +extern "C" +void __tsan_on_report(void *report) { + const char *description; + int count; + int stack_count, mop_count, loc_count, mutex_count, thread_count, + unique_tid_count; + void *sleep_trace[16] = {0}; + __tsan_get_report_data(report, &description, &count, &stack_count, &mop_count, + &loc_count, &mutex_count, &thread_count, + &unique_tid_count, sleep_trace, 16); + fprintf(stderr, "report type = '%s', count = %d\n", description, count); + // CHECK: report type = 'external-race', count = 0 + + unsigned long tag; + __tsan_get_report_tag(report, &tag); + fprintf(stderr, "tag = %ld\n", tag); + // CHECK: tag = 1 +} + +// CHECK: Done. +// CHECK: ThreadSanitizer: reported 1 warnings diff --git a/test/tsan/Darwin/gcd-after-null.mm b/test/tsan/Darwin/gcd-after-null.mm deleted file mode 100644 index 7c9913c0fb17..000000000000 --- a/test/tsan/Darwin/gcd-after-null.mm +++ /dev/null @@ -1,23 +0,0 @@ -// Regression test to make sure we don't crash when dispatch_after is called with a NULL queue. - -// RUN: %clang_tsan %s -o %t -framework Foundation -// RUN: %run %t 2>&1 | FileCheck %s - -#import <Foundation/Foundation.h> - -int main(int argc, const char *argv[]) { - fprintf(stderr, "start\n"); - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_MSEC)), NULL, ^{ - dispatch_async(dispatch_get_main_queue(), ^{ - CFRunLoopStop(CFRunLoopGetMain()); - }); - }); - CFRunLoopRun(); - - fprintf(stderr, "done\n"); - return 0; -} - -// CHECK: start -// CHECK: done diff --git a/test/tsan/Darwin/norace-objcxx-run-time.mm b/test/tsan/Darwin/norace-objcxx-run-time.mm index 1de431a076c7..ee76ec155cb4 100644 --- a/test/tsan/Darwin/norace-objcxx-run-time.mm +++ b/test/tsan/Darwin/norace-objcxx-run-time.mm @@ -1,4 +1,4 @@ -// RUN: %clang_tsan %s -lc++ -fobjc-arc -lobjc -o %t -framework Foundation +// RUN: %clang_tsan %s -lc++ -fobjc-arc -lobjc -o %t -framework Foundation %darwin_min_target_with_full_runtime_arc_support // RUN: %run %t 2>&1 | FileCheck %s // Check that we do not report races between: diff --git a/test/tsan/Darwin/objc-synchronize-tagged.mm b/test/tsan/Darwin/objc-synchronize-tagged.mm new file mode 100644 index 000000000000..ab0af46ec4af --- /dev/null +++ b/test/tsan/Darwin/objc-synchronize-tagged.mm @@ -0,0 +1,62 @@ +// RUN: %clangxx_tsan %s -o %t -framework Foundation -fobjc-arc %darwin_min_target_with_full_runtime_arc_support +// RUN: %run %t 2>&1 | FileCheck %s + +#import <Foundation/Foundation.h> + +NSString *tagged_string = nil; + +@interface MyClass : NSObject { + long field; +} +@property(nonatomic, readonly) long value; +@end + +dispatch_group_t group; + +@implementation MyClass + +- (void)start { + dispatch_queue_t q = dispatch_queue_create(NULL, NULL); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + for (int i = 0; i < 10; i++) { + dispatch_async(q, ^{ + @synchronized(tagged_string) { + self->field = i; + } + }); + } + }); +} + +- (long)value { + @synchronized(tagged_string) { + return self->field; + } +} + +- (void)dealloc { + dispatch_group_leave(group); +} + +@end + +int main() { + tagged_string = [NSString stringWithFormat:@"%s", "abc"]; + uintptr_t tagged_string_bits = (uintptr_t)tagged_string; + assert((tagged_string_bits & 0x8000000000000001ull) != 0); + group = dispatch_group_create(); + @autoreleasepool { + for (int j = 0; j < 100; ++j) { + dispatch_group_enter(group); + MyClass *obj = [[MyClass alloc] init]; + [obj start]; + long x = obj.value; + (void)x; + } + } + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + NSLog(@"Hello world"); +} + +// CHECK: Hello world +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/test/tsan/Darwin/objc-synchronize.mm b/test/tsan/Darwin/objc-synchronize.mm new file mode 100644 index 000000000000..0bf06370a9b8 --- /dev/null +++ b/test/tsan/Darwin/objc-synchronize.mm @@ -0,0 +1,57 @@ +// RUN: %clangxx_tsan %s -o %t -framework Foundation -fobjc-arc %darwin_min_target_with_full_runtime_arc_support +// RUN: %run %t 2>&1 | FileCheck %s + +#import <Foundation/Foundation.h> + +@interface MyClass : NSObject { + long field; +} +@property (nonatomic, readonly) long value; +@end + +dispatch_group_t group; + +@implementation MyClass + +- (void) start { + dispatch_queue_t q = dispatch_queue_create(NULL, NULL); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + for (int i = 0; i < 1000; i++) { + dispatch_async(q, ^{ + @synchronized(self) { + self->field = i; + } + }); + } + }); +} + +- (long) value { + @synchronized(self) { + return self->field; + } +} + +- (void)dealloc { + dispatch_group_leave(group); +} + +@end + +int main() { + group = dispatch_group_create(); + @autoreleasepool { + for (int j = 0; j < 100; ++j) { + dispatch_group_enter(group); + MyClass *obj = [[MyClass alloc] init]; + [obj start]; + long x = obj.value; + (void)x; + } + } + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + NSLog(@"Hello world"); +} + +// CHECK: Hello world +// CHECK-NOT: WARNING: ThreadSanitizer diff --git a/test/tsan/allocator_returns_null.cc b/test/tsan/allocator_returns_null.cc deleted file mode 100644 index 5e2e2e9a53c7..000000000000 --- a/test/tsan/allocator_returns_null.cc +++ /dev/null @@ -1,124 +0,0 @@ -// Test the behavior of malloc/calloc/realloc/new when the allocation size is -// more than TSan allocator's max allowed one. -// By default (allocator_may_return_null=0) the process should crash. -// With allocator_may_return_null=1 the allocator should return 0, except the -// operator new(), which should crash anyway (operator new(std::nothrow) should -// return nullptr, indeed). -// -// RUN: %clangxx_tsan -O0 %s -o %t -// RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mCRASH -// RUN: %env_tsan_opts=allocator_may_return_null=1 %run %t malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mNULL -// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-cCRASH -// RUN: %env_tsan_opts=allocator_may_return_null=1 %run %t calloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-cNULL -// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-coCRASH -// RUN: %env_tsan_opts=allocator_may_return_null=1 %run %t calloc-overflow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-coNULL -// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-rCRASH -// RUN: %env_tsan_opts=allocator_may_return_null=1 %run %t realloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-rNULL -// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mrCRASH -// RUN: %env_tsan_opts=allocator_may_return_null=1 %run %t realloc-after-malloc 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-mrNULL -// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t new 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH -// RUN: %env_tsan_opts=allocator_may_return_null=1 not %run %t new 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nCRASH -// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nnCRASH -// RUN: %env_tsan_opts=allocator_may_return_null=1 %run %t new-nothrow 2>&1 \ -// RUN: | FileCheck %s --check-prefix=CHECK-nnNULL - -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <limits> -#include <new> - -int main(int argc, char **argv) { - // Disable stderr buffering. Needed on Windows. - setvbuf(stderr, NULL, _IONBF, 0); - - assert(argc == 2); - const char *action = argv[1]; - fprintf(stderr, "%s:\n", action); - - // The limit enforced in tsan_mman.cc, user_alloc_internal function. - static const size_t kMaxAllowedMallocSizePlusOne = (1ULL << 40) + 1; - - void *x = 0; - if (!strcmp(action, "malloc")) { - x = malloc(kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "calloc")) { - x = calloc((kMaxAllowedMallocSizePlusOne / 4) + 1, 4); - } else if (!strcmp(action, "calloc-overflow")) { - volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max(); - size_t kArraySize = 4096; - volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10; - x = calloc(kArraySize, kArraySize2); - } else if (!strcmp(action, "realloc")) { - x = realloc(0, kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "realloc-after-malloc")) { - char *t = (char*)malloc(100); - *t = 42; - x = realloc(t, kMaxAllowedMallocSizePlusOne); - assert(*t == 42); - } else if (!strcmp(action, "new")) { - x = operator new(kMaxAllowedMallocSizePlusOne); - } else if (!strcmp(action, "new-nothrow")) { - x = operator new(kMaxAllowedMallocSizePlusOne, std::nothrow); - } else { - assert(0); - } - - fprintf(stderr, "errno: %d\n", errno); - - // The NULL pointer is printed differently on different systems, while (long)0 - // is always the same. - fprintf(stderr, "x: %lx\n", (long)x); - free(x); - - return x != 0; -} - -// CHECK-mCRASH: malloc: -// CHECK-mCRASH: ThreadSanitizer's allocator is terminating the process -// CHECK-cCRASH: calloc: -// CHECK-cCRASH: ThreadSanitizer's allocator is terminating the process -// CHECK-coCRASH: calloc-overflow: -// CHECK-coCRASH: ThreadSanitizer's allocator is terminating the process -// CHECK-rCRASH: realloc: -// CHECK-rCRASH: ThreadSanitizer's allocator is terminating the process -// CHECK-mrCRASH: realloc-after-malloc: -// CHECK-mrCRASH: ThreadSanitizer's allocator is terminating the process -// CHECK-nCRASH: new: -// CHECK-nCRASH: ThreadSanitizer's allocator is terminating the process -// CHECK-nnCRASH: new-nothrow: -// CHECK-nnCRASH: ThreadSanitizer's allocator is terminating the process - -// CHECK-mNULL: malloc: -// CHECK-mNULL: errno: 12 -// CHECK-mNULL: x: 0 -// CHECK-cNULL: calloc: -// CHECK-cNULL: errno: 12 -// CHECK-cNULL: x: 0 -// CHECK-coNULL: calloc-overflow: -// CHECK-coNULL: errno: 12 -// CHECK-coNULL: x: 0 -// CHECK-rNULL: realloc: -// CHECK-rNULL: errno: 12 -// CHECK-rNULL: x: 0 -// CHECK-mrNULL: realloc-after-malloc: -// CHECK-mrNULL: errno: 12 -// CHECK-mrNULL: x: 0 -// CHECK-nnNULL: new-nothrow: -// CHECK-nnNULL: x: 0 diff --git a/test/tsan/global_race.cc b/test/tsan/global_race.cc index ec26b06f5c1c..01df3b6de9c3 100644 --- a/test/tsan/global_race.cc +++ b/test/tsan/global_race.cc @@ -1,12 +1,15 @@ -// RUN: %clangxx_tsan -O1 %s -o %T/global_race.cc.exe && %deflake %run %T/global_race.cc.exe 2>&1 \ +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir + +// RUN: %clangxx_tsan -O1 %s -o %t-dir/global_race.cc.exe && %deflake %run %t-dir/global_race.cc.exe 2>&1 \ // RUN: | FileCheck %s // Also check that memory access instrumentation can be configured by either // driver or legacy flags: -// RUN: %clangxx_tsan -O1 %s -o %T/global_race.cc.exe -fno-sanitize-thread-memory-access && not %deflake %run %T/global_race.cc.exe 2>&1 \ +// RUN: %clangxx_tsan -O1 %s -o %t-dir/global_race.cc.exe -fno-sanitize-thread-memory-access && not %deflake %run %t-dir/global_race.cc.exe 2>&1 \ // RUN: | FileCheck --allow-empty --check-prefix=CHECK-MEMORY-ACCESS-OFF %s -// RUN: %clangxx_tsan -O1 %s -o %T/global_race.cc.exe -mllvm -tsan-instrument-memory-accesses=0 && not %deflake %run %T/global_race.cc.exe 2>&1 \ +// RUN: %clangxx_tsan -O1 %s -o %t-dir/global_race.cc.exe -mllvm -tsan-instrument-memory-accesses=0 && not %deflake %run %t-dir/global_race.cc.exe 2>&1 \ // RUN: | FileCheck --allow-empty --check-prefix=CHECK-MEMORY-ACCESS-OFF %s #include "test.h" diff --git a/test/tsan/ignore_lib0.cc b/test/tsan/ignore_lib0.cc index 84632019fccb..2b217f21ff56 100644 --- a/test/tsan/ignore_lib0.cc +++ b/test/tsan/ignore_lib0.cc @@ -1,9 +1,12 @@ -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib0.so -// RUN: %clangxx_tsan -O1 %s -L%T -lignore_lib0 -o %t +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir + +// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib0.so +// RUN: %clangxx_tsan -O1 %s -L%t-dir -lignore_lib0 -o %t // RUN: echo running w/o suppressions: -// RUN: env LD_LIBRARY_PATH=%T${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP +// RUN: env LD_LIBRARY_PATH=%t-dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP // RUN: echo running with suppressions: -// RUN: env LD_LIBRARY_PATH=%T${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP +// RUN: env LD_LIBRARY_PATH=%t-dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP // Tests that interceptors coming from a library specified in called_from_lib // suppression are ignored. diff --git a/test/tsan/ignore_lib1.cc b/test/tsan/ignore_lib1.cc index 5949d811ed44..1660cf3e41f9 100644 --- a/test/tsan/ignore_lib1.cc +++ b/test/tsan/ignore_lib1.cc @@ -1,9 +1,12 @@ -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib1.so -// RUN: %clangxx_tsan -O1 %s -o %t +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir + +// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so +// RUN: %clangxx_tsan -O1 %s -o %t-dir/executable // RUN: echo running w/o suppressions: -// RUN: %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP +// RUN: %deflake %run %t-dir/executable | FileCheck %s --check-prefix=CHECK-NOSUPP // RUN: echo running with suppressions: -// RUN: %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP +// RUN: %env_tsan_opts=suppressions='%s.supp' %run %t-dir/executable 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP // Tests that interceptors coming from a dynamically loaded library specified // in called_from_lib suppression are ignored. diff --git a/test/tsan/ignore_lib2.cc b/test/tsan/ignore_lib2.cc index 4f584b14664a..e0dac5670122 100644 --- a/test/tsan/ignore_lib2.cc +++ b/test/tsan/ignore_lib2.cc @@ -1,7 +1,10 @@ -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib2_0.so -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib2_1.so -// RUN: %clangxx_tsan -O1 %s -o %t -// RUN: %env_tsan_opts=suppressions='%s.supp' %deflake %run %t | FileCheck %s +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir + +// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib2_0.so +// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib2_1.so +// RUN: %clangxx_tsan -O1 %s -o %t-dir/executable +// RUN: %env_tsan_opts=suppressions='%s.supp' %deflake %run %t-dir/executable | FileCheck %s // Tests that called_from_lib suppression matched against 2 libraries // causes program crash (this is not supported). diff --git a/test/tsan/ignore_lib3.cc b/test/tsan/ignore_lib3.cc index 3f7be5cf8233..a5af07fdd112 100644 --- a/test/tsan/ignore_lib3.cc +++ b/test/tsan/ignore_lib3.cc @@ -1,6 +1,9 @@ -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib3.so -// RUN: %clangxx_tsan -O1 %s -o %t -// RUN: %env_tsan_opts=suppressions='%s.supp' %deflake %run %t | FileCheck %s +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir + +// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib3.so +// RUN: %clangxx_tsan -O1 %s -o %t-dir/executable +// RUN: %env_tsan_opts=suppressions='%s.supp' %deflake %run %t-dir/executable | FileCheck %s // Tests that unloading of a library matched against called_from_lib suppression // causes program crash (this is not supported). diff --git a/test/tsan/ignore_lib4.cc b/test/tsan/ignore_lib4.cc index 84d8b2768a94..da636ae3bf37 100644 --- a/test/tsan/ignore_lib4.cc +++ b/test/tsan/ignore_lib4.cc @@ -1,7 +1,10 @@ -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -shared -o %T/libignore_lib4.so -// RUN: %clangxx_tsan -O1 %s -o %t -// RUN: echo "called_from_lib:libignore_lib4.so" > %t.supp -// RUN: %env_tsan_opts=suppressions='%t.supp' %run %t 2>&1 | FileCheck %s +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir + +// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -shared -o %t-dir/libignore_lib4.so +// RUN: %clangxx_tsan -O1 %s -o %t-dir/executable +// RUN: echo "called_from_lib:libignore_lib4.so" > %t-dir/executable.supp +// RUN: %env_tsan_opts=suppressions='%t-dir/executable.supp' %run %t-dir/executable 2>&1 | FileCheck %s // powerpc64 big endian bots failed with "FileCheck error: '-' is empty" due // to a segmentation fault. diff --git a/test/tsan/ignore_lib5.cc b/test/tsan/ignore_lib5.cc index 54630d534c34..d6c3f870e49b 100644 --- a/test/tsan/ignore_lib5.cc +++ b/test/tsan/ignore_lib5.cc @@ -1,9 +1,12 @@ -// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %T/libignore_lib1.so -// RUN: %clangxx_tsan -O1 %s -o %t +// RUN: rm -rf %t-dir +// RUN: mkdir %t-dir + +// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so +// RUN: %clangxx_tsan -O1 %s -o %t-dir/executable // RUN: echo running w/o suppressions: -// RUN: %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP +// RUN: %deflake %run %t-dir/executable | FileCheck %s --check-prefix=CHECK-NOSUPP // RUN: echo running with suppressions: -// RUN: %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP +// RUN: %env_tsan_opts=suppressions='%s.supp' %run %t-dir/executable 2>&1 | FileCheck %s --check-prefix=CHECK-WITHSUPP // REQUIRES: stable-runtime // UNSUPPORTED: powerpc64le diff --git a/test/tsan/ignored-interceptors-mmap.cc b/test/tsan/ignored-interceptors-mmap.cc index 8715883238e2..796ea9323345 100644 --- a/test/tsan/ignored-interceptors-mmap.cc +++ b/test/tsan/ignored-interceptors-mmap.cc @@ -1,6 +1,7 @@ // RUN: %clangxx_tsan -O0 %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NORMAL // RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-IGNORE +// XFAIL: freebsd #include <errno.h> #include <sys/mman.h> diff --git a/test/tsan/java_symbolization.cc b/test/tsan/java_symbolization.cc index aa5ec0c37558..f82bd5ead48e 100644 --- a/test/tsan/java_symbolization.cc +++ b/test/tsan/java_symbolization.cc @@ -2,18 +2,13 @@ #include "java.h" #include <memory.h> -extern "C" bool __tsan_symbolize_external(jptr pc, - char *func_buf, jptr func_siz, - char *file_buf, jptr file_siz, - int *line, int *col) { +extern "C" void __tsan_symbolize_external_ex( + jptr pc, void (*add_frame)(void *, const char *, const char *, int, int), + void *ctx) { if (pc == (1234 | kExternalPCBit)) { - memcpy(func_buf, "MyFunc", sizeof("MyFunc")); - memcpy(file_buf, "MyFile.java", sizeof("MyFile.java")); - *line = 1234; - *col = 56; - return true; + add_frame(ctx, "MyInnerFunc", "MyInnerFile.java", 1234, 56); + add_frame(ctx, "MyOuterFunc", "MyOuterFile.java", 4321, 65); } - return false; } void *Thread(void *p) { @@ -40,5 +35,6 @@ int main() { } // CHECK: WARNING: ThreadSanitizer: data race -// CHECK: #0 MyFunc MyFile.java:1234:56 +// CHECK: #0 MyInnerFunc MyInnerFile.java:1234:56 +// CHECK: #1 MyOuterFunc MyOuterFile.java:4321:65 // CHECK: DONE diff --git a/test/tsan/java_symbolization_legacy.cc b/test/tsan/java_symbolization_legacy.cc new file mode 100644 index 000000000000..aa5ec0c37558 --- /dev/null +++ b/test/tsan/java_symbolization_legacy.cc @@ -0,0 +1,44 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +#include "java.h" +#include <memory.h> + +extern "C" bool __tsan_symbolize_external(jptr pc, + char *func_buf, jptr func_siz, + char *file_buf, jptr file_siz, + int *line, int *col) { + if (pc == (1234 | kExternalPCBit)) { + memcpy(func_buf, "MyFunc", sizeof("MyFunc")); + memcpy(file_buf, "MyFile.java", sizeof("MyFile.java")); + *line = 1234; + *col = 56; + return true; + } + return false; +} + +void *Thread(void *p) { + barrier_wait(&barrier); + __tsan_write1_pc((jptr)p, 1234 | kExternalPCBit); + return 0; +} + +int main() { + barrier_init(&barrier, 2); + int const kHeapSize = 1024 * 1024; + jptr jheap = (jptr)malloc(kHeapSize + 8) + 8; + __tsan_java_init(jheap, kHeapSize); + const int kBlockSize = 16; + __tsan_java_alloc(jheap, kBlockSize); + pthread_t th; + pthread_create(&th, 0, Thread, (void*)jheap); + __tsan_write1_pc((jptr)jheap, 1234 | kExternalPCBit); + barrier_wait(&barrier); + pthread_join(th, 0); + __tsan_java_free(jheap, kBlockSize); + fprintf(stderr, "DONE\n"); + return __tsan_java_fini(); +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: #0 MyFunc MyFile.java:1234:56 +// CHECK: DONE diff --git a/test/tsan/lit.cfg b/test/tsan/lit.cfg index fdbafefbc66f..233d273f3130 100644 --- a/test/tsan/lit.cfg +++ b/test/tsan/lit.cfg @@ -56,7 +56,7 @@ clang_tsan_cxxflags = config.cxx_mode_flags + clang_tsan_cflags + ["-std=c++11"] if config.has_libcxx and config.host_os != 'Darwin': # FIXME: Dehardcode this path somehow. libcxx_path = os.path.join(config.compiler_rt_obj_root, "lib", - "tsan", "libcxx_tsan_" + config.target_arch) + "tsan", "libcxx_tsan_%s" % config.target_arch) libcxx_incdir = os.path.join(libcxx_path, "include", "c++", "v1") libcxx_libdir = os.path.join(libcxx_path, "lib") libcxx_so = os.path.join(libcxx_libdir, "libc++.so") @@ -85,5 +85,8 @@ if config.host_os not in ['FreeBSD', 'Linux', 'Darwin', 'NetBSD']: if config.android: config.unsupported = True -if config.host_os == 'Darwin' and config.target_arch in ["x86_64", "x86_64h"]: - config.parallelism_group = "darwin-64bit-sanitizer" +if config.host_os == 'Darwin': + if config.target_arch in ["x86_64", "x86_64h"]: + config.parallelism_group = "darwin-64bit-sanitizer" + elif config.apple_platform != "osx" and not config.apple_platform.endswith("sim"): + config.parallelism_group = "darwin-ios-device-sanitizer" diff --git a/test/tsan/lit.site.cfg.in b/test/tsan/lit.site.cfg.in index a215e664a5b4..6dec5f92b271 100644 --- a/test/tsan/lit.site.cfg.in +++ b/test/tsan/lit.site.cfg.in @@ -3,8 +3,7 @@ config.name_suffix = "@TSAN_TEST_CONFIG_SUFFIX@" config.tsan_lit_source_dir = "@TSAN_LIT_SOURCE_DIR@" config.has_libcxx = @TSAN_HAS_LIBCXX@ -config.ios = @TSAN_TEST_IOS_PYBOOL@ -config.iossim = @TSAN_TEST_IOSSIM_PYBOOL@ +config.apple_platform = "@TSAN_TEST_APPLE_PLATFORM@" config.target_cflags = "@TSAN_TEST_TARGET_CFLAGS@" config.target_arch = "@TSAN_TEST_TARGET_ARCH@" diff --git a/test/tsan/mutex_destroy_locked2.cc b/test/tsan/mutex_destroy_locked2.cc new file mode 100644 index 000000000000..e29c96138a8e --- /dev/null +++ b/test/tsan/mutex_destroy_locked2.cc @@ -0,0 +1,29 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +#include <pthread.h> +#include <unistd.h> + +void *thread(void *arg) { + pthread_mutex_t m; + pthread_mutex_init(&m, 0); + pthread_mutex_lock(&m); + pthread_mutex_destroy(&m); + return 0; +} + +int main() { + pthread_t th; + pthread_create(&th, 0, thread, 0); + pthread_join(th, 0); + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: destroy of a locked mutex +// CHECK: #0 pthread_mutex_destroy +// CHECK: #1 thread +// CHECK: and: +// CHECK: #0 pthread_mutex_lock +// CHECK: #1 thread +// CHECK: Mutex {{.*}} created at: +// CHECK: #0 pthread_mutex_init +// CHECK: #1 thread +// CHECK: SUMMARY: ThreadSanitizer: destroy of a locked mutex {{.*}} in thread diff --git a/test/tsan/race_on_fputs.cc b/test/tsan/race_on_fputs.cc new file mode 100644 index 000000000000..53042e3d36bc --- /dev/null +++ b/test/tsan/race_on_fputs.cc @@ -0,0 +1,29 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +#include "test.h" + +char s[] = "abracadabra"; + +void *Thread0(void *p) { + fputs(s, stdout); + barrier_wait(&barrier); + return 0; +} + +void *Thread1(void *p) { + barrier_wait(&barrier); + s[3] = 'z'; + return 0; +} + +int main() { + barrier_init(&barrier, 2); + pthread_t th[2]; + pthread_create(&th[0], 0, Thread0, 0); + pthread_create(&th[1], 0, Thread1, 0); + pthread_join(th[0], 0); + pthread_join(th[1], 0); + fprintf(stderr, "DONE"); +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: DONE diff --git a/test/tsan/simple_stack2.cc b/test/tsan/simple_stack2.cc index 12ee0da31090..bbea71307749 100644 --- a/test/tsan/simple_stack2.cc +++ b/test/tsan/simple_stack2.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_tsan -O1 %s -o %T/simple_stack2.cc.exe && %deflake %run %T/simple_stack2.cc.exe | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s #include "test.h" int Global; @@ -44,10 +44,10 @@ int main() { // CHECK: WARNING: ThreadSanitizer: data race // CHECK-NEXT: Write of size 4 at {{.*}} by thread T1: -// CHECK-NEXT: #0 foo1{{.*}} {{.*}}simple_stack2.cc:7{{(:10)?}} ({{.*}}) -// CHECK-NEXT: #1 bar1{{.*}} {{.*}}simple_stack2.cc:14{{(:3)?}} ({{.*}}) -// CHECK-NEXT: #2 Thread1{{.*}} {{.*}}simple_stack2.cc:32{{(:3)?}} ({{.*}}) +// CHECK-NEXT: #0 foo1{{.*}} {{.*}}simple_stack2.cc:[[@LINE-40]]{{(:10)?}} ({{.*}}) +// CHECK-NEXT: #1 bar1{{.*}} {{.*}}simple_stack2.cc:[[@LINE-34]]{{(:3)?}} ({{.*}}) +// CHECK-NEXT: #2 Thread1{{.*}} {{.*}}simple_stack2.cc:[[@LINE-17]]{{(:3)?}} ({{.*}}) // CHECK: Previous read of size 4 at {{.*}} by main thread: -// CHECK-NEXT: #0 foo2{{.*}} {{.*}}simple_stack2.cc:18{{(:22)?}} ({{.*}}) -// CHECK-NEXT: #1 bar2{{.*}} {{.*}}simple_stack2.cc:27{{(:3)?}} ({{.*}}) -// CHECK-NEXT: #2 main{{.*}} {{.*}}simple_stack2.cc:40{{(:3)?}} ({{.*}}) +// CHECK-NEXT: #0 foo2{{.*}} {{.*}}simple_stack2.cc:[[@LINE-33]]{{(:22)?}} ({{.*}}) +// CHECK-NEXT: #1 bar2{{.*}} {{.*}}simple_stack2.cc:[[@LINE-25]]{{(:3)?}} ({{.*}}) +// CHECK-NEXT: #2 main{{.*}} {{.*}}simple_stack2.cc:[[@LINE-13]]{{(:3)?}} ({{.*}}) diff --git a/test/tsan/static_init6.cc b/test/tsan/static_init6.cc index fd22e0a02e6a..06215ced3c76 100644 --- a/test/tsan/static_init6.cc +++ b/test/tsan/static_init6.cc @@ -1,4 +1,5 @@ -// RUN: %clangxx_tsan -stdlib=libstdc++ -static-libstdc++ -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_tsan %linux_static_libstdcplusplus -O1 %s -o %t && %run %t 2>&1 \ +// RUN: | FileCheck %s #include <pthread.h> #include <stdlib.h> #include <stdio.h> diff --git a/test/tsan/strerror_r.cc b/test/tsan/strerror_r.cc index ad482013012c..cfe8a18c1736 100644 --- a/test/tsan/strerror_r.cc +++ b/test/tsan/strerror_r.cc @@ -1,26 +1,30 @@ // RUN: %clangxx_tsan -O1 -DTEST_ERROR=ERANGE %s -o %t && %run %t 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-SYS %s // RUN: %clangxx_tsan -O1 -DTEST_ERROR=-1 %s -o %t && not %run %t 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-USER %s // UNSUPPORTED: darwin +// This test provokes a data race under FreeBSD +// XFAIL: freebsd + +#include "test.h" -#include <assert.h> #include <errno.h> #include <pthread.h> -#include <stdio.h> #include <string.h> char buffer[1000]; void *Thread(void *p) { + barrier_wait(&barrier); strerror_r(TEST_ERROR, buffer, sizeof(buffer)); return buffer; } int main() { - pthread_t th[2]; - pthread_create(&th[0], 0, Thread, 0); - pthread_create(&th[1], 0, Thread, 0); - pthread_join(th[0], 0); - pthread_join(th[1], 0); + barrier_init(&barrier, 2); + pthread_t th; + pthread_create(&th, 0, Thread, 0); + strerror_r(TEST_ERROR, buffer, sizeof(buffer)); + barrier_wait(&barrier); + pthread_join(th, 0); fprintf(stderr, "DONE\n"); } diff --git a/test/tsan/suppressions_mutex.cc b/test/tsan/suppressions_mutex.cc new file mode 100644 index 000000000000..5d3a5d05289f --- /dev/null +++ b/test/tsan/suppressions_mutex.cc @@ -0,0 +1,19 @@ +// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=suppressions='%s.supp' %run %t 2>&1 | FileCheck %s +#include "test.h" + +void __attribute__((noinline)) suppress_this(pthread_mutex_t *mu) { + pthread_mutex_destroy(mu); +} + +int main() { + pthread_mutex_t mu; + pthread_mutex_init(&mu, 0); + pthread_mutex_lock(&mu); + suppress_this(&mu); + fprintf(stderr, "DONE\n"); + return 0; +} + +// CHECK-NOT: failed to open suppressions file +// CHECK-NOT: WARNING: ThreadSanitizer: +// CHECK: DONE diff --git a/test/tsan/suppressions_mutex.cc.supp b/test/tsan/suppressions_mutex.cc.supp new file mode 100644 index 000000000000..595febbea5ce --- /dev/null +++ b/test/tsan/suppressions_mutex.cc.supp @@ -0,0 +1,2 @@ +mutex:suppress_this + diff --git a/test/tsan/test.h b/test/tsan/test.h index bc4f7aad55fe..595590b58ce2 100644 --- a/test/tsan/test.h +++ b/test/tsan/test.h @@ -56,7 +56,7 @@ unsigned long long monotonic_clock_ns() { #endif //The const kPCInc must be in sync with StackTrace::GetPreviousInstructionPc -#if defined(__powerpc64__) +#if defined(__powerpc64__) || defined(__arm__) || defined(__aarch64__) // PCs are always 4 byte aligned. const int kPCInc = 4; #elif defined(__sparc__) || defined(__mips__) diff --git a/test/tsan/thread_name.cc b/test/tsan/thread_name.cc index 17caa62ef440..1fa055579ee0 100644 --- a/test/tsan/thread_name.cc +++ b/test/tsan/thread_name.cc @@ -7,7 +7,7 @@ #elif defined(__FreeBSD__) #include <pthread_np.h> #define USE_PTHREAD_SETNAME_NP 1 -#define tasn_pthread_setname_np pthread_set_name_np +#define tsan_pthread_setname_np pthread_set_name_np #elif defined(__NetBSD__) #define USE_PTHREAD_SETNAME_NP 1 #define tsan_pthread_setname_np(a, b) pthread_setname_np((a), "%s", (void *)(b)) diff --git a/test/tsan/tls_race2.cc b/test/tsan/tls_race2.cc index f3139b69fc08..5968e66d5b18 100644 --- a/test/tsan/tls_race2.cc +++ b/test/tsan/tls_race2.cc @@ -22,6 +22,8 @@ int main() { pthread_t t; pthread_create(&t, 0, Thread, 0); pthread_join(t, 0); + fprintf(stderr, "DONE\n"); + return 0; } // CHECK: WARNING: ThreadSanitizer: data race @@ -29,3 +31,4 @@ int main() { // CHECK-FreeBSD: Location is TLS of thread T1. // CHECK-NetBSD: Location is TLS of thread T1. // CHECK-Darwin: Location is heap block of size 4 +// CHECK: DONE diff --git a/test/ubsan/CMakeLists.txt b/test/ubsan/CMakeLists.txt index 7791681472fd..fa8b16b8093e 100644 --- a/test/ubsan/CMakeLists.txt +++ b/test/ubsan/CMakeLists.txt @@ -38,6 +38,9 @@ set(UBSAN_TEST_ARCH ${UBSAN_SUPPORTED_ARCH}) if(APPLE) darwin_filter_host_archs(UBSAN_SUPPORTED_ARCH UBSAN_TEST_ARCH) endif() +if(OS_NAME MATCHES "SunOS") + list(REMOVE_ITEM UBSAN_TEST_ARCH x86_64) +endif() foreach(arch ${UBSAN_TEST_ARCH}) set(UBSAN_TEST_TARGET_ARCH ${arch}) diff --git a/test/ubsan/TestCases/Float/cast-overflow.cpp b/test/ubsan/TestCases/Float/cast-overflow.cpp index a53c663b1367..460150aa3b2e 100644 --- a/test/ubsan/TestCases/Float/cast-overflow.cpp +++ b/test/ubsan/TestCases/Float/cast-overflow.cpp @@ -29,6 +29,16 @@ # ifndef LITTLE_ENDIAN # define LITTLE_ENDIAN _LITTLE_ENDIAN # endif +#elif defined(__sun__) && defined(__svr4__) +// Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h. +# include <sys/types.h> +# define BIG_ENDIAN 4321 +# define LITTLE_ENDIAN 1234 +# if defined(_BIG_ENDIAN) +# define BYTE_ORDER BIG_ENDIAN +# else +# define BYTE_ORDER LITTLE_ENDIAN +# endif #elif defined(_WIN32) # define BYTE_ORDER 0 # define BIG_ENDIAN 1 diff --git a/test/ubsan/TestCases/Integer/negate-overflow.cpp b/test/ubsan/TestCases/Integer/negate-overflow.cpp index 72438d3fba7f..5e36b9db657f 100644 --- a/test/ubsan/TestCases/Integer/negate-overflow.cpp +++ b/test/ubsan/TestCases/Integer/negate-overflow.cpp @@ -1,10 +1,12 @@ // RUN: %clangxx -fsanitize=signed-integer-overflow %s -o %t1 && %run %t1 2>&1 | FileCheck %s --check-prefix=CHECKS // RUN: %clangxx -fsanitize=unsigned-integer-overflow %s -o %t2 && %run %t2 2>&1 | FileCheck %s --check-prefix=CHECKU +// RUN: %clangxx -fsanitize=unsigned-integer-overflow %s -o %t2 && %env_ubsan_opts=silence_unsigned_overflow=1 %run %t2 2>&1 | FileCheck %s --check-prefix=CHECKU-SILENT --allow-empty int main() { // CHECKS-NOT: runtime error - // CHECKU: negate-overflow.cpp:[[@LINE+2]]:3: runtime error: negation of 2147483648 cannot be represented in type 'unsigned int' + // CHECKU: negate-overflow.cpp:[[@LINE+3]]:3: runtime error: negation of 2147483648 cannot be represented in type 'unsigned int' // CHECKU-NOT: cast to an unsigned + // CHECKU-SILENT-NOT: runtime error -unsigned(-0x7fffffff - 1); // ok // CHECKS: negate-overflow.cpp:[[@LINE+2]]:3: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself // CHECKU-NOT: runtime error diff --git a/test/ubsan/TestCases/Integer/no-recover.cpp b/test/ubsan/TestCases/Integer/no-recover.cpp index bbc2f8d2c1c4..515ebbd0702e 100644 --- a/test/ubsan/TestCases/Integer/no-recover.cpp +++ b/test/ubsan/TestCases/Integer/no-recover.cpp @@ -1,5 +1,6 @@ // RUN: %clangxx -fsanitize=unsigned-integer-overflow %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=RECOVER // RUN: %clangxx -fsanitize=unsigned-integer-overflow -fno-sanitize-recover=all -fsanitize-recover=unsigned-integer-overflow %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=RECOVER +// RUN: %env_ubsan_opts=silence_unsigned_overflow=1 %run %t 2>&1 | FileCheck %s --check-prefix=SILENT-RECOVER --allow-empty // RUN: %clangxx -fsanitize=unsigned-integer-overflow -fno-sanitize-recover=unsigned-integer-overflow %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=ABORT #include <stdint.h> @@ -18,5 +19,6 @@ int main() { (void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull)); // RECOVER: 10000000000000000000 + 9000000000000000000 cannot be represented in type 'unsigned {{long( long)?}}' + // SILENT-RECOVER-NOT: runtime error // ABORT-NOT: runtime error } diff --git a/test/ubsan/TestCases/Integer/suppressions.cpp b/test/ubsan/TestCases/Integer/suppressions.cpp index f72d82edf278..65d8bba13b01 100644 --- a/test/ubsan/TestCases/Integer/suppressions.cpp +++ b/test/ubsan/TestCases/Integer/suppressions.cpp @@ -4,6 +4,8 @@ // requires the compiler-rt runtime to be able to symbolize stack addresses. // REQUIRES: can-symbolize // UNSUPPORTED: android +// Output differs on OpenBSD longer by displaying the values. +// XFAIL: openbsd // Fails without any suppression. // RUN: %env_ubsan_opts=halt_on_error=1 not %run %t 2>&1 | FileCheck %s diff --git a/test/ubsan/TestCases/Misc/coverage-levels.cc b/test/ubsan/TestCases/Misc/coverage-levels.cc index 05c19937ddf8..364f985c5051 100644 --- a/test/ubsan/TestCases/Misc/coverage-levels.cc +++ b/test/ubsan/TestCases/Misc/coverage-levels.cc @@ -3,26 +3,28 @@ // FIXME: Port the environment variable logic below for the lit shell. // REQUIRES: shell // -// RUN: rm -rf %T/coverage-levels && mkdir %T/coverage-levels +// RUN: rm -rf %t-dir && mkdir %t-dir // RUN: %clangxx -fsanitize=shift -DGOOD_SHIFT=1 -O1 -fsanitize-coverage=func %s -o %t -// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%T/coverage-levels"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN +// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%t-dir"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN // RUN: %clangxx -fsanitize=undefined -DGOOD_SHIFT=1 -O1 -fsanitize-coverage=func %s -o %t -// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%T/coverage-levels"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN +// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%t-dir"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN // Also works without any sanitizer. // RUN: %clangxx -DGOOD_SHIFT=1 -O1 -fsanitize-coverage=func %s -o %t -// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%T/coverage-levels"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN +// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%t-dir"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN // RUN: %clangxx -fsanitize=shift -O1 -fsanitize-coverage=func %s -o %t -// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%T/coverage-levels"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_WARN +// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%t-dir"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_WARN // RUN: %clangxx -fsanitize=shift -O1 -fsanitize-coverage=bb %s -o %t -// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%T/coverage-levels"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 --check-prefix=CHECK_WARN +// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%t-dir"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 --check-prefix=CHECK_WARN // RUN: %clangxx -fsanitize=shift -O1 -fsanitize-coverage=edge %s -o %t -// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%T/coverage-levels"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN +// RUN: %env_ubsan_opts=coverage=1:verbosity=1:coverage_dir='"%t-dir"' %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN // Coverage is not yet implemented in TSan. // XFAIL: ubsan-tsan // UNSUPPORTED: ubsan-standalone-static +// No coverage support +// UNSUPPORTED: openbsd volatile int sink; int main(int argc, char **argv) { diff --git a/test/ubsan/TestCases/Misc/missing_return.cpp b/test/ubsan/TestCases/Misc/missing_return.cpp index 5c5b286f1a65..fe8c8bae603d 100644 --- a/test/ubsan/TestCases/Misc/missing_return.cpp +++ b/test/ubsan/TestCases/Misc/missing_return.cpp @@ -1,6 +1,8 @@ // RUN: %clangxx -fsanitize=return %gmlt %s -O3 -o %t // RUN: not %run %t 2>&1 | FileCheck %s // RUN: %env_ubsan_opts=print_stacktrace=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-STACKTRACE +// Error message does not exact what expected +// XFAIL: openbsd // CHECK: missing_return.cpp:[[@LINE+1]]:5: runtime error: execution reached the end of a value-returning function without returning a value int f() { diff --git a/test/ubsan/TestCases/Misc/monitor.cpp b/test/ubsan/TestCases/Misc/monitor.cpp new file mode 100644 index 000000000000..6c5cacfed8be --- /dev/null +++ b/test/ubsan/TestCases/Misc/monitor.cpp @@ -0,0 +1,44 @@ +// RUN: %clangxx -w -fsanitize=bool %s -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +// __ubsan_on_report is not defined as weak. Redefining it here isn't supported +// on Windows. +// +// UNSUPPORTED: win32 +// Linkage issue +// XFAIL: openbsd + +#include <cstdio> + +extern "C" { +void __ubsan_get_current_report_data(const char **OutIssueKind, + const char **OutMessage, + const char **OutFilename, + unsigned *OutLine, unsigned *OutCol, + char **OutMemoryAddr); + +// Override the definition of __ubsan_on_report from the runtime, just for +// testing purposes. +void __ubsan_on_report(void) { + const char *IssueKind, *Message, *Filename; + unsigned Line, Col; + char *Addr; + __ubsan_get_current_report_data(&IssueKind, &Message, &Filename, &Line, &Col, + &Addr); + + printf("Issue: %s\n", IssueKind); + printf("Location: %s:%u:%u\n", Filename, Line, Col); + printf("Message: %s\n", Message); + + (void)Addr; +} +} + +int main() { + char C = 3; + bool B = *(bool *)&C; + // CHECK: Issue: invalid-bool-load + // CHECK-NEXT: Location: {{.*}}monitor.cpp:[[@LINE-2]]:12 + // CHECK-NEXT: Message: Load of value 3, which is not a valid value for type 'bool' + return 0; +} diff --git a/test/ubsan/TestCases/TypeCheck/Function/function.cpp b/test/ubsan/TestCases/TypeCheck/Function/function.cpp index 25b2bdc32c7a..7b9f0982639a 100644 --- a/test/ubsan/TestCases/TypeCheck/Function/function.cpp +++ b/test/ubsan/TestCases/TypeCheck/Function/function.cpp @@ -1,8 +1,10 @@ -// RUN: %clangxx -fsanitize=function %s -O3 -g -o %t +// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -o %t // RUN: %run %t 2>&1 | FileCheck %s // Verify that we can disable symbolization if needed: // RUN: %env_ubsan_opts=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM // XFAIL: win32,win64 +// Unsupported function flag +// UNSUPPORTED: openbsd #include <stdint.h> @@ -23,9 +25,49 @@ void make_invalid_call() { reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(f))(42); } +void f1(int) {} +void f2(unsigned int) {} +void f3(int) noexcept {} +void f4(unsigned int) noexcept {} + +void check_noexcept_calls() { + void (*p1)(int); + p1 = &f1; + p1(0); + p1 = reinterpret_cast<void (*)(int)>(&f2); + // CHECK: function.cpp:[[@LINE+2]]:3: runtime error: call to function f2(unsigned int) through pointer to incorrect function type 'void (*)(int)' + // NOSYM: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)' + p1(0); + p1 = &f3; + p1(0); + p1 = reinterpret_cast<void (*)(int)>(&f4); + // CHECK: function.cpp:[[@LINE+2]]:3: runtime error: call to function f4(unsigned int) through pointer to incorrect function type 'void (*)(int)' + // NOSYM: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)' + p1(0); + + void (*p2)(int) noexcept; + p2 = reinterpret_cast<void (*)(int) noexcept>(&f1); + // TODO: Unclear whether calling a non-noexcept function through a pointer to + // nexcept function should cause an error. + // CHECK-NOT: function.cpp:[[@LINE+2]]:3: runtime error: call to function f1(int) through pointer to incorrect function type 'void (*)(int) noexcept' + // NOSYM-NOT: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int) noexcept' + p2(0); + p2 = reinterpret_cast<void (*)(int) noexcept>(&f2); + // CHECK: function.cpp:[[@LINE+2]]:3: runtime error: call to function f2(unsigned int) through pointer to incorrect function type 'void (*)(int) noexcept' + // NOSYM: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int) noexcept' + p2(0); + p2 = &f3; + p2(0); + p2 = reinterpret_cast<void (*)(int) noexcept>(&f4); + // CHECK: function.cpp:[[@LINE+2]]:3: runtime error: call to function f4(unsigned int) through pointer to incorrect function type 'void (*)(int) noexcept' + // NOSYM: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int) noexcept' + p2(0); +} + int main(void) { make_valid_call(); make_invalid_call(); + check_noexcept_calls(); // Check that no more errors will be printed. // CHECK-NOT: runtime error: call to function // NOSYM-NOT: runtime error: call to function diff --git a/test/ubsan/TestCases/TypeCheck/misaligned.cpp b/test/ubsan/TestCases/TypeCheck/misaligned.cpp index 4eaedf37e565..a5cefaa31cd6 100644 --- a/test/ubsan/TestCases/TypeCheck/misaligned.cpp +++ b/test/ubsan/TestCases/TypeCheck/misaligned.cpp @@ -11,6 +11,8 @@ // RUN: %clangxx -fsanitize=alignment -fno-sanitize-recover=alignment %s -O3 -o %t // RUN: not %run %t w1 2>&1 | FileCheck %s --check-prefix=CHECK-WILD +// Compilation error make the test fails. +// XFAIL: openbsd #include <new> diff --git a/test/ubsan/TestCases/TypeCheck/vptr.cpp b/test/ubsan/TestCases/TypeCheck/vptr.cpp index d7848c4ce3f9..9b53e8095777 100644 --- a/test/ubsan/TestCases/TypeCheck/vptr.cpp +++ b/test/ubsan/TestCases/TypeCheck/vptr.cpp @@ -40,6 +40,8 @@ // UNSUPPORTED: win32 // Suppressions file not pushed to the device. // UNSUPPORTED: android +// Compilation error +// UNSUPPORTED: openbsd #include <new> #include <typeinfo> #include <assert.h> diff --git a/test/ubsan/lit.common.cfg b/test/ubsan/lit.common.cfg index 83475a2dc36c..e20832bd655f 100644 --- a/test/ubsan/lit.common.cfg +++ b/test/ubsan/lit.common.cfg @@ -68,7 +68,7 @@ config.substitutions.append( ("%gmlt ", " ".join(config.debug_info_flags) + " ") config.suffixes = ['.c', '.cc', '.cpp'] # Check that the host supports UndefinedBehaviorSanitizer tests -if config.host_os not in ['Linux', 'Darwin', 'FreeBSD', 'Windows', 'NetBSD']: +if config.host_os not in ['Linux', 'Darwin', 'FreeBSD', 'Windows', 'NetBSD', 'SunOS', 'OpenBSD']: config.unsupported = True config.available_features.add('arch=' + config.target_arch) diff --git a/test/ubsan_minimal/CMakeLists.txt b/test/ubsan_minimal/CMakeLists.txt index 712654e94518..5da5fcd02b94 100644 --- a/test/ubsan_minimal/CMakeLists.txt +++ b/test/ubsan_minimal/CMakeLists.txt @@ -4,6 +4,9 @@ set(UBSAN_TEST_ARCH ${UBSAN_SUPPORTED_ARCH}) if(APPLE) darwin_filter_host_archs(UBSAN_SUPPORTED_ARCH UBSAN_TEST_ARCH) endif() +if(OS_NAME MATCHES "SunOS") + list(REMOVE_ITEM UBSAN_TEST_ARCH x86_64) +endif() set(UBSAN_TESTSUITES) set(UBSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) diff --git a/test/ubsan_minimal/lit.common.cfg b/test/ubsan_minimal/lit.common.cfg index e8b42bb823c8..a436a315f0a6 100644 --- a/test/ubsan_minimal/lit.common.cfg +++ b/test/ubsan_minimal/lit.common.cfg @@ -30,7 +30,7 @@ config.substitutions.append( ("%clangxx ", build_invocation(clang_ubsan_cxxflags config.suffixes = ['.c', '.cc', '.cpp'] # Check that the host supports UndefinedBehaviorSanitizerMinimal tests -if config.host_os not in ['Linux', 'FreeBSD', 'NetBSD', 'Darwin']: # TODO: Windows +if config.host_os not in ['Linux', 'FreeBSD', 'NetBSD', 'Darwin', 'OpenBSD']: # TODO: Windows config.unsupported = True # Don't target x86_64h if the test machine can't execute x86_64h binaries. diff --git a/test/xray/CMakeLists.txt b/test/xray/CMakeLists.txt index b51b3cd0ccd8..d049ac0f979f 100644 --- a/test/xray/CMakeLists.txt +++ b/test/xray/CMakeLists.txt @@ -28,11 +28,13 @@ if (COMPILER_RT_BUILD_XRAY AND COMPILER_RT_HAS_XRAY) # Add 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 XRAY_TEST_DEPS XRayUnitTests) - list(APPEND XRAY_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit) + if(UNIX AND NOT APPLE) + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg) + list(APPEND XRAY_TEST_DEPS XRayUnitTests) + list(APPEND XRAY_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit) + endif() endif() endif() diff --git a/test/xray/TestCases/Linux/always-never-instrument.cc b/test/xray/TestCases/Posix/always-never-instrument.cc index 4e196859bcda..fd9299b756bb 100644 --- a/test/xray/TestCases/Linux/always-never-instrument.cc +++ b/test/xray/TestCases/Posix/always-never-instrument.cc @@ -9,7 +9,7 @@ // RUN: FileCheck %s --check-prefix NOINSTR // RUN: %llvm_xray extract -symbolize %t | \ // RUN: FileCheck %s --check-prefix ALWAYSINSTR -// REQUIRES: x86_64-linux +// REQUIRES: x86_64-target-arch // REQUIRES: built-in-llvm-tree // NOINSTR-NOT: {{.*__xray_NeverInstrumented.*}} diff --git a/test/xray/TestCases/Linux/arg1-arg0-logging.cc b/test/xray/TestCases/Posix/arg1-arg0-logging.cc index e7730bfa6172..757f81a8babb 100644 --- a/test/xray/TestCases/Linux/arg1-arg0-logging.cc +++ b/test/xray/TestCases/Posix/arg1-arg0-logging.cc @@ -1,7 +1,7 @@ // Allow having both the no-arg and arg1 logging implementation live together, // and be called in the correct cases. // -// RUN: rm arg0-arg1-logging-* || true +// RUN: rm -f arg0-arg1-logging-* // RUN: %clangxx_xray -std=c++11 %s -o %t // RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=arg0-arg1-logging-" %run %t // diff --git a/test/xray/TestCases/Linux/arg1-logger.cc b/test/xray/TestCases/Posix/arg1-logger.cc index 25dda13fb23d..a6ca0a495250 100644 --- a/test/xray/TestCases/Linux/arg1-logger.cc +++ b/test/xray/TestCases/Posix/arg1-logger.cc @@ -2,13 +2,13 @@ // using a custom logging function. // // RUN: %clangxx_xray -std=c++11 %s -o %t -// RUN: rm arg1-logger-* || true +// RUN: rm -f arg1-logger-* // RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_naive_log=true \ // RUN: xray_logfile_base=arg1-logger-" %run %t 2>&1 | FileCheck %s // // After all that, clean up the XRay log file. // -// RUN: rm arg1-logger-* || true +// RUN: rm -f arg1-logger-* // // At the time of writing, the ARM trampolines weren't written yet. // XFAIL: arm || aarch64 || mips diff --git a/test/xray/TestCases/Linux/arg1-logging-implicit-this.cc b/test/xray/TestCases/Posix/arg1-logging-implicit-this.cc index 66dfce9a3b7d..d8dd62247bff 100644 --- a/test/xray/TestCases/Linux/arg1-logging-implicit-this.cc +++ b/test/xray/TestCases/Posix/arg1-logging-implicit-this.cc @@ -1,10 +1,10 @@ // Intercept the implicit 'this' argument of class member functions. // // RUN: %clangxx_xray -g -std=c++11 %s -o %t -// RUN: rm log-args-this-* || true +// RUN: rm -f log-args-this-* // RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=log-args-this-" %run %t // -// XFAIL: arm || aarch64 || mips +// XFAIL: FreeBSD || arm || aarch64 || mips // UNSUPPORTED: powerpc64le #include "xray/xray_interface.h" #include <cassert> diff --git a/test/xray/TestCases/Linux/argv0-log-file-name.cc b/test/xray/TestCases/Posix/argv0-log-file-name.cc index 2f9a234f8064..2f9a234f8064 100644 --- a/test/xray/TestCases/Linux/argv0-log-file-name.cc +++ b/test/xray/TestCases/Posix/argv0-log-file-name.cc diff --git a/test/xray/TestCases/Linux/basic-filtering.cc b/test/xray/TestCases/Posix/basic-filtering.cc index b758859cf6cb..db07ef510c5c 100644 --- a/test/xray/TestCases/Linux/basic-filtering.cc +++ b/test/xray/TestCases/Posix/basic-filtering.cc @@ -2,8 +2,8 @@ // logging implementation. // RUN: %clangxx_xray -std=c++11 %s -o %t -g -// RUN: rm basic-filtering-* || true -// RUN: XRAY_OPTIONS="patch_premain=true xray_naive_log=true verbosity=1 \ +// RUN: rm -f basic-filtering-* +// RUN: XRAY_OPTIONS="patch_premain=true xray_mode=xray-basic verbosity=1 \ // RUN: xray_logfile_base=basic-filtering- \ // RUN: xray_naive_log_func_duration_threshold_us=1000 \ // RUN: xray_naive_log_max_stack_depth=2" %run %t 2>&1 | \ @@ -11,9 +11,19 @@ // RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \ // RUN: "`ls basic-filtering-* | head -1`" | \ // RUN: FileCheck %s --check-prefix TRACE -// RUN: rm basic-filtering-* || true +// RUN: rm -f basic-filtering-* // -// REQUIRES: x86_64-linux +// Now check support for the XRAY_BASIC_OPTIONS environment variable. +// RUN: XRAY_OPTIONS="patch_premain=true xray_mode=xray-basic verbosity=1 \ +// RUN: xray_logfile_base=basic-filtering-" \ +// RUN: XRAY_BASIC_OPTIONS="func_duration_threshold_us=1000 max_stack_depth=2" \ +// RUN: %run %t 2>&1 | FileCheck %s +// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \ +// RUN: "`ls basic-filtering-* | head -1`" | \ +// RUN: FileCheck %s --check-prefix TRACE +// RUN: rm -f basic-filtering-* +// +// REQUIRES: x86_64-target-arch // REQUIRES: built-in-llvm-tree #include <cstdio> diff --git a/test/xray/TestCases/Posix/c-test.cc b/test/xray/TestCases/Posix/c-test.cc new file mode 100644 index 000000000000..28a7870d0f74 --- /dev/null +++ b/test/xray/TestCases/Posix/c-test.cc @@ -0,0 +1,15 @@ +// RUN: %clang_xray -g -fxray-modes=xray-basic,xray-fdr,xray-profiling -o %t %s +// RUN: rm -f xray-log.c-test.* +// RUN: XRAY_OPTIONS=patch_premain=true:verbosity=1:xray_mode=xray-basic %t \ +// RUN: 2>&1 | FileCheck %s +// RUN: rm -f xray-log.c-test.* +// +// REQUIRES: x86_64-target-arch +// REQUIRES: built-in-llvm-tree +__attribute__((xray_always_instrument)) void always() {} + +int main() { + always(); +} + +// CHECK: =={{[0-9].*}}==XRay: Log file in '{{.*}}' diff --git a/test/xray/TestCases/Linux/common-trampoline-alignment.cc b/test/xray/TestCases/Posix/common-trampoline-alignment.cc index 5d1cc1e9b451..dac0789abdec 100644 --- a/test/xray/TestCases/Linux/common-trampoline-alignment.cc +++ b/test/xray/TestCases/Posix/common-trampoline-alignment.cc @@ -4,7 +4,7 @@ // RUN: %clangxx_xray -std=c++11 %s -o %t // RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false" \ // RUN: %run %t 2>&1 -// REQUIRES: x86_64-linux +// REQUIRES: x86_64-target-arch // REQUIRES: built-in-llvm-tree #include "xray/xray_interface.h" #include <stdio.h> diff --git a/test/xray/TestCases/Linux/coverage-sample.cc b/test/xray/TestCases/Posix/coverage-sample.cc index 62c13ba3d42a..62c13ba3d42a 100644 --- a/test/xray/TestCases/Linux/coverage-sample.cc +++ b/test/xray/TestCases/Posix/coverage-sample.cc diff --git a/test/xray/TestCases/Linux/custom-event-handler-alignment.cc b/test/xray/TestCases/Posix/custom-event-handler-alignment.cc index 447f6e4f2b42..c8de18b0e2b6 100644 --- a/test/xray/TestCases/Linux/custom-event-handler-alignment.cc +++ b/test/xray/TestCases/Posix/custom-event-handler-alignment.cc @@ -4,7 +4,7 @@ // RUN: %clangxx_xray -std=c++11 %s -o %t // RUN: XRAY_OPTIONS="patch_premain=false verbosity=1 xray_naive_log=false" \ // RUN: %run %t 2>&1 -// REQUIRES: x86_64-linux +// REQUIRES: x86_64-target-arch // REQUIRES: built-in-llvm-tree #include <xmmintrin.h> #include <stdio.h> diff --git a/test/xray/TestCases/Linux/custom-event-logging.cc b/test/xray/TestCases/Posix/custom-event-logging.cc index 48fd62034194..48fd62034194 100644 --- a/test/xray/TestCases/Linux/custom-event-logging.cc +++ b/test/xray/TestCases/Posix/custom-event-logging.cc diff --git a/test/xray/TestCases/Posix/fdr-mode-inmemory.cc b/test/xray/TestCases/Posix/fdr-mode-inmemory.cc new file mode 100644 index 000000000000..ff31626d7779 --- /dev/null +++ b/test/xray/TestCases/Posix/fdr-mode-inmemory.cc @@ -0,0 +1,50 @@ +// RUN: %clangxx_xray -g -std=c++11 %s -o %t -fxray-modes=xray-fdr +// RUN: rm -f fdr-inmemory-test-* +// RUN: XRAY_OPTIONS="patch_premain=false xray_logfile_base=fdr-inmemory-test- \ +// RUN: verbosity=1" \ +// RUN: XRAY_FDR_OPTIONS="no_file_flush=true func_duration_threshold_us=0" \ +// RUN: %run %t 2>&1 | FileCheck %s +// RUN: FILES=`find %T -name 'fdr-inmemory-test-*' | wc -l` +// RUN: [ $FILES -eq 0 ] +// RUN: rm -f fdr-inmemory-test-* +// +// REQUIRES: x86_64-target-arch +// REQUIRES: built-in-llvm-tree + +#include "xray/xray_log_interface.h" +#include <cassert> +#include <iostream> + +uint64_t var = 0; +uint64_t buffers = 0; +[[clang::xray_always_instrument]] void __attribute__((noinline)) f() { ++var; } + +int main(int argc, char *argv[]) { + assert(__xray_log_select_mode("xray-fdr") == + XRayLogRegisterStatus::XRAY_REGISTRATION_OK); + auto status = __xray_log_init_mode( + "xray-fdr", + "buffer_size=4096:buffer_max=10:func_duration_threshold_us=0"); + assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED); + __xray_patch(); + + // Create enough entries. + for (int i = 0; i != 1 << 20; ++i) { + f(); + } + + // Then we want to verify that we're getting 10 buffers outside of the initial + // header. + auto finalize_status = __xray_log_finalize(); + assert(finalize_status == XRayLogInitStatus::XRAY_LOG_FINALIZED); + auto process_status = + __xray_log_process_buffers([](const char *, XRayBuffer) { ++buffers; }); + std::cout << "buffers = " << buffers << std::endl; + assert(process_status == XRayLogFlushStatus::XRAY_LOG_FLUSHED); + auto flush_status = __xray_log_flushLog(); + assert(flush_status == XRayLogFlushStatus::XRAY_LOG_FLUSHED); + // We expect 11 buffers because 1 header buffer + 10 actual FDR buffers. + // CHECK: Buffers = 11 + std::cout << "Buffers = " << buffers << std::endl; + return 0; +} diff --git a/test/xray/TestCases/Posix/fdr-mode-multiple.cc b/test/xray/TestCases/Posix/fdr-mode-multiple.cc new file mode 100644 index 000000000000..487e3031325e --- /dev/null +++ b/test/xray/TestCases/Posix/fdr-mode-multiple.cc @@ -0,0 +1,76 @@ +// RUN: %clangxx_xray -g -std=c++11 %s -o %t -fxray-modes=xray-fdr +// RUN: rm -f fdr-inmemory-test-* +// RUN: XRAY_OPTIONS="patch_premain=false xray_logfile_base=fdr-inmemory-test- \ +// RUN: verbosity=1" \ +// RUN: XRAY_FDR_OPTIONS="no_file_flush=true func_duration_threshold_us=0" \ +// RUN: %run %t 2>&1 | FileCheck %s +// RUN: FILES=`find %T -name 'fdr-inmemory-test-*' | wc -l` +// RUN: [ $FILES -eq 0 ] +// RUN: rm -f fdr-inmemory-test-* +// +// REQUIRES: x86_64-target-arch +// REQUIRES: built-in-llvm-tree + +#include "xray/xray_log_interface.h" +#include <cassert> +#include <iostream> + +uint64_t var = 0; +uint64_t buffers = 0; +[[clang::xray_always_instrument]] void __attribute__((noinline)) f() { ++var; } + +int main(int argc, char *argv[]) { + assert(__xray_log_select_mode("xray-fdr") == + XRayLogRegisterStatus::XRAY_REGISTRATION_OK); + auto status = __xray_log_init_mode( + "xray-fdr", + "buffer_size=4096:buffer_max=10:func_duration_threshold_us=0"); + assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED); + __xray_patch(); + + // Create enough entries. + for (int i = 0; i != 1 << 20; ++i) { + f(); + } + + // Then we want to verify that we're getting 10 buffers outside of the initial + // header. + auto finalize_status = __xray_log_finalize(); + assert(finalize_status == XRayLogInitStatus::XRAY_LOG_FINALIZED); + auto process_status = + __xray_log_process_buffers([](const char *, XRayBuffer) { ++buffers; }); + std::cout << "buffers = " << buffers << std::endl; + assert(process_status == XRayLogFlushStatus::XRAY_LOG_FLUSHED); + auto flush_status = __xray_log_flushLog(); + assert(flush_status == XRayLogFlushStatus::XRAY_LOG_FLUSHED); + // We expect 11 buffers because 1 header buffer + 10 actual FDR buffers. + // CHECK: Buffers = 11 + std::cout << "Buffers = " << buffers << std::endl; + + // In this test we ensure that we can restart the cycle after the flush. + status = __xray_log_init_mode( + "xray-fdr", + "buffer_size=4096:buffer_max=10:func_duration_threshold_us=0"); + assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED); + __xray_patch(); + + // Create enough entries. + for (int i = 0; i != 1 << 20; ++i) { + f(); + } + + // Then we want to verify that we're getting 10 buffers outside of the initial + // header. + finalize_status = __xray_log_finalize(); + assert(finalize_status == XRayLogInitStatus::XRAY_LOG_FINALIZED); + process_status = + __xray_log_process_buffers([](const char *, XRayBuffer) { ++buffers; }); + std::cout << "buffers = " << buffers << std::endl; + assert(process_status == XRayLogFlushStatus::XRAY_LOG_FLUSHED); + flush_status = __xray_log_flushLog(); + assert(flush_status == XRayLogFlushStatus::XRAY_LOG_FLUSHED); + // We expect 22 buffers because 1 header buffer + 10 actual FDR buffers, plus + // the number of buffers we got from the previous run (also 11). + // CHECK: Buffers = 22 + std::cout << "Buffers = " << buffers << std::endl; +} diff --git a/test/xray/TestCases/Linux/fdr-mode.cc b/test/xray/TestCases/Posix/fdr-mode.cc index 744c051cfb2c..b12d97c0005a 100644 --- a/test/xray/TestCases/Linux/fdr-mode.cc +++ b/test/xray/TestCases/Posix/fdr-mode.cc @@ -1,14 +1,25 @@ // RUN: %clangxx_xray -g -std=c++11 %s -o %t -// RUN: rm fdr-logging-test-* || true -// RUN: rm fdr-unwrite-test-* || true -// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false xray_logfile_base=fdr-logging-test- xray_fdr_log=true verbosity=1 xray_fdr_log_func_duration_threshold_us=0" %run %t 2>&1 | FileCheck %s -// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false xray_logfile_base=fdr-unwrite-test- xray_fdr_log=true verbosity=1 xray_fdr_log_func_duration_threshold_us=5000" %run %t 2>&1 | FileCheck %s -// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t "`ls fdr-logging-test-* | head -1`" | FileCheck %s --check-prefix=TRACE -// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t "`ls fdr-unwrite-test-* | head -1`" | FileCheck %s --check-prefix=UNWRITE +// RUN: rm -f fdr-logging-test-* +// RUN: rm -f fdr-unwrite-test-* +// RUN: XRAY_OPTIONS="patch_premain=false xray_logfile_base=fdr-logging-test- \ +// RUN: xray_mode=xray-fdr verbosity=1" \ +// RUN: XRAY_FDR_OPTIONS="func_duration_threshold_us=0" \ +// RUN: %run %t 2>&1 | FileCheck %s +// RUN: XRAY_OPTIONS="patch_premain=false \ +// RUN: xray_logfile_base=fdr-unwrite-test- xray_mode=xray-fdr \ +// RUN: verbosity=1" \ +// RUN: XRAY_FDR_OPTIONS="func_duration_threshold_us=5000" \ +// RUN: %run %t 2>&1 | FileCheck %s +// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \ +// RUN: "`ls fdr-logging-test-* | head -1`" \ +// RUN: | FileCheck %s --check-prefix=TRACE +// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \ +// RUN: "`ls fdr-unwrite-test-* | head -1`" \ +// RUN: | FileCheck %s --check-prefix=UNWRITE // RUN: rm fdr-logging-test-* // RUN: rm fdr-unwrite-test-* // FIXME: Make llvm-xray work on non-x86_64 as well. -// REQUIRES: x86_64-linux +// REQUIRES: x86_64-target-arch // REQUIRES: built-in-llvm-tree #include "xray/xray_log_interface.h" @@ -20,9 +31,6 @@ #include <thread> #include <time.h> -constexpr auto kBufferSize = 16384; -constexpr auto kBufferMax = 10; - thread_local uint64_t var = 0; [[clang::xray_always_instrument]] void __attribute__((noinline)) fC() { ++var; } @@ -35,11 +43,12 @@ void __attribute__((noinline)) fArg(int) { } int main(int argc, char *argv[]) { using namespace __xray; - FDRLoggingOptions Options; std::cout << "Logging before init." << std::endl; // CHECK: Logging before init. - auto status = __xray_log_init(kBufferSize, kBufferMax, &Options, - sizeof(FDRLoggingOptions)); + assert(__xray_log_select_mode("xray-fdr") == + XRayLogRegisterStatus::XRAY_REGISTRATION_OK); + auto status = + __xray_log_init_mode("xray-fdr", "buffer_size=16384:buffer_max=10"); assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED); std::cout << "Init status " << status << std::endl; // CHECK: Init status {{.*}} @@ -72,32 +81,32 @@ int main(int argc, char *argv[]) { } // Check that we're able to see two threads, each entering and exiting fA(). -// TRACE-DAG: - { type: 0, func-id: [[FIDA:[0-9]+]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } -// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } -// TRACE-DAG: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } -// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FIDA:[0-9]+]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } +// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}} } +// TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } // // Do the same as above for fC() -// TRACE-DAG: - { type: 0, func-id: [[FIDC:[0-9]+]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } -// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } -// TRACE-DAG: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } -// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FIDC:[0-9]+]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}} } +// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}} } +// TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } // Do the same as above for fB() -// TRACE-DAG: - { type: 0, func-id: [[FIDB:[0-9]+]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } -// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } -// TRACE-DAG: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } -// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FIDB:[0-9]+]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}} } +// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}} } +// TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } -// TRACE-DAG: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2]], kind: function-enter-arg, tsc: {{[0-9]+}} } -// TRACE-DAG: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-enter-arg, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-exit, tsc: {{[0-9]+}} } // Assert that when unwriting is enabled with a high threshold time, all the function records are erased. A CPU switch could erroneously fail this test, but // is unlikely given the test program. // Even with a high threshold, arg1 logging is never unwritten. // UNWRITE: header: // UNWRITE: records: -// UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter-arg, tsc: {{[0-9]+}} } -// UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], kind: function-exit, tsc: {{[0-9]+}} } +// UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS:[0-9]+]], kind: function-enter-arg, tsc: {{[0-9]+}} } +// UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-exit, tsc: {{[0-9]+}} } // UNWRITE-NOT: function-enter // UNWRITE-NOT: function-{{exit|tail-exit}} diff --git a/test/xray/TestCases/Linux/fdr-single-thread.cc b/test/xray/TestCases/Posix/fdr-single-thread.cc index dd50f485f82b..480502b0a60f 100644 --- a/test/xray/TestCases/Linux/fdr-single-thread.cc +++ b/test/xray/TestCases/Posix/fdr-single-thread.cc @@ -1,5 +1,5 @@ // RUN: %clangxx_xray -g -std=c++11 %s -o %t -// RUN: rm fdr-logging-1thr-* || true +// RUN: rm -f fdr-logging-1thr-* // RUN: XRAY_OPTIONS=XRAY_OPTIONS="verbosity=1 patch_premain=true \ // RUN: xray_naive_log=false xray_fdr_log=true \ // RUN: xray_fdr_log_func_duration_threshold_us=0 \ @@ -8,7 +8,7 @@ // RUN: "`ls fdr-logging-1thr-* | head -n1`" | FileCheck %s // RUN: rm fdr-logging-1thr-* // -// REQUIRES: x86_64-linux +// REQUIRES: x86_64-target-arch #include "xray/xray_log_interface.h" #include <cassert> @@ -34,5 +34,5 @@ int main(int argc, char *argv[]) { } // CHECK: records: -// CHECK-NEXT: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*fn.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } -// CHECK-NEXT: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*fn.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-exit, tsc: {{[0-9]+}} } +// CHECK-NEXT: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*fn.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } +// CHECK-NEXT: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*fn.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS:[0-9]+]], kind: function-exit, tsc: {{[0-9]+}} } diff --git a/test/xray/TestCases/Linux/fdr-thread-order.cc b/test/xray/TestCases/Posix/fdr-thread-order.cc index 8e8c421dcc66..1d6b01759f14 100644 --- a/test/xray/TestCases/Linux/fdr-thread-order.cc +++ b/test/xray/TestCases/Posix/fdr-thread-order.cc @@ -11,7 +11,7 @@ // RUN: FileCheck %s --check-prefix TRACE // RUN: rm fdr-thread-order.* // FIXME: Make llvm-xray work on non-x86_64 as well. -// REQUIRES: x86_64-linux +// REQUIRES: x86_64-target-arch // REQUIRES: built-in-llvm-tree #include "xray/xray_log_interface.h" @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) { } // We want to make sure that the order of the function log doesn't matter. -// TRACE-DAG: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } -// TRACE-DAG: - { type: 0, func-id: [[FID2:[0-9]+]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } -// TRACE-DAG: - { type: 0, func-id: [[FID1]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1]], kind: {{function-exit|function-tail-exit}}, tsc: {{[0-9]+}} } -// TRACE-DAG: - { type: 0, func-id: [[FID2]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2]], kind: {{function-exit|function-tail-exit}}, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FID1:[0-9]+]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FID2:[0-9]+]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FID1]], function: {{.*f1.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS]], kind: {{function-exit|function-tail-exit}}, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[FID2]], function: {{.*f2.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: {{function-exit|function-tail-exit}}, tsc: {{[0-9]+}} } diff --git a/test/xray/TestCases/Linux/fixedsize-logging.cc b/test/xray/TestCases/Posix/fixedsize-logging.cc index a2a41ce60d6e..a2a41ce60d6e 100644 --- a/test/xray/TestCases/Linux/fixedsize-logging.cc +++ b/test/xray/TestCases/Posix/fixedsize-logging.cc diff --git a/test/xray/TestCases/Posix/fork_basic_logging.cc b/test/xray/TestCases/Posix/fork_basic_logging.cc new file mode 100644 index 000000000000..5aefdec08016 --- /dev/null +++ b/test/xray/TestCases/Posix/fork_basic_logging.cc @@ -0,0 +1,100 @@ +// Check that when forking in basic logging mode, we get the different tids for child and parent +// RUN: %clangxx_xray -g -std=c++11 %s -o %t +// RUN: rm -f fork-basic-logging-test-* +// RUN: XRAY_OPTIONS="patch_premain=true xray_logfile_base=fork-basic-logging-test- \ +// RUN: xray_mode=xray-basic verbosity=1 xray_naive_log_func_duration_threshold_us=0" \ +// RUN: %run %t 2>&1 | FileCheck %s +// RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \ +// RUN: "`ls -S fork-basic-logging-test-* | head -1`" \ +// RUN: | FileCheck %s --check-prefix=TRACE + +// REQUIRES: x86_64-target-arch +// REQUIRES: built-in-llvm-tree + +#include "xray/xray_log_interface.h" +#include <stdio.h> +#include <unistd.h> +#include <stdint.h> +#include <sys/syscall.h> + +//modified from sanitizer + +static uintptr_t syscall_gettid() { + uint64_t retval; + asm volatile("syscall" : "=a"(retval) : "a"(__NR_gettid) : "rcx", "r11", + "memory", "cc"); + return retval; +} + +///////////// + +static uint64_t parent_tid; + +[[clang::xray_always_instrument]] +uint64_t __attribute__((noinline)) log_syscall_gettid() +{ + //don't optimize this function away + uint64_t tid = syscall_gettid(); + printf("Logging tid %lu\n", tid); + return tid; +} + +[[clang::xray_always_instrument, clang::xray_log_args(1)]] +void __attribute__((noinline)) print_parent_tid(uint64_t tid) +{ + printf("Parent with tid %lu", tid); +} + +[[clang::xray_always_instrument, clang::xray_log_args(1)]] +void __attribute__((noinline)) print_child_tid(uint64_t tid) +{ + printf("Child with tid %lu", tid); +} + +[[clang::xray_always_instrument]] void __attribute__((noinline)) print_parent_or_child() +{ + uint64_t tid = syscall_gettid(); + if(tid == parent_tid) + { + print_parent_tid(tid); + } + else + { + print_child_tid(tid); + } +} + +int main() +{ + parent_tid = log_syscall_gettid(); + if(fork()) + { + print_parent_or_child(); + // CHECK-DAG: Parent with tid + } + else + { + print_parent_or_child(); + // CHECK-DAG: Child with tid + } + return 0; +} + +// Make sure we know which thread is the parent process +// TRACE-DAG: - { type: 0, func-id: [[LSGT:[0-9]+]], function: {{.*log_syscall_gettid.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } + +// TRACE-DAG: - { type: 0, func-id: [[PPOC:[0-9]+]], function: {{.*print_parent_or_child.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS1]], kind: function-enter, tsc: {{[0-9]+}} } +// +// The parent will print its pid +// TRACE-DAG: - { type: 0, func-id: [[PPTARG:[0-9]+]], function: {{.*print_parent_tid.*}}, args: [ [[THREAD1]] ], cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS1]], kind: function-enter-arg, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[PPTARG]], function: {{.*print_parent_tid.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS1]], kind: function-exit, tsc: {{[0-9]+}} } +// +// TRACE-DAG - { type: 0, func-id: [[PPOC]], function: {{.*print_parent_or_child.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } + +// TRACE-DAG: - { type: 0, func-id: [[PPOC]], function: {{.*print_parent_or_child.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}} } +// +// The child will print its pid +// TRACE-DAG: - { type: 0, func-id: [[PCTARG:[0-9]+]], function: {{.*print_child_tid.*}}, args: [ [[THREAD2]] ], cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS2]], kind: function-enter-arg, tsc: {{[0-9]+}} } +// TRACE-DAG: - { type: 0, func-id: [[PCTARG]], function: {{.*print_child_tid.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS2]], kind: function-exit, tsc: {{[0-9]+}} } +// +// TRACE-DAG: - { type: 0, func-id: [[PPOC]], function: {{.*print_parent_or_child.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}} } diff --git a/test/xray/TestCases/Linux/func-id-utils.cc b/test/xray/TestCases/Posix/func-id-utils.cc index 412753666019..412753666019 100644 --- a/test/xray/TestCases/Linux/func-id-utils.cc +++ b/test/xray/TestCases/Posix/func-id-utils.cc diff --git a/test/xray/TestCases/Linux/logging-modes.cc b/test/xray/TestCases/Posix/logging-modes.cc index 22f6942b7595..f839ba5e5f50 100644 --- a/test/xray/TestCases/Linux/logging-modes.cc +++ b/test/xray/TestCases/Posix/logging-modes.cc @@ -1,6 +1,7 @@ // Check that we can install an implementation associated with a mode. // -// RUN: %clangxx_xray -std=c++11 %s -o %t +// RUN: rm -f xray-log.logging-modes* +// RUN: %clangxx_xray -std=c++11 %s -o %t -fxray-modes=none // RUN: %run %t | FileCheck %s // // UNSUPPORTED: target-is-mips64,target-is-mips64el @@ -9,6 +10,7 @@ #include "xray/xray_log_interface.h" #include <cassert> #include <cstdio> +#include <string> [[clang::xray_never_instrument]] void printing_handler(int32_t fid, XRayEntryType) { @@ -20,8 +22,29 @@ printing = false; } +[[clang::xray_never_instrument]] XRayBuffer next_buffer(XRayBuffer buffer) { + static const char data[10] = {}; + static const XRayBuffer first_and_last{data, 10}; + if (buffer.Data == nullptr) + return first_and_last; + if (buffer.Data == first_and_last.Data) + return XRayBuffer{nullptr, 0}; + assert(false && "Invalid buffer provided."); +} + +static constexpr char Options[] = "additional_flags"; + [[clang::xray_never_instrument]] XRayLogInitStatus -printing_init(size_t, size_t, void *, size_t) { +printing_init(size_t BufferSize, size_t MaxBuffers, void *Config, + size_t ArgsSize) { + // We require that the printing init is called through the + // __xray_log_init_mode(...) implementation, and that the promised contract is + // enforced. + assert(BufferSize == 0); + assert(MaxBuffers == 0); + assert(Config != nullptr); + assert(ArgsSize == 0 || ArgsSize == sizeof(Options)); + __xray_log_set_buffer_iterator(next_buffer); return XRayLogInitStatus::XRAY_LOG_INITIALIZED; } @@ -30,29 +53,42 @@ printing_init(size_t, size_t, void *, size_t) { } [[clang::xray_never_instrument]] XRayLogFlushStatus printing_flush_log() { + __xray_log_remove_buffer_iterator(); return XRayLogFlushStatus::XRAY_LOG_FLUSHED; } [[clang::xray_always_instrument]] void callme() { std::printf("called me!\n"); } -static bool unused = [] { +static auto buffer_counter = 0; + +void process_buffer(const char *, XRayBuffer) { ++buffer_counter; } + +int main(int argc, char **argv) { assert(__xray_log_register_mode("custom", {printing_init, printing_finalize, printing_handler, printing_flush_log}) == XRayLogRegisterStatus::XRAY_REGISTRATION_OK); - return true; -}(); - -int main(int argc, char **argv) { assert(__xray_log_select_mode("custom") == XRayLogRegisterStatus::XRAY_REGISTRATION_OK); + assert(__xray_log_get_current_mode() != nullptr); + std::string current_mode = __xray_log_get_current_mode(); + assert(current_mode == "custom"); assert(__xray_patch() == XRayPatchingStatus::SUCCESS); - assert(__xray_log_init(0, 0, nullptr, 0) == + assert(__xray_log_init_mode("custom", "flags_config_here=true") == XRayLogInitStatus::XRAY_LOG_INITIALIZED); + + // Also test that we can use the "binary" version of the + // __xray_log_niit_mode(...) API. + assert(__xray_log_init_mode_bin("custom", Options, sizeof(Options)) == + XRayLogInitStatus::XRAY_LOG_INITIALIZED); + // CHECK: printing {{.*}} callme(); // CHECK: called me! // CHECK: printing {{.*}} assert(__xray_log_finalize() == XRayLogInitStatus::XRAY_LOG_FINALIZED); + assert(__xray_log_process_buffers(process_buffer) == + XRayLogFlushStatus::XRAY_LOG_FLUSHED); + assert(buffer_counter == 1); assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED); assert(__xray_log_select_mode("not-found") == XRayLogRegisterStatus::XRAY_MODE_NOT_FOUND); diff --git a/test/xray/TestCases/Linux/optional-inmemory-log.cc b/test/xray/TestCases/Posix/optional-inmemory-log.cc index feaaa4124750..feaaa4124750 100644 --- a/test/xray/TestCases/Linux/optional-inmemory-log.cc +++ b/test/xray/TestCases/Posix/optional-inmemory-log.cc diff --git a/test/xray/TestCases/Linux/patching-unpatching.cc b/test/xray/TestCases/Posix/patching-unpatching.cc index a7ea58f6dc69..a7ea58f6dc69 100644 --- a/test/xray/TestCases/Linux/patching-unpatching.cc +++ b/test/xray/TestCases/Posix/patching-unpatching.cc diff --git a/test/xray/TestCases/Linux/pic_test.cc b/test/xray/TestCases/Posix/pic_test.cc index 4de1ad3d6da9..93e1a6a47d3c 100644 --- a/test/xray/TestCases/Linux/pic_test.cc +++ b/test/xray/TestCases/Posix/pic_test.cc @@ -2,12 +2,12 @@ // RUN: %clangxx_xray -fxray-instrument -std=c++11 -ffunction-sections \ // RUN: -fdata-sections -fpic -fpie -Wl,--gc-sections %s -o %t -// RUN: rm pic-test-logging-* || true +// RUN: rm -f pic-test-logging-* // RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_naive_log=true \ // RUN: xray_logfile_base=pic-test-logging-" %run %t 2>&1 | FileCheck %s // After all that, clean up the output xray log. // -// RUN: rm pic-test-logging-* || true +// RUN: rm -f pic-test-logging-* // UNSUPPORTED: target-is-mips64,target-is-mips64el diff --git a/test/xray/TestCases/Posix/profiling-multi-threaded.cc b/test/xray/TestCases/Posix/profiling-multi-threaded.cc new file mode 100644 index 000000000000..7ccad1bac1fd --- /dev/null +++ b/test/xray/TestCases/Posix/profiling-multi-threaded.cc @@ -0,0 +1,57 @@ +// Check that we can get a profile from a single-threaded application, on +// demand through the XRay logging implementation API. +// +// FIXME: Make -fxray-modes=xray-profiling part of the default? +// RUN: %clangxx_xray -std=c++11 %s -o %t -fxray-modes=xray-profiling +// RUN: rm -f xray-log.profiling-multi-* +// RUN: XRAY_OPTIONS=verbosity=1 \ +// RUN: XRAY_PROFILING_OPTIONS=no_flush=1 %run %t +// RUN: XRAY_OPTIONS=verbosity=1 %run %t +// RUN: PROFILES=`ls xray-log.profiling-multi-* | wc -l` +// RUN: [ $PROFILES -eq 1 ] +// RUN: rm -f xray-log.profiling-multi-* +// +// REQUIRES: x86_64-target-arch +// REQUIRES: built-in-llvm-tree + +#include "xray/xray_interface.h" +#include "xray/xray_log_interface.h" +#include <cassert> +#include <cstdio> +#include <string> +#include <thread> + +[[clang::xray_always_instrument]] void f2() { return; } +[[clang::xray_always_instrument]] void f1() { f2(); } +[[clang::xray_always_instrument]] void f0() { f1(); } + +using namespace std; + +volatile int buffer_counter = 0; + +[[clang::xray_never_instrument]] void process_buffer(const char *, XRayBuffer) { + // FIXME: Actually assert the contents of the buffer. + ++buffer_counter; +} + +[[clang::xray_always_instrument]] int main(int, char **) { + assert(__xray_log_select_mode("xray-profiling") == + XRayLogRegisterStatus::XRAY_REGISTRATION_OK); + assert(__xray_log_get_current_mode() != nullptr); + std::string current_mode = __xray_log_get_current_mode(); + assert(current_mode == "xray-profiling"); + assert(__xray_patch() == XRayPatchingStatus::SUCCESS); + assert(__xray_log_init(0, 0, nullptr, 0) == + XRayLogInitStatus::XRAY_LOG_INITIALIZED); + std::thread t0([] { f0(); }); + std::thread t1([] { f0(); }); + f0(); + t0.join(); + t1.join(); + assert(__xray_log_finalize() == XRayLogInitStatus::XRAY_LOG_FINALIZED); + assert(__xray_log_process_buffers(process_buffer) == + XRayLogFlushStatus::XRAY_LOG_FLUSHED); + // We're running three threds, so we expect three buffers. + assert(buffer_counter == 3); + assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED); +} diff --git a/test/xray/TestCases/Posix/profiling-single-threaded.cc b/test/xray/TestCases/Posix/profiling-single-threaded.cc new file mode 100644 index 000000000000..fd508b1acd14 --- /dev/null +++ b/test/xray/TestCases/Posix/profiling-single-threaded.cc @@ -0,0 +1,65 @@ +// Check that we can get a profile from a single-threaded application, on +// demand through the XRay logging implementation API. +// +// FIXME: Make -fxray-modes=xray-profiling part of the default? +// RUN: %clangxx_xray -std=c++11 %s -o %t -fxray-modes=xray-profiling +// RUN: rm -f xray-log.profiling-single-* +// RUN: XRAY_OPTIONS=verbosity=1 \ +// RUN: XRAY_PROFILING_OPTIONS=no_flush=true %run %t +// RUN: XRAY_OPTIONS=verbosity=1 %run %t +// RUN: PROFILES=`ls xray-log.profiling-single-* | wc -l` +// RUN: [ $PROFILES -eq 2 ] +// RUN: rm -f xray-log.profiling-single-* +// +// REQUIRES: x86_64-target-arch +// REQUIRES: built-in-llvm-tree + +#include "xray/xray_interface.h" +#include "xray/xray_log_interface.h" +#include <cassert> +#include <cstdio> +#include <string> + +[[clang::xray_always_instrument]] void f2() { return; } +[[clang::xray_always_instrument]] void f1() { f2(); } +[[clang::xray_always_instrument]] void f0() { f1(); } + +using namespace std; + +volatile int buffer_counter = 0; + +[[clang::xray_never_instrument]] void process_buffer(const char *, XRayBuffer) { + // FIXME: Actually assert the contents of the buffer. + ++buffer_counter; +} + +[[clang::xray_always_instrument]] int main(int, char **) { + assert(__xray_log_select_mode("xray-profiling") == + XRayLogRegisterStatus::XRAY_REGISTRATION_OK); + assert(__xray_log_get_current_mode() != nullptr); + std::string current_mode = __xray_log_get_current_mode(); + assert(current_mode == "xray-profiling"); + assert(__xray_patch() == XRayPatchingStatus::SUCCESS); + assert(__xray_log_init_mode("xray-profiling", "") == + XRayLogInitStatus::XRAY_LOG_INITIALIZED); + f0(); + assert(__xray_log_finalize() == XRayLogInitStatus::XRAY_LOG_FINALIZED); + f0(); + assert(__xray_log_process_buffers(process_buffer) == + XRayLogFlushStatus::XRAY_LOG_FLUSHED); + assert(buffer_counter == 1); + assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED); + + // Let's reset the counter. + buffer_counter = 0; + + assert(__xray_log_init_mode("xray-profiling", "") == + XRayLogInitStatus::XRAY_LOG_INITIALIZED); + f0(); + assert(__xray_log_finalize() == XRayLogInitStatus::XRAY_LOG_FINALIZED); + f0(); + assert(__xray_log_process_buffers(process_buffer) == + XRayLogFlushStatus::XRAY_LOG_FLUSHED); + assert(buffer_counter == 1); + assert(__xray_log_flushLog() == XRayLogFlushStatus::XRAY_LOG_FLUSHED); +} diff --git a/test/xray/TestCases/Linux/quiet-start.cc b/test/xray/TestCases/Posix/quiet-start.cc index e26fa63aa5ba..00d5af6609dd 100644 --- a/test/xray/TestCases/Linux/quiet-start.cc +++ b/test/xray/TestCases/Posix/quiet-start.cc @@ -10,7 +10,7 @@ // // FIXME: Understand how to make this work on other platforms // REQUIRES: built-in-llvm-tree -// REQUIRES: x86_64-linux +// REQUIRES: x86_64-target-arch #include <iostream> using namespace std; diff --git a/test/xray/lit.cfg b/test/xray/lit.cfg index d5e40975da56..0dc2108ba187 100644 --- a/test/xray/lit.cfg +++ b/test/xray/lit.cfg @@ -20,6 +20,11 @@ def build_invocation(compile_flags): llvm_xray = os.path.join(config.llvm_tools_dir, 'llvm-xray') # Setup substitutions. +if config.host_os == "Linux": + libdl_flag = "-ldl" +else: + libdl_flag = "" + config.substitutions.append( ('%clang ', build_invocation([config.target_cflags]))) config.substitutions.append( @@ -33,14 +38,14 @@ config.substitutions.append( ('%llvm_xray', llvm_xray)) config.substitutions.append( ('%xraylib', - ('-lm -lpthread -ldl -lrt -L%s ' - '-Wl,-whole-archive -lclang_rt.xray-%s -Wl,-no-whole-archive') - % (config.compiler_rt_libdir, config.host_arch))) + ('-lm -lpthread %s -lrt -L%s ' + '-Wl,-whole-archive -lclang_rt.xray%s -Wl,-no-whole-archive') + % (libdl_flag, config.compiler_rt_libdir, config.target_suffix))) # Default test suffixes. config.suffixes = ['.c', '.cc', '.cpp'] -if config.host_os not in ['Linux']: +if config.host_os not in ['FreeBSD', 'Linux', 'NetBSD', 'OpenBSD']: config.unsupported = True elif '64' not in config.host_arch: if 'arm' in config.host_arch: |