diff options
Diffstat (limited to 'compiler-rt/test')
59 files changed, 1209 insertions, 23 deletions
diff --git a/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cpp b/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cpp index bf82a517df37..67331606c3ba 100644 --- a/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/global-overflow-bfd.cpp @@ -2,6 +2,9 @@ // false negatives with the BFD linker. // RUN: %clangxx_asan -fuse-ld=bfd -Wl,-gc-sections -ffunction-sections -fdata-sections -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// Android does not use bfd. +// UNSUPPORTED: android + #include <string.h> int main(int argc, char **argv) { static char XXX[10]; diff --git a/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp b/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp index 2d729497548d..60ef0e5b0de6 100644 --- a/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp @@ -23,6 +23,8 @@ // RUN: | grep -v "__sanitizer_weak_hook" \ // RUN: | grep -v "__sanitizer_override_function" \ // RUN: | grep -v "__sanitizer_override_function_by_addr" \ +// RUN: | grep -v "__ubsan_handle_dynamic_type_cache_miss" \ +// RUN: | grep -v "__ubsan_handle_dynamic_type_cache_miss_abort" \ // RUN: | grep -v "__sanitizer_register_weak_function" \ // RUN: | sed -e "s/.*(//" -e "s/).*//" > %t.imports // diff --git a/compiler-rt/test/asan/TestCases/Windows/allocator_may_return_null_limits.cpp b/compiler-rt/test/asan/TestCases/Windows/allocator_may_return_null_limits.cpp new file mode 100644 index 000000000000..90db0d45af2d --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/allocator_may_return_null_limits.cpp @@ -0,0 +1,34 @@ +// RUN: %clangxx_asan -O0 %s -o %t +// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-ABORT +// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RETURN-NULL + +// RUN: %clangxx_asan -O0 %s -o %t -DUSER_FUNCTION +// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RETURN-NULL + +#if USER_FUNCTION +// On Windows, flags configured through the user-defined function `__asan_default_options` +// are suspected to not always be honored according to GitHub bug: +// https://github.com/llvm/llvm-project/issues/117925 +// This test ensures we do not regress on `allocator_may_return_null` specifically. +extern "C" __declspec(dllexport) extern const char *__asan_default_options() { + return "allocator_may_return_null=1"; +} +#endif + +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <limits> + +int main() { + // Attempt to allocate an excessive amount of memory, which should + // terminate the program unless `allocator_may_return_null` is set. + size_t max = std::numeric_limits<size_t>::max(); + + // CHECK-ABORT: exceeds maximum supported size + // CHECK-ABORT: ABORT + free(malloc(max)); + + printf("Success"); // CHECK-RETURN-NULL: Success + return 0; +} diff --git a/compiler-rt/test/builtins/Unit/divdf3_test.c b/compiler-rt/test/builtins/Unit/divdf3_test.c index 1b8f2b398a91..f1f3f3b4f7e0 100644 --- a/compiler-rt/test/builtins/Unit/divdf3_test.c +++ b/compiler-rt/test/builtins/Unit/divdf3_test.c @@ -113,5 +113,9 @@ int main() if (test__divdf3(0x1.0p-1022, 0x1.0028p+52, UINT64_C(0x1))) return 1; + // test 1 / (1 - eps(0.5)) = 1 + eps(1) + if (test__divdf3(1.0, 0x1.fffffffffffffp-1, UINT64_C(0x3ff0000000000001))) + return 1; + return 0; } diff --git a/compiler-rt/test/builtins/Unit/divsf3_test.c b/compiler-rt/test/builtins/Unit/divsf3_test.c index 7a783cdfb863..f8cb6169ac28 100644 --- a/compiler-rt/test/builtins/Unit/divsf3_test.c +++ b/compiler-rt/test/builtins/Unit/divsf3_test.c @@ -107,5 +107,9 @@ int main() if (test__divsf3(0x1.fffffep-126F, 2.F, UINT32_C(0x00800000))) return 1; + // test 1 / (1 - eps(0.5)) = 1 + eps(1) + if (test__divsf3(1.0F, 0x1.fffffep-1F, UINT32_C(0x3f800001))) + return 1; + return 0; } diff --git a/compiler-rt/test/builtins/Unit/divtf3_test.c b/compiler-rt/test/builtins/Unit/divtf3_test.c index d46fcc047769..3c70e43741af 100644 --- a/compiler-rt/test/builtins/Unit/divtf3_test.c +++ b/compiler-rt/test/builtins/Unit/divtf3_test.c @@ -156,6 +156,11 @@ int main() { UINT64_C(0x0001000000000000), UINT64_C(0))) return 1; + // test 1 / (1 - eps(0.5)) = 1 + eps(1). + if (test__divtf3(1.0L, TF_C(0x1.ffffffffffffffffffffffffffffp-1), + UINT64_C(0x3FFF000000000000), UINT64_C(1))) + return 1; + #else printf("skipped\n"); diff --git a/compiler-rt/test/builtins/Unit/truncxfhf2_test.c b/compiler-rt/test/builtins/Unit/truncxfhf2_test.c new file mode 100644 index 000000000000..b5e2a91f0b93 --- /dev/null +++ b/compiler-rt/test/builtins/Unit/truncxfhf2_test.c @@ -0,0 +1,74 @@ +// RUN: %clang_builtins %s %librt -o %t && %run %t +// REQUIRES: librt_has_truncxfhf2 + +#include <stdio.h> + +#include "fp_test.h" + +#if HAS_80_BIT_LONG_DOUBLE + +TYPE_FP16 __truncxfhf2(xf_float f); + +int test_truncxfhf2(uint16_t inputHi, uint64_t inputLo, uint16_t e) { + xf_float a = F80FromRep80(inputHi, inputLo); + TYPE_FP16 x = __truncxfhf2(a); + int ret = compareResultH(x, e); + if (ret) { + printf("error in test__truncxfhf2(%Lf) = %#.4x, " + "expected %#.4x\n", + a, toRep16(x), e); + } + return ret; +} + +int main() { + // Small positive value + if (test_truncxfhf2(UINT16_C(0x3ffb), UINT64_C(0xccc0000000000000), + UINT16_C(0x2e66))) + return 1; + + // Small negative value + if (test_truncxfhf2(UINT16_C(0xbffb), UINT64_C(0xccc0000000000000), + UINT16_C(0xae66))) + return 1; + + // Zero + if (test_truncxfhf2(UINT16_C(0x0), UINT64_C(0x0), UINT16_C(0))) + return 1; + + // Smallest positive non-zero value + if (test_truncxfhf2(UINT16_C(0x3fef), UINT64_C(0x8000000000000000), + UINT16_C(0x0100))) + return 1; + + // Smallest negative non-zero value + if (test_truncxfhf2(UINT16_C(0xbfef), UINT64_C(0x8000000000000000), + UINT16_C(0x8100))) + return 1; + + // Positive infinity + if (test_truncxfhf2(UINT16_C(0x7fff), UINT64_C(0x8000000000000000), + UINT16_C(0x7c00))) + return 1; + + // Negative infinity + if (test_truncxfhf2(UINT16_C(0xffff), UINT64_C(0x8000000000000000), + UINT16_C(0xfc00))) + return 1; + + // NaN + if (test_truncxfhf2(UINT16_C(0x7fff), UINT64_C(0xc000000000000000), + UINT16_C(0x7e00))) + return 1; + + return 0; +} + +#else + +int main() { + printf("skipped\n"); + return 0; +} + +#endif diff --git a/compiler-rt/test/fuzzer/noasan-strcmp.test b/compiler-rt/test/fuzzer/noasan-strcmp.test index 0d82d6b2846f..f73af35f5d89 100644 --- a/compiler-rt/test/fuzzer/noasan-strcmp.test +++ b/compiler-rt/test/fuzzer/noasan-strcmp.test @@ -1,4 +1,4 @@ -UNSUPPORTED: darwin, target={{.*(freebsd|windows).*}} +UNSUPPORTED: darwin, target={{.*(freebsd|windows).*}}, target=aarch64{{.*}} RUN: %cpp_compiler -fno-sanitize=address %S/StrcmpTest.cpp -o %t-NoAsanStrcmpTest RUN: not %run %t-NoAsanStrcmpTest -seed=1 -runs=2000000 2>&1 | FileCheck %s diff --git a/compiler-rt/test/memprof/TestCases/default_options.cpp b/compiler-rt/test/memprof/TestCases/default_options.cpp index 1b6b61fc048b..4042a7df588b 100644 --- a/compiler-rt/test/memprof/TestCases/default_options.cpp +++ b/compiler-rt/test/memprof/TestCases/default_options.cpp @@ -1,5 +1,8 @@ // RUN: %clangxx_memprof -O2 %s -o %t && %run %t 2>&1 | FileCheck %s +// Check that overriding __memprof_default_options() takes precedence over the LLVM flag +// RUN: %clangxx_memprof -O2 %s -o %t-flag -mllvm -memprof-runtime-default-options="verbosity=0 help=0" && %run %t-flag 2>&1 | FileCheck %s + const char *kMemProfDefaultOptions = "verbosity=1 help=1"; extern "C" const char *__memprof_default_options() { diff --git a/compiler-rt/test/memprof/TestCases/dump_at_exit.cpp b/compiler-rt/test/memprof/TestCases/dump_at_exit.cpp new file mode 100644 index 000000000000..426849d1cea0 --- /dev/null +++ b/compiler-rt/test/memprof/TestCases/dump_at_exit.cpp @@ -0,0 +1,16 @@ +// RUN: %clangxx_memprof %s -o %t + +// RUN: %env_memprof_opts=print_text=true:log_path=stdout:dump_at_exit=false %run %t | count 0 +// RUN: %env_memprof_opts=print_text=true:log_path=stdout:dump_at_exit=true %run %t | FileCheck %s + +#include <stdlib.h> +#include <string.h> + +int main() { + char *x = (char *)malloc(10); + memset(x, 0, 10); + free(x); + return 0; +} + +// CHECK: Recorded MIBs diff --git a/compiler-rt/test/memprof/TestCases/set_options.cpp b/compiler-rt/test/memprof/TestCases/set_options.cpp new file mode 100644 index 000000000000..dddcfcf98c5c --- /dev/null +++ b/compiler-rt/test/memprof/TestCases/set_options.cpp @@ -0,0 +1,16 @@ +// RUN: %clangxx_memprof %s -o %t-default +// RUN: %run %t-default | FileCheck %s --check-prefix=DEFAULT + +// RUN: %clangxx_memprof %s -mllvm -memprof-runtime-default-options="print_text=true,log_path=stdout,atexit=false" -o %t +// RUN: %run %t | FileCheck %s + +#include <sanitizer/memprof_interface.h> +#include <stdio.h> + +int main() { + printf("Options: \"%s\"\n", __memprof_default_options()); + return 0; +} + +// DEFAULT: Options: "" +// CHECK: Options: "print_text=true,log_path=stdout,atexit=false" diff --git a/compiler-rt/test/orc/TestCases/Generic/Inputs/foo-ret-42.ll b/compiler-rt/test/orc/TestCases/Generic/Inputs/foo-ret-42.ll new file mode 100644 index 000000000000..2d6b33933755 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Generic/Inputs/foo-ret-42.ll @@ -0,0 +1,4 @@ +define i32 @foo() { +entry: + ret i32 42 +} diff --git a/compiler-rt/test/orc/TestCases/Generic/Inputs/var-x-42.ll b/compiler-rt/test/orc/TestCases/Generic/Inputs/var-x-42.ll new file mode 100644 index 000000000000..ee479a1ffa4f --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Generic/Inputs/var-x-42.ll @@ -0,0 +1 @@ +@x = global i32 42 diff --git a/compiler-rt/test/orc/TestCases/Generic/lazy-link.ll b/compiler-rt/test/orc/TestCases/Generic/lazy-link.ll new file mode 100644 index 000000000000..5a8dbfc532b0 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Generic/lazy-link.ll @@ -0,0 +1,30 @@ +; Check that files passed with the -lazy option aren't linked unless they're +; needed. The foo-ret-42.ll file, which contains only code, should not be +; needed in this -noexec case, whereas x.o, which contains a global variable +; referenced by main, should be linked (despite being passed with -lazy). +; +; RUN: rm -rf %t && mkdir -p %t +; RUN: %clang -c -o %t/foo.o %S/Inputs/foo-ret-42.ll +; RUN: %clang -c -o %t/x.o %S/Inputs/var-x-42.ll +; RUN: %clang -c -o %t/main.o %s +; RUN: %llvm_jitlink -noexec -show-linked-files %t/main.o -lazy %t/foo.o \ +; RUN: -lazy %t/x.o | FileCheck %s +; +; UNSUPPORTED: system-windows +; REQUIRES: target={{(arm|aarch|x86_)64.*}} +; +; CHECK: Linking {{.*}}main.o +; CHECK-DAG: Linking <indirect stubs graph #1> +; CHECK-DAG: Linking {{.*}}x.o +; CHECK-NOT: Linking {{.*}}foo.o + +declare i32 @foo() +@x = external global i32 + +define i32 @main(i32 %argc, ptr %argv) { +entry: + %foo_result = call i32 @foo() + %x_val = load i32, ptr @x + %result = add nsw i32 %foo_result, %x_val + ret i32 %result +} diff --git a/compiler-rt/test/orc/TestCases/Generic/orc-rt-executor-usage.test b/compiler-rt/test/orc/TestCases/Generic/orc-rt-executor-usage.test deleted file mode 100644 index 951688d7961d..000000000000 --- a/compiler-rt/test/orc/TestCases/Generic/orc-rt-executor-usage.test +++ /dev/null @@ -1,6 +0,0 @@ -// Test that the orc-remote-executor tool errors out as expected when called -// with no arguments. -// -// RUN: not %orc_rt_executor 2>&1 | FileCheck %s - -// CHECK: usage: orc-rt-executor [help] [<mode>] <program arguments>... diff --git a/compiler-rt/test/orc/lit.cfg.py b/compiler-rt/test/orc/lit.cfg.py index 6dfa94b11cc9..7a6eb4e7de32 100644 --- a/compiler-rt/test/orc/lit.cfg.py +++ b/compiler-rt/test/orc/lit.cfg.py @@ -16,6 +16,11 @@ if config.host_arch == "x86_64h" and config.target_arch == "x86_64": host_arch_compatible = True if host_arch_compatible: config.available_features.add("host-arch-compatible") + +# If the target OS hasn't been set then assume host. +if not config.target_os: + config.target_os = config.host_os + config.test_target_is_host_executable = ( config.target_os == config.host_os and host_arch_compatible ) diff --git a/compiler-rt/test/profile/ContinuousSyncMode/basic.c b/compiler-rt/test/profile/ContinuousSyncMode/basic.c index e8bd087a0f59..531877b78a1a 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/basic.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/basic.c @@ -1,4 +1,4 @@ -// REQUIRES: target={{.*(darwin|aix).*}} +// REQUIRES: continuous-mode // RUN: %clang_profgen_cont -fcoverage-mapping -o %t.exe %s // RUN: echo "garbage" > %t.profraw diff --git a/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c b/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c index 40a0cc5ffd68..e341dd429eb8 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c @@ -1,4 +1,4 @@ -// REQUIRES: target={{.*(darwin|aix).*}} +// REQUIRES: continuous-mode // RUN: %clang_pgogen_cont -o %t.exe %s // RUN: env LLVM_PROFILE_FILE="%c%t.profraw" %run %t.exe %t.profraw diff --git a/compiler-rt/test/profile/ContinuousSyncMode/image-with-mcdc.c b/compiler-rt/test/profile/ContinuousSyncMode/image-with-mcdc.c index d171badbf4d3..fa24e26c4c53 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/image-with-mcdc.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/image-with-mcdc.c @@ -1,4 +1,4 @@ -// REQUIRES: target={{.*(darwin|aix).*}} +// REQUIRES: continuous-mode // RUN: %clang_profgen_cont -fcoverage-mapping -fcoverage-mcdc -O3 -o %t.exe %s // RUN: env LLVM_PROFILE_FILE="%c%t.profraw" %run %t.exe 3 3 diff --git a/compiler-rt/test/profile/ContinuousSyncMode/multi-threaded.cpp b/compiler-rt/test/profile/ContinuousSyncMode/multi-threaded.cpp index ff05a69a5e7d..aa0a46e0fc39 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/multi-threaded.cpp +++ b/compiler-rt/test/profile/ContinuousSyncMode/multi-threaded.cpp @@ -1,4 +1,4 @@ -// REQUIRES: target={{.*(darwin|aix).*}} +// REQUIRES: continuous-mode // RUN: rm -f %t.profraw // RUN: %clangxx_pgogen_cont -lpthread %s -o %t.exe -mllvm -disable-vp -fprofile-update=atomic diff --git a/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c b/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c index 54346487a5c7..c1931410f8c7 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c @@ -1,4 +1,4 @@ -// REQUIRES: target={{.*(darwin|aix).*}} +// REQUIRES: continuous-mode // Test the online merging mode (%m) along with continuous mode (%c). // diff --git a/compiler-rt/test/profile/ContinuousSyncMode/pid-substitution.c b/compiler-rt/test/profile/ContinuousSyncMode/pid-substitution.c index 309b685a95c5..8a00b28825ca 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/pid-substitution.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/pid-substitution.c @@ -1,4 +1,4 @@ -// REQUIRES: target={{.*(darwin|aix).*}} +// REQUIRES: continuous-mode // RUN: rm -rf %t.dir && mkdir -p %t.dir // RUN: %clang_pgogen_cont -o %t.exe %s diff --git a/compiler-rt/test/profile/ContinuousSyncMode/set-filename.c b/compiler-rt/test/profile/ContinuousSyncMode/set-filename.c index 106e12e4e3b6..abc72646d16b 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/set-filename.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/set-filename.c @@ -1,4 +1,4 @@ -// REQUIRES: target={{.*(darwin|aix).*}} +// REQUIRES: continuous-mode // RUN: %clang_pgogen_cont -o %t.exe %s // RUN: env LLVM_PROFILE_FILE="%c%t.profraw" %run %t.exe %t.profraw %t.bad diff --git a/compiler-rt/test/profile/Inputs/instrprof-gcov-exceptions.cpp.gcov b/compiler-rt/test/profile/Inputs/instrprof-gcov-exceptions.cpp.gcov index aa202763fd56..233fd142444a 100644 --- a/compiler-rt/test/profile/Inputs/instrprof-gcov-exceptions.cpp.gcov +++ b/compiler-rt/test/profile/Inputs/instrprof-gcov-exceptions.cpp.gcov @@ -2,7 +2,6 @@ // 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: 1: 3:void asd(std::string i) { diff --git a/compiler-rt/test/profile/Inputs/instrprof-gcov-multiple-bbs-single-line.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-gcov-multiple-bbs-single-line.c.gcov index 9297073d21ef..a25632d475b3 100644 --- a/compiler-rt/test/profile/Inputs/instrprof-gcov-multiple-bbs-single-line.c.gcov +++ b/compiler-rt/test/profile/Inputs/instrprof-gcov-multiple-bbs-single-line.c.gcov @@ -2,7 +2,6 @@ // 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 77% // CHECK-NEXT: 1: 1:int main(void) // CHECK-NEXT: -: 2:{ diff --git a/compiler-rt/test/profile/Inputs/instrprof-gcov-one-line-function.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-gcov-one-line-function.c.gcov index 5a570a04742d..4dc68177e0b7 100644 --- a/compiler-rt/test/profile/Inputs/instrprof-gcov-one-line-function.c.gcov +++ b/compiler-rt/test/profile/Inputs/instrprof-gcov-one-line-function.c.gcov @@ -2,7 +2,6 @@ // CHECK-NEXT: -: 0:Graph:instrprof-gcov-one-line-function.gcno // CHECK-NEXT: -: 0:Data:instrprof-gcov-one-line-function.gcda // CHECK-NEXT: -: 0:Runs:1 -// CHECK-NEXT: -: 0:Programs:1 // CHECK-NEXT: 1: 1:void foo() { } // CHECK-NEXT: -: 2: // CHECK-NEXT: 1: 3:void bar() { } diff --git a/compiler-rt/test/profile/Inputs/instrprof-gcov-switch1.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-gcov-switch1.c.gcov index 741dff59954b..2b4d67f9abbe 100644 --- a/compiler-rt/test/profile/Inputs/instrprof-gcov-switch1.c.gcov +++ b/compiler-rt/test/profile/Inputs/instrprof-gcov-switch1.c.gcov @@ -2,7 +2,6 @@ // CHECK-NEXT: -: 0:Graph:instrprof-gcov-switch1.gcno // CHECK-NEXT: -: 0:Data:instrprof-gcov-switch1.gcda // CHECK-NEXT: -: 0:Runs:1 -// CHECK-NEXT: -: 0:Programs:1 // CHECK-NEXT: 1: 1:int main(void) // CHECK-NEXT: -: 2:{ // CHECK-NEXT: 1: 3: int i = 22; diff --git a/compiler-rt/test/profile/Inputs/instrprof-gcov-switch2.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-gcov-switch2.c.gcov index c931365ddf48..f9501e0c870b 100644 --- a/compiler-rt/test/profile/Inputs/instrprof-gcov-switch2.c.gcov +++ b/compiler-rt/test/profile/Inputs/instrprof-gcov-switch2.c.gcov @@ -2,7 +2,6 @@ // CHECK-NEXT: -: 0:Graph:instrprof-gcov-switch2.gcno // CHECK-NEXT: -: 0:Data:instrprof-gcov-switch2.gcda // CHECK-NEXT: -: 0:Runs:1 -// CHECK-NEXT: -: 0:Programs:1 // CHECK-NEXT: 1: 1:int main(void) // CHECK-NEXT: -: 2:{ // CHECK-NEXT: 1: 3: int i = 22; diff --git a/compiler-rt/test/profile/Inputs/instrprof-shared-lib_in-loop.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-shared-lib_in-loop.c.gcov index 69350471312e..d75a222977a0 100644 --- a/compiler-rt/test/profile/Inputs/instrprof-shared-lib_in-loop.c.gcov +++ b/compiler-rt/test/profile/Inputs/instrprof-shared-lib_in-loop.c.gcov @@ -2,7 +2,6 @@ // 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: diff --git a/compiler-rt/test/profile/Inputs/instrprof-shared-main.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-shared-main.c.gcov index a31a60238809..24facb5e1a38 100644 --- a/compiler-rt/test/profile/Inputs/instrprof-shared-main.c.gcov +++ b/compiler-rt/test/profile/Inputs/instrprof-shared-main.c.gcov @@ -2,7 +2,6 @@ // 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: diff --git a/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c b/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c index ca13a0896a7b..96cf4296524d 100644 --- a/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c +++ b/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c @@ -8,7 +8,6 @@ // RUN: llvm-cov gcov -t gcov-__gcov_flush-terminate.gcda | FileCheck %s // CHECK: -: 0:Runs:1 -// CHECK-NEXT: -: 0:Programs:1 void __gcov_dump(void); void __gcov_reset(void); diff --git a/compiler-rt/test/profile/lit.cfg.py b/compiler-rt/test/profile/lit.cfg.py index 72a389eaf0df..fc2baf7c40b8 100644 --- a/compiler-rt/test/profile/lit.cfg.py +++ b/compiler-rt/test/profile/lit.cfg.py @@ -31,7 +31,7 @@ if ( target_is_msvc = bool(re.match(r".*-windows-msvc$", config.target_triple)) # Whether continous profile collection (%c) requires runtime counter relocation on this platform -runtime_reloc = bool(config.host_os in ["AIX"]) +runtime_reloc = bool(config.host_os in ["AIX", "Linux"]) if config.host_os in ["Linux"]: extra_link_flags = ["-ldl"] @@ -210,3 +210,6 @@ if config.android: if config.have_curl: config.available_features.add("curl") + +if config.host_os in ("AIX", "Darwin", "Linux"): + config.available_features.add("continuous-mode") diff --git a/compiler-rt/test/rtsan/Darwin/dlopen.cpp b/compiler-rt/test/rtsan/Darwin/dlopen.cpp new file mode 100644 index 000000000000..1aabe5cb6e58 --- /dev/null +++ b/compiler-rt/test/rtsan/Darwin/dlopen.cpp @@ -0,0 +1,44 @@ +// Checks that on OS X 10.11+ dlopen'ing a RTsanified library from a +// non-instrumented program exits with a user-friendly message. + +// REQUIRES: osx-autointerception + +// XFAIL: ios + +// RUN: %clangxx -fsanitize=realtime %s -o %t.so -shared -DSHARED_LIB +// RUN: %clangxx %s -o %t + +// RUN: RTSAN_DYLIB_PATH=`%clangxx -fsanitize=realtime %s -### 2>&1 \ +// RUN: | grep "libclang_rt.rtsan_osx_dynamic.dylib" \ +// RUN: | sed -e 's/.*"\(.*libclang_rt.rtsan_osx_dynamic.dylib\)".*/\1/'` + +// Launching a non-instrumented binary that dlopen's an instrumented library should fail. +// RUN: not %run %t %t.so 2>&1 | FileCheck %s --check-prefix=CHECK-FAIL +// Launching a non-instrumented binary with an explicit DYLD_INSERT_LIBRARIES should work. +// RUN: DYLD_INSERT_LIBRARIES=$RTSAN_DYLIB_PATH %run %t %t.so 2>&1 | FileCheck %s + +// Launching an instrumented binary with the DYLD_INSERT_LIBRARIES env variable has no error +// RUN: %clangxx -fsanitize=realtime %s -o %t +// RUN: DYLD_INSERT_LIBRARIES=$RTSAN_DYLIB_PATH %run %t %t.so 2>&1 | FileCheck %s --check-prefix=CHECK-INSTRUMENTED + +#include <dlfcn.h> +#include <stdio.h> + +#if defined(SHARED_LIB) +extern "C" void foo() { fprintf(stderr, "Hello world.\n"); } +#else // defined(SHARED_LIB) +int main(int argc, char *argv[]) { + void *handle = dlopen(argv[1], RTLD_NOW); + void (*foo)() = (void (*)())dlsym(handle, "foo"); + foo(); +} +#endif // defined(SHARED_LIB) + +// CHECK: Hello world. +// CHECK-NOT: ERROR: Interceptors are not working. + +// CHECK-FAIL-NOT: Hello world. +// CHECK-FAIL: ERROR: Interceptors are not working. + +// CHECK-INSTRUMENTED-NOT: ERROR: Interceptors are not working +// CHECK-INSTRUMENTED: Hello world. diff --git a/compiler-rt/test/tysan/CMakeLists.txt b/compiler-rt/test/tysan/CMakeLists.txt new file mode 100644 index 000000000000..76f57501e854 --- /dev/null +++ b/compiler-rt/test/tysan/CMakeLists.txt @@ -0,0 +1,32 @@ +set(TYSAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +set(TYSAN_TESTSUITES) + +set(TYSAN_TEST_ARCH ${TYSAN_SUPPORTED_ARCH}) +if(APPLE) + darwin_filter_host_archs(TYSAN_SUPPORTED_ARCH TYSAN_TEST_ARCH) +endif() + +foreach(arch ${TYSAN_TEST_ARCH}) + set(TYSAN_TEST_TARGET_ARCH ${arch}) + string(TOLOWER "-${arch}" TYSAN_TEST_CONFIG_SUFFIX) + get_test_cc_for_arch(${arch} TYSAN_TEST_TARGET_CC TYSAN_TEST_TARGET_CFLAGS) + string(TOUPPER ${arch} ARCH_UPPER_CASE) + set(CONFIG_NAME ${ARCH_UPPER_CASE}Config) + + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg.py) + list(APPEND TYSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) +endforeach() + +set(TYSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) +if(NOT COMPILER_RT_STANDALONE_BUILD) + list(APPEND TYSAN_TEST_DEPS tysan) +endif() + +add_lit_testsuite(check-tysan "Running the TypeSanitizer tests" + ${TYSAN_TESTSUITES} + DEPENDS ${TYSAN_TEST_DEPS} + ) +set_target_properties(check-tysan PROPERTIES FOLDER "Compiler-RT Misc") diff --git a/compiler-rt/test/tysan/anon-ns.cpp b/compiler-rt/test/tysan/anon-ns.cpp new file mode 100644 index 000000000000..681304411df3 --- /dev/null +++ b/compiler-rt/test/tysan/anon-ns.cpp @@ -0,0 +1,41 @@ +// RUN: %clangxx_tysan -O0 %s -c -o %t.o +// RUN: %clangxx_tysan -O0 %s -DPMAIN -c -o %tm.o +// RUN: %clangxx_tysan -O0 %t.o %tm.o -o %t +// RUN: %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <iostream> + +// This test demonstrates that the types from anonymous namespaces are +// different in different translation units (while the char* type is the same). + +namespace { +struct X { + X(int i, int j) : a(i), b(j) {} + int a; + int b; +}; +} // namespace + +#ifdef PMAIN +void foo(void *context, int i); +char fbyte(void *context); + +int main() { + X x(5, 6); + foo((void *)&x, 8); + std::cout << "fbyte: " << fbyte((void *)&x) << "\n"; +} +#else +void foo(void *context, int i) { + X *x = (X *)context; + x->b = i; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type int (in (anonymous namespace)::X at offset 4) accesses an existing object of type int (in (anonymous namespace)::X at offset 4) + // CHECK: {{#0 0x.* in foo\(void\*, int\) .*anon-ns.cpp:}}[[@LINE-3]] +} + +char fbyte(void *context) { return *(char *)context; } +#endif + +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation diff --git a/compiler-rt/test/tysan/anon-same-struct.c b/compiler-rt/test/tysan/anon-same-struct.c new file mode 100644 index 000000000000..b9044f2a0a73 --- /dev/null +++ b/compiler-rt/test/tysan/anon-same-struct.c @@ -0,0 +1,26 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <stdio.h> + +// The two anonymous structs are structurally identical. As a result, we don't +// report an aliasing violation here. +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation + +typedef struct { + int i1; +} s1; +typedef struct { + int i2; +} s2; + +void f(s1 *s1p, s2 *s2p) { + s1p->i1 = 2; + s2p->i2 = 3; + printf("%i\n", s1p->i1); +} + +int main() { + s1 s = {.i1 = 1}; + f(&s, (s2 *)&s); +} diff --git a/compiler-rt/test/tysan/anon-struct.c b/compiler-rt/test/tysan/anon-struct.c new file mode 100644 index 000000000000..25f663354592 --- /dev/null +++ b/compiler-rt/test/tysan/anon-struct.c @@ -0,0 +1,27 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <stdio.h> + +typedef struct { + int i1, i1b; +} s1; +typedef struct { + int i2, i2b, i2c; +} s2; + +void f(s1 *s1p, s2 *s2p) { + s1p->i1 = 2; + s2p->i2 = 3; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type int (in <anonymous type> at offset 0) accesses an existing object of type int (in <anonymous type> at offset 0) + // CHECK: {{#0 0x.* in f .*anon-struct.c:}}[[@LINE-3]] + printf("%i\n", s1p->i1); +} + +int main() { + s1 s = {.i1 = 1, .i1b = 5}; + f(&s, (s2 *)&s); +} + +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation diff --git a/compiler-rt/test/tysan/basic.c b/compiler-rt/test/tysan/basic.c new file mode 100644 index 000000000000..8e66e1a72138 --- /dev/null +++ b/compiler-rt/test/tysan/basic.c @@ -0,0 +1,65 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t 10 >%t.out.0 2>&1 +// RUN: FileCheck %s < %t.out.0 +// RUN: %clang_tysan -O2 %s -o %t && %run %t 10 >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void __attribute__((noinline)) add_flt(float *a) { + *a += 2.0f; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: READ of size 4 at {{.*}} with type float accesses an existing object of type int + // CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-3]] + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type float accesses an existing object of type int + // CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-6]] + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: READ of size 4 at {{.*}} with type float accesses an existing object of type long + // CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-9]] + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type float accesses an existing object of type long + // CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-12]] + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: READ of size 4 at {{.*}} with type float accesses part of an existing object of type long that starts at offset -4 + // CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-15]] + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type float accesses part of an existing object of type long that starts at offset -4 + // CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-18]] + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: READ of size 4 at {{.*}} with type float partially accesses an object of type short that starts at offset 2 + // CHECK: {{#0 0x.* in add_flt .*basic.c:}}[[@LINE-21]] +} + +int main(int argc, char *argv[]) { + int x = atoi(argv[1]); + add_flt((float *)&x); + printf("x = %d\n", x); + + long y = x; + add_flt((float *)&y); + printf("y = %ld\n", y); + + add_flt(((float *)&y) + 1); + printf("y = %ld\n", y); + + char *mem = (char *)malloc(4 * sizeof(short)); + memset(mem, 0, 4 * sizeof(short)); + *(short *)(mem + 2) = x; + add_flt((float *)mem); + short s1 = *(short *)mem; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: READ of size 2 at {{.*}} with type short accesses an existing object of type float + // CHECK: {{#0 0x.* in main .*basic.c:}}[[@LINE-3]] + short s2 = *(short *)(mem + 2); + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: READ of size 2 at {{.*}} with type short accesses part of an existing object of type float that starts at offset -2 + // CHECK: {{#0 0x.* in main .*basic.c:}}[[@LINE-3]] + printf("m[0] = %d, m[1] = %d\n", s1, s2); + free(mem); + + return 0; +} + +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation diff --git a/compiler-rt/test/tysan/char-memcpy.c b/compiler-rt/test/tysan/char-memcpy.c new file mode 100644 index 000000000000..ebbb6b53d0f3 --- /dev/null +++ b/compiler-rt/test/tysan/char-memcpy.c @@ -0,0 +1,45 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out.0 2>&1 +// RUN: FileCheck %s < %t.out.0 +// RUN: %clang_tysan -O2 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <stdio.h> + +// There's no type-based-aliasing violation here: the memcpy is implemented +// using only char* or unsigned char* (both of which may alias anything). +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation + +void my_memcpy_uchar(void *dest, void *src, int n) { + unsigned char *p = dest, *q = src, *end = p + n; + while (p < end) + *p++ = *q++; +} + +void my_memcpy_char(void *dest, void *src, int n) { + char *p = dest, *q = src, *end = p + n; + while (p < end) + *p++ = *q++; +} + +void test_uchar() { + struct S { + short x; + short *r; + } s = {10, &s.x}, s2; + my_memcpy_uchar(&s2, &s, sizeof(struct S)); + printf("%d\n", *(s2.r)); +} + +void test_char() { + struct S { + short x; + short *r; + } s = {10, &s.x}, s2; + my_memcpy_char(&s2, &s, sizeof(struct S)); + printf("%d\n", *(s2.r)); +} + +int main() { + test_uchar(); + test_char(); +} diff --git a/compiler-rt/test/tysan/constexpr-subobject.cpp b/compiler-rt/test/tysan/constexpr-subobject.cpp new file mode 100644 index 000000000000..c473ffe5e445 --- /dev/null +++ b/compiler-rt/test/tysan/constexpr-subobject.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck --allow-empty %s < %t.out + +// CHECK-NOT: TypeSanitizer + +int foo() { return 0; } + +struct Bar { + struct S2 { + int (*fnA)(); + int (*fnB)(); + }; + + static int x() { return 0; } + + static const S2 &get() { + static constexpr S2 Info = {&foo, &Bar::x}; + return Info; + } +}; + +int main() { + auto Info = Bar::get(); + return Info.fnB(); +} diff --git a/compiler-rt/test/tysan/global.c b/compiler-rt/test/tysan/global.c new file mode 100644 index 000000000000..247ee768a816 --- /dev/null +++ b/compiler-rt/test/tysan/global.c @@ -0,0 +1,31 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out +#include <stdlib.h> +#include <string.h> + +float P; +long L; + +int main() { + *(int *)&P = 5; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type int accesses an existing object of type float + // CHECK: {{#0 0x.* in main .*global.c:}}[[@LINE-3]] + + void *mem = malloc(sizeof(long)); + *(int *)mem = 6; + memcpy(mem, &L, sizeof(L)); + *(int *)mem = 8; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type int accesses an existing object of type long + // CHECK: {{#0 0x.* in main .*global.c:}}[[@LINE-3]] + int r = *(((int *)mem) + 1); + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: READ of size 4 at {{.*}} with type int accesses part of an existing object of type long that starts at offset -4 + // CHECK: {{#0 0x.* in main .*global.c:}}[[@LINE-3]] + free(mem); + + return r; +} + +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation diff --git a/compiler-rt/test/tysan/int-long.c b/compiler-rt/test/tysan/int-long.c new file mode 100644 index 000000000000..b7956c07376e --- /dev/null +++ b/compiler-rt/test/tysan/int-long.c @@ -0,0 +1,21 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <stdio.h> + +long foo(int *x, long *y) { + *x = 0; + *y = 1; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 8 at {{.*}} with type long accesses an existing object of type int + // CHECK: {{#0 0x.* in foo .*int-long.c:}}[[@LINE-3]] + + return *x; +} + +int main(void) { + long l; + printf("%ld\n", foo((int *)&l, &l)); +} + +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation diff --git a/compiler-rt/test/tysan/lit.cfg.py b/compiler-rt/test/tysan/lit.cfg.py new file mode 100644 index 000000000000..817a3f0921e8 --- /dev/null +++ b/compiler-rt/test/tysan/lit.cfg.py @@ -0,0 +1,147 @@ +# -*- Python -*- + +import os +import platform +import re +import shlex + +import lit.formats + + +def get_required_attr(config, attr_name): + attr_value = getattr(config, attr_name, None) + if attr_value is not None: + return attr_value + + lit_config.fatal( + "No attribute %r in test configuration! You may need to run " + "tests from your build directory or add this attribute " + "to lit.site.cfg.py " % attr_name + ) + + +def push_dynamic_library_lookup_path(config, new_path): + if platform.system() == "Windows": + dynamic_library_lookup_var = "PATH" + elif platform.system() == "Darwin": + dynamic_library_lookup_var = "DYLD_LIBRARY_PATH" + else: + dynamic_library_lookup_var = "LD_LIBRARY_PATH" + + new_ld_library_path = os.path.pathsep.join( + (new_path, config.environment.get(dynamic_library_lookup_var, "")) + ) + config.environment[dynamic_library_lookup_var] = new_ld_library_path + + if platform.system() == "FreeBSD": + dynamic_library_lookup_var = "LD_32_LIBRARY_PATH" + new_ld_32_library_path = os.path.pathsep.join( + (new_path, config.environment.get(dynamic_library_lookup_var, "")) + ) + config.environment[dynamic_library_lookup_var] = new_ld_32_library_path + + if platform.system() == "SunOS": + dynamic_library_lookup_var = "LD_LIBRARY_PATH_32" + new_ld_library_path_32 = os.path.pathsep.join( + (new_path, config.environment.get(dynamic_library_lookup_var, "")) + ) + config.environment[dynamic_library_lookup_var] = new_ld_library_path_32 + + dynamic_library_lookup_var = "LD_LIBRARY_PATH_64" + new_ld_library_path_64 = os.path.pathsep.join( + (new_path, config.environment.get(dynamic_library_lookup_var, "")) + ) + config.environment[dynamic_library_lookup_var] = new_ld_library_path_64 + + +# Setup config name. +config.name = "TypeSanitizer" + config.name_suffix + +# Platform-specific default TYSAN_OPTIONS for lit tests. +default_tysan_opts = list(config.default_sanitizer_opts) + +default_tysan_opts_str = ":".join(default_tysan_opts) +if default_tysan_opts_str: + config.environment["TYSAN_OPTIONS"] = default_tysan_opts_str + default_tysan_opts_str += ":" +config.substitutions.append( + ("%env_tysan_opts=", "env TYSAN_OPTIONS=" + default_tysan_opts_str) +) + +# Setup source root. +config.test_source_root = os.path.dirname(__file__) + +if config.host_os not in ["FreeBSD", "NetBSD"]: + libdl_flag = "-ldl" +else: + libdl_flag = "" + +# GCC-ASan doesn't link in all the necessary libraries automatically, so +# we have to do it ourselves. +if config.compiler_id == "GNU": + extra_link_flags = ["-pthread", "-lstdc++", libdl_flag] +else: + extra_link_flags = [] + +# Setup default compiler flags used with -fsanitize=address option. +# FIXME: Review the set of required flags and check if it can be reduced. +target_cflags = [get_required_attr(config, "target_cflags")] + extra_link_flags +target_cxxflags = config.cxx_mode_flags + target_cflags +clang_tysan_static_cflags = ( + [ + "-fsanitize=type", + "-mno-omit-leaf-frame-pointer", + "-fno-omit-frame-pointer", + "-fno-optimize-sibling-calls", + ] + + config.debug_info_flags + + target_cflags +) +if config.target_arch == "s390x": + clang_tysan_static_cflags.append("-mbackchain") +clang_tysan_static_cxxflags = config.cxx_mode_flags + clang_tysan_static_cflags + +clang_tysan_cflags = clang_tysan_static_cflags +clang_tysan_cxxflags = clang_tysan_static_cxxflags + + +def build_invocation(compile_flags): + return " " + " ".join([config.clang] + compile_flags) + " " + + +config.substitutions.append(("%clang ", build_invocation(target_cflags))) +config.substitutions.append(("%clangxx ", build_invocation(target_cxxflags))) +config.substitutions.append(("%clang_tysan ", build_invocation(clang_tysan_cflags))) +config.substitutions.append(("%clangxx_tysan ", build_invocation(clang_tysan_cxxflags))) + + +# FIXME: De-hardcode this path. +tysan_source_dir = os.path.join( + get_required_attr(config, "compiler_rt_src_root"), "lib", "tysan" +) +python_exec = shlex.quote(get_required_attr(config, "python_executable")) + +# Set LD_LIBRARY_PATH to pick dynamic runtime up properly. +push_dynamic_library_lookup_path(config, config.compiler_rt_libdir) + +# Default test suffixes. +config.suffixes = [".c", ".cpp"] + +if config.host_os == "Darwin": + config.suffixes.append(".mm") + +if config.host_os == "Windows": + config.substitutions.append(("%fPIC", "")) + config.substitutions.append(("%fPIE", "")) + config.substitutions.append(("%pie", "")) +else: + config.substitutions.append(("%fPIC", "-fPIC")) + config.substitutions.append(("%fPIE", "-fPIE")) + config.substitutions.append(("%pie", "-pie")) + +# Only run the tests on supported OSs. +if config.host_os not in [ + "Linux", + "Darwin", +]: + config.unsupported = Tr diff --git a/compiler-rt/test/tysan/lit.site.cfg.py.in b/compiler-rt/test/tysan/lit.site.cfg.py.in new file mode 100644 index 000000000000..b56dce4fed7a --- /dev/null +++ b/compiler-rt/test/tysan/lit.site.cfg.py.in @@ -0,0 +1,17 @@ +@LIT_SITE_CFG_IN_HEADER@ + +# Tool-specific config options. +config.name_suffix = "@TYSAN_TEST_CONFIG_SUFFIX@" +config.target_cflags = "@TYSAN_TEST_TARGET_CFLAGS@" +config.clang = "@TYSAN_TEST_TARGET_CC@" +config.bits = "@TYSAN_TEST_BITS@" +config.arm_thumb = "@COMPILER_RT_ARM_THUMB@" +config.apple_platform = "@TYSAN_TEST_APPLE_PLATFORM@" +config.apple_platform_min_deployment_target_flag = "@TYSAN_TEST_MIN_DEPLOYMENT_TARGET_FLAG@" +config.target_arch = "@TYSAN_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, "@TYSAN_LIT_SOURCE_DIR@/lit.cfg.py") diff --git a/compiler-rt/test/tysan/ptr-float.c b/compiler-rt/test/tysan/ptr-float.c new file mode 100644 index 000000000000..aaa989598698 --- /dev/null +++ b/compiler-rt/test/tysan/ptr-float.c @@ -0,0 +1,19 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +float *P; +void zero_array() { + int i; + for (i = 0; i < 1; ++i) + P[i] = 0.0f; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type float accesses an existing object of type p1 float + // CHECK: {{#0 0x.* in zero_array .*ptr-float.c:}}[[@LINE-3]] +} + +int main() { + P = (float *)&P; + zero_array(); +} + +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation diff --git a/compiler-rt/test/tysan/struct-offset-multiple-compilation-units.cpp b/compiler-rt/test/tysan/struct-offset-multiple-compilation-units.cpp new file mode 100644 index 000000000000..f7baa14d15af --- /dev/null +++ b/compiler-rt/test/tysan/struct-offset-multiple-compilation-units.cpp @@ -0,0 +1,51 @@ +// RUN: %clangxx_tysan -O0 %s -c -o %t.o +// RUN: %clangxx_tysan -O0 %s -DPMAIN -c -o %tm.o +// RUN: %clangxx_tysan -O0 %s -DPINIT -c -o %tinit.o +// RUN: %clangxx_tysan -O0 %t.o %tm.o %tinit.o -o %t +// RUN: %run %t 2>&1 | FileCheck %s + +#include <stdio.h> +#include <stdlib.h> + +extern "C" { +typedef struct X { + int *start; + int *end; + int i; +} X; +}; + +#ifdef PMAIN +int foo(struct X *); +void bar(struct X *); +void init(struct X *); + +int main() { + struct X x; + init(&x); + printf("%d\n", foo(&x)); + free(x.start); + return 0; +} + +#elif PINIT + +void init(struct X *x) { + x->start = (int *)calloc(100, sizeof(int)); + x->end = x->start + 99; + x->i = 0; +} + +#else + +__attribute__((noinline)) int foo(struct X *x) { + if (x->start < x->end) + return 30; + return 10; +} + +void bar(struct X *x) { x->end = NULL; } + +#endif + +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation diff --git a/compiler-rt/test/tysan/struct-offset.c b/compiler-rt/test/tysan/struct-offset.c new file mode 100644 index 000000000000..7295e0ae121e --- /dev/null +++ b/compiler-rt/test/tysan/struct-offset.c @@ -0,0 +1,26 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <stdio.h> +#include <stdlib.h> + +struct X { + int i; + int j; +}; + +int foo(struct X *p, struct X *q) { + q->j = 1; + p->i = 0; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type int (in X at offset 0) accesses an existing object of type int (in X at offset 4) + // CHECK: {{#0 0x.* in foo .*struct-offset.c:}}[[@LINE-3]] + return q->j; +} + +int main() { + unsigned char *p = malloc(3 * sizeof(int)); + printf("%i\n", foo((struct X *)(p + sizeof(int)), (struct X *)p)); +} + +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation diff --git a/compiler-rt/test/tysan/struct.c b/compiler-rt/test/tysan/struct.c new file mode 100644 index 000000000000..f7ecef596762 --- /dev/null +++ b/compiler-rt/test/tysan/struct.c @@ -0,0 +1,39 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <stdio.h> + +typedef struct S1 { + int i1; +} s1; +typedef struct S2 { + int i2; +} s2; + +void g(int *i) { + *i = 5; + printf("%i\n", *i); +} + +void h(char *c) { + *c = 5; + printf("%i\n", (int)*c); +} + +void f(s1 *s1p, s2 *s2p) { + s1p->i1 = 2; + s2p->i2 = 3; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type int (in S2 at offset 0) accesses an existing object of type int (in S1 at offset 0) + // CHECK: {{#0 0x.* in f .*struct.c:}}[[@LINE-3]] + printf("%i\n", s1p->i1); +} + +int main() { + s1 s = {.i1 = 1}; + f(&s, (s2 *)&s); + g(&s.i1); + h((char *)&s.i1); +} + +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation diff --git a/compiler-rt/test/tysan/union-wr-wr.c b/compiler-rt/test/tysan/union-wr-wr.c new file mode 100644 index 000000000000..6414bbfcf9d9 --- /dev/null +++ b/compiler-rt/test/tysan/union-wr-wr.c @@ -0,0 +1,18 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <stdio.h> + +// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation + +int main() { + union { + int i; + short s; + } u; + + u.i = 42; + u.s = 1; + + printf("%d\n", u.i); +} diff --git a/compiler-rt/test/tysan/violation-pr45282.c b/compiler-rt/test/tysan/violation-pr45282.c new file mode 100644 index 000000000000..b3d8b0a6465f --- /dev/null +++ b/compiler-rt/test/tysan/violation-pr45282.c @@ -0,0 +1,32 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +// https://github.com/llvm/llvm-project/issues/45282 + +#include <stdio.h> + +int main(void) { + + double a[29], b[20]; + int i, j; + + for (i = 0; i < 20; ++i) { + b[i] = 2.01f + 1.f; + ((float *)a)[i] = 2.01f * 2.0145f; + ((float *)a + 38)[i] = 2.01f * 1.0123f; + } + + // CHECK: TypeSanitizer: type-aliasing-violation on address + // CHECK-NEXT: WRITE of size 8 at {{.+}} with type double accesses an existing object of type float + // CHECK-NEXT: in main {{.*/?}}violation-pr45282.c:25 + + // loop of problems + for (j = 2; j <= 4; ++j) { + a[j - 1] = ((float *)a)[j] * ((float *)a + 38)[j - 1]; + ((float *)a + 38)[j - 1] = ((float *)a)[j - 1] + b[j - 1]; + } + + printf("((float *)a + 38)[2] = %f\n", ((float *)a + 38)[2]); + + return 0; +} diff --git a/compiler-rt/test/tysan/violation-pr47137.c b/compiler-rt/test/tysan/violation-pr47137.c new file mode 100644 index 000000000000..fb895ff729de --- /dev/null +++ b/compiler-rt/test/tysan/violation-pr47137.c @@ -0,0 +1,41 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +// https://github.com/llvm/llvm-project/issues/47137 +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +void f(int m) { + int n = (4 * m + 2) / 3; + uint64_t *a = malloc(n * sizeof(uint64_t)); + uint64_t *b = malloc(n * sizeof(uint64_t)); + uint64_t aa[] = {0xffff3e0000000001, 0x22eaf0b680a88c16, 0x5a65d25ac40e20f3, + 0x34e7ac346236953e, 0x9dea3e0a26c6ba89, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000}; + uint64_t bb[] = {0x0000000024c0ffff, 0x000000004634d940, 0x00000000219d18ef, + 0x0000000000154519, 0x000000000000035f, 0x0000000000000000, + 0x0000000000000000, 0x0000000000000000}; + char l[20]; + l[0] = 0; + for (int i = 0; i < n; i++) { + a[i] = aa[i] + l[0] - '0'; + b[i] = bb[i] + l[0] - '0'; + } + + // CHECK: TypeSanitizer: type-aliasing-violation on address + // CHECK-NEXT: READ of size 2 at {{.+}} with type short accesses an existing object of type long + // CHECK-NEXT: in f {{.*/?}}violation-pr47137.c:31 + for (int i = 0, j = 0; j < 4 * m; i += 4, j += 3) { + for (int k = 0; k < 3; k++) { + ((uint16_t *)a)[j + k] = ((uint16_t *)a)[i + k]; + ((uint16_t *)b)[j + k] = ((uint16_t *)b)[i + k]; + } + } + + printf("a: %016llx\n", a[0]); + free(a); + free(b); +} + +int main() { f(6); } diff --git a/compiler-rt/test/tysan/violation-pr51837.c b/compiler-rt/test/tysan/violation-pr51837.c new file mode 100644 index 000000000000..d49a813933d6 --- /dev/null +++ b/compiler-rt/test/tysan/violation-pr51837.c @@ -0,0 +1,34 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <stdint.h> +#include <stdio.h> + +// CHECK-NOT: TypeSanitizer + +union a { + int16_t b; + uint64_t c; +} d; + +uint64_t *e = &d.c; +static uint16_t f(int16_t a, int32_t b, uint64_t c); +static int64_t g(int32_t aa, uint8_t h, union a bb) { + int16_t *i = &d.b; + f(0, h, 0); + *i = h; + return 0; +} +uint16_t f(int16_t a, int32_t b, uint64_t c) { + for (d.c = 0; 0;) + ; + *e = 0; + return 0; +} + +int main() { + uint32_t j = 8; + g(1, j, d); + printf("%d\n", d.b); + return 0; +} diff --git a/compiler-rt/test/tysan/violation-pr62544.c b/compiler-rt/test/tysan/violation-pr62544.c new file mode 100644 index 000000000000..65dd33327211 --- /dev/null +++ b/compiler-rt/test/tysan/violation-pr62544.c @@ -0,0 +1,24 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +// https://github.com/llvm/llvm-project/issues/62544 + +int printf(const char *, ...); +int a, b, c; +long d; +int main() { + short *e = &a; + int *f = &a; + *f = 0; + for (; b <= 9; b++) { + int **g = &f; + *f = d; + *g = &c; + } + + // CHECK: TypeSanitizer: type-aliasing-violation on address + // CHECK-NEXT: WRITE of size 2 at {{.+}} with type short accesses an existing object of type int + // CHECK-NEXT: in main {{.*/?}}violation-pr62544.c:22 + *e = 3; + printf("%d\n", a); +} diff --git a/compiler-rt/test/tysan/violation-pr62828.cpp b/compiler-rt/test/tysan/violation-pr62828.cpp new file mode 100644 index 000000000000..709132c4aba6 --- /dev/null +++ b/compiler-rt/test/tysan/violation-pr62828.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +// https://github.com/llvm/llvm-project/issues/62828 +#include <stdio.h> + +typedef int int_v8[8]; +typedef short short_v8[8]; +short *test1(int_v8 *cast_c_array, short_v8 *shuf_c_array1, int *ptr) { + int *input1 = reinterpret_cast<int *>(((int_v8 *)(cast_c_array))); + short *input2 = reinterpret_cast<short *>(reinterpret_cast<int_v8 *>(input1)); + + short *output1 = reinterpret_cast<short *>(((short_v8 *)(shuf_c_array1))); + short *output2 = + reinterpret_cast<short *>(reinterpret_cast<short_v8 *>(output1)); + + for (int r = 0; r < 8; ++r) { + int tmp = (int)((r * 4) + ptr[r]); + if ((ptr[r] / 4) == 0) { + int *input = reinterpret_cast<int *>(((int_v8 *)(cast_c_array))); + input[r] = tmp; + } + } + + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation on address + // CHECK-NEXT: READ of size 2 at {{.+}} with type short accesses an existing object of type int + // CHECK-NEXT: in test1(int (*) [8], short (*) [8], int*) {{.*/?}}violation-pr62828.cpp:29 + for (int i3 = 0; i3 < 4; ++i3) { + output2[i3] = input2[(i3 * 2)]; + } + return output2; +} + +int main() { + int_v8 in[4] = {{4, 4, 4, 4}}; + short_v8 out[4] = {{0}}; + int ptr[8] = {2}; + test1(in, out, ptr); + short *p = reinterpret_cast<short *>(out); + for (int i = 0; i < 32; i++) { + printf("%d ", p[i]); + } + return 0; +} diff --git a/compiler-rt/test/tysan/violation-pr68655.cpp b/compiler-rt/test/tysan/violation-pr68655.cpp new file mode 100644 index 000000000000..7be05c7a7d4f --- /dev/null +++ b/compiler-rt/test/tysan/violation-pr68655.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +// https://github.com/llvm/llvm-project/issues/68655 +struct S1 { + long long a; + long long b; +}; + +// CHECK: TypeSanitizer: type-aliasing-violation on address +// CHECK-NEXT: READ of size 4 at {{.+}} with type int accesses an existing object of type long long (in {{.*}}S1 at offset 0) +// CHECK-NEXT: in copyMem(S1*, S1*) {{.*/?}}violation-pr68655.cpp:19 + +void inline copyMem(S1 *dst, S1 *src) { + unsigned *d = reinterpret_cast<unsigned *>(dst); + unsigned *s = reinterpret_cast<unsigned *>(src); + + for (int i = 0; i < sizeof(S1) / sizeof(unsigned); i++) { + *d = *s; + d++; + s++; + } +} + +void math(S1 *dst, int *srcA, int idx_t) { + S1 zero[4]; + for (int i = 0; i < 2; i++) { + zero[i].a = i + idx_t; + zero[i].b = i * idx_t; + } + + copyMem(&dst[idx_t], &zero[srcA[idx_t]]); +} + +int main() { + S1 dst = {0}; + int Src[2] = {0, 0}; + math(&dst, &Src[0], 0); + return 0; +} diff --git a/compiler-rt/test/tysan/violation-pr86685.c b/compiler-rt/test/tysan/violation-pr86685.c new file mode 100644 index 000000000000..43b8d478e685 --- /dev/null +++ b/compiler-rt/test/tysan/violation-pr86685.c @@ -0,0 +1,29 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out + +#include <stdio.h> +#include <stdlib.h> + +// Violation reported in https://github.com/llvm/llvm-project/issues/86685. +void foo(int *s, float *f, long n) { + for (long i = 0; i < n; ++i) { + *f = 2; + if (i == 1) + break; + + // CHECK: TypeSanitizer: type-aliasing-violation on address + // CHECK-NEXT: WRITE of size 4 at {{.+}} with type int accesses an existing object of type float + // CHECK-NEXT: #0 {{.+}} in foo {{.*/?}}violation-pr86685.c:17 + *s = 4; + } +} + +int main(void) { + union { + int s; + float f; + } u = {0}; + foo(&u.s, &u.f, 2); + printf("%.f\n", u.f); + return 0; +} diff --git a/compiler-rt/test/ubsan/TestCases/Misc/local_bounds.cpp b/compiler-rt/test/ubsan/TestCases/Misc/local_bounds.cpp new file mode 100644 index 000000000000..5c3bae80ecdd --- /dev/null +++ b/compiler-rt/test/ubsan/TestCases/Misc/local_bounds.cpp @@ -0,0 +1,34 @@ +// RUN: %clangxx -fsanitize=local-bounds %s -O3 -o %t && %run %t 1 +// RUN: %clangxx -fsanitize=local-bounds %s -O3 -o %t && not --crash %run %t 3 +// RUN: %clangxx -fsanitize=local-bounds -fno-sanitize-trap=local-bounds %s -O3 -o %t && not %run %t 3 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=local-bounds -fno-sanitize-trap=local-bounds -fsanitize-recover=local-bounds %s -O3 -o %t && %run %t 3 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=local-bounds -fno-sanitize-trap=local-bounds -fsanitize-recover=local-bounds -g %s -O3 -o %t && %run %t 3 2>&1 | FileCheck %s --check-prefixes=LINE + +#include <cstdlib> + +struct S { + int k; + int l; +}; + +__attribute__((noinline)) void init(S *s) { + __asm__ __volatile__("" : : "r"(s) : "memory"); +} + +__attribute__((noinline, no_sanitize("memory", "address", "hwaddress"))) int +test(char i) { + S a; + init(&a); + S b; + init(&b); + return ((int *)(&a))[i]; + // CHECK: error: access out of bounds + // CHECK: SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior + // LINE: local_bounds.cpp:[[#@LINE-3]]:{{.*}}runtime error: access out of bounds + // LINE: SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior {{.*}}local_bounds.cpp:[[#@LINE-4]] +} + +int main(int argc, char **argv) { + test(argv[1][0] - '0'); + return 0; +} diff --git a/compiler-rt/test/ubsan_minimal/TestCases/local_bounds.cpp b/compiler-rt/test/ubsan_minimal/TestCases/local_bounds.cpp new file mode 100644 index 000000000000..c972e1ecfc01 --- /dev/null +++ b/compiler-rt/test/ubsan_minimal/TestCases/local_bounds.cpp @@ -0,0 +1,29 @@ +// RUN: %clangxx -fsanitize=local-bounds %s -O3 -o %t && %run %t 1 +// RUN: %clangxx -fsanitize=local-bounds %s -O3 -o %t && not --crash %run %t 3 +// RUN: %clangxx -fsanitize=local-bounds -fno-sanitize-trap=local-bounds %s -O3 -o %t && not --crash %run %t 3 2>&1 | FileCheck %s +// RUN: %clangxx -fsanitize=local-bounds -fno-sanitize-trap=local-bounds -fsanitize-recover=local-bounds %s -O3 -o %t && %run %t 3 2>&1 | FileCheck %s + +#include <cstdlib> + +struct S { + int k; + int l; +}; + +__attribute__((noinline)) void init(S *s) { + __asm__ __volatile__("" : : "r"(s) : "memory"); +} + +__attribute__((noinline, no_sanitize("memory"))) int test(char i) { + S a; + init(&a); + S b; + init(&b); + return ((int *)(&a))[i]; + // CHECK: ubsan: local-out-of-bounds by 0x{{[[:xdigit:]]+$}} +} + +int main(int argc, char **argv) { + test(argv[1][0] - '0'); + return 0; +} diff --git a/compiler-rt/test/ubsan_minimal/TestCases/override-callback.c b/compiler-rt/test/ubsan_minimal/TestCases/override-callback.c new file mode 100644 index 000000000000..e11a3712f1be --- /dev/null +++ b/compiler-rt/test/ubsan_minimal/TestCases/override-callback.c @@ -0,0 +1,15 @@ +// RUN: %clang -fsanitize=implicit-integer-sign-change %s -o %t && %run %t 0 2>&1 | FileCheck %s +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +static int Result; + +void __ubsan_report_error(const char *kind, uintptr_t caller) { + fprintf(stderr, "CUSTOM_CALLBACK: %s\n", kind); +} + +int main(int argc, const char **argv) { + int32_t t0 = (~((uint32_t)0)); + // CHECK: CUSTOM_CALLBACK: implicit-conversion +} |
