From 316d58822dada9440bd06ecfc758dcc2364d617c Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Mon, 2 Jan 2017 19:18:27 +0000 Subject: Vendor import of compiler-rt trunk r290819: https://llvm.org/svn/llvm-project/compiler-rt/trunk@290819 --- test/asan/TestCases/Android/coverage-android.cc | 4 + test/asan/TestCases/Darwin/cstring_section.c | 17 ++ test/asan/TestCases/Darwin/dead-strip.c | 22 +++ test/asan/TestCases/Darwin/dump_registers.cc | 26 +++ test/asan/TestCases/Darwin/malloc_destroy_zone.cc | 21 +++ test/asan/TestCases/Darwin/odr-lto.cc | 45 +++++ test/asan/TestCases/Linux/abort_on_error.cc | 2 + .../TestCases/Linux/auto_memory_profile_test.cc | 32 ++++ test/asan/TestCases/Linux/coverage_html_report.cc | 24 --- test/asan/TestCases/Linux/cuda_test.cc | 37 ++++ test/asan/TestCases/Linux/local_alias.cc | 5 +- .../asan/TestCases/Linux/malloc_delete_mismatch.cc | 3 +- test/asan/TestCases/Linux/memmem_test.cc | 13 +- test/asan/TestCases/Linux/new_delete_mismatch.cc | 4 +- test/asan/TestCases/Linux/odr-violation.cc | 5 +- .../TestCases/Linux/print_memory_profile_test.cc | 24 +-- .../Linux/pthread_create_from_constructor.cc | 49 ++++++ test/asan/TestCases/Linux/quarantine_size_mb.cc | 2 +- test/asan/TestCases/Linux/release_to_os_test.cc | 46 +++++ test/asan/TestCases/Linux/scariness_score_test.cc | 192 -------------------- test/asan/TestCases/Linux/stack-trace-dlclose.cc | 3 +- .../asan/TestCases/Linux/swapcontext_annotation.cc | 74 +++++--- .../Linux/thread_local_quarantine_size_kb.cc | 40 +++++ .../TestCases/Posix/asan-symbolize-sanity-test.cc | 4 +- test/asan/TestCases/Posix/coverage-fork.cc | 2 +- test/asan/TestCases/Posix/halt_on_error-signals.c | 2 +- test/asan/TestCases/Posix/halt_on_error-torture.cc | 11 +- .../Posix/halt_on_error_suppress_equal_pcs.cc | 6 +- test/asan/TestCases/Posix/handle_abort_on_error.cc | 9 + test/asan/TestCases/Posix/no_asan_gen_globals.c | 12 ++ test/asan/TestCases/Posix/start-deactivated.cc | 41 +++-- .../Windows/bind_io_completion_callback.cc | 5 - test/asan/TestCases/Windows/coverage-dll-stdio.cc | 16 ++ test/asan/TestCases/Windows/default_options.cc | 18 -- test/asan/TestCases/Windows/delay_dbghelp.cc | 18 ++ .../asan/TestCases/Windows/dll_global_dead_strip.c | 28 +++ test/asan/TestCases/Windows/dll_host.cc | 31 +++- .../asan/TestCases/Windows/dll_intercept_memchr.cc | 6 + .../Windows/dll_intercept_memcpy_indirect.cc | 2 +- .../dll_operator_array_new_with_dtor_left_oob.cc | 4 +- test/asan/TestCases/Windows/free_hook_realloc.cc | 3 + test/asan/TestCases/Windows/global_dead_strip.c | 23 +++ test/asan/TestCases/Windows/intercept_memcpy.cc | 4 +- test/asan/TestCases/Windows/on_error_callback.cc | 20 --- test/asan/TestCases/Windows/oom.cc | 1 + .../operator_array_new_with_dtor_left_oob.cc | 4 +- .../asan/TestCases/Windows/queue_user_work_item.cc | 5 - .../Windows/queue_user_work_item_report.cc | 2 - .../Windows/report_after_syminitialize.cc | 6 +- test/asan/TestCases/Windows/shadow_conflict_32.cc | 29 +++ .../TestCases/Windows/shadow_mapping_failure.cc | 1 + test/asan/TestCases/Windows/tls_init.cc | 51 ++++++ test/asan/TestCases/Windows/unsymbolized.cc | 4 +- test/asan/TestCases/alloca_big_alignment.cc | 2 +- test/asan/TestCases/alloca_detect_custom_size_.cc | 2 +- .../TestCases/alloca_instruments_all_paddings.cc | 4 +- test/asan/TestCases/alloca_loop_unpoisoning.cc | 2 +- test/asan/TestCases/alloca_overflow_partial.cc | 2 +- test/asan/TestCases/alloca_overflow_right.cc | 2 +- test/asan/TestCases/alloca_safe_access.cc | 2 +- test/asan/TestCases/alloca_underflow_left.cc | 2 +- test/asan/TestCases/alloca_vla_interact.cc | 2 +- test/asan/TestCases/atexit_stats.cc | 4 +- test/asan/TestCases/coverage-order-pcs.cc | 2 +- test/asan/TestCases/coverage-pc-buffer.cc | 65 ------- test/asan/TestCases/coverage-tracing.cc | 2 +- test/asan/TestCases/debug_double_free.cc | 50 ++++++ test/asan/TestCases/debug_mapping.cc | 8 +- test/asan/TestCases/debug_report.cc | 3 + test/asan/TestCases/debug_stacks.cc | 14 +- test/asan/TestCases/deep_stack_uaf.cc | 3 +- test/asan/TestCases/default_options.cc | 3 + test/asan/TestCases/double-free.cc | 4 +- test/asan/TestCases/exitcode.cc | 130 ++++++++++++++ test/asan/TestCases/global-address.cpp | 12 ++ test/asan/TestCases/ill.cc | 31 ++++ test/asan/TestCases/initialization-bug.cc | 4 +- test/asan/TestCases/interception_failure_test.cc | 11 +- test/asan/TestCases/intra-object-overflow.cc | 2 + test/asan/TestCases/invalid-free.cc | 3 +- test/asan/TestCases/large_func_test.cc | 3 +- test/asan/TestCases/no_asan_gen_globals.c | 13 -- test/asan/TestCases/on_error_callback.cc | 3 + test/asan/TestCases/printf-m.c | 14 ++ test/asan/TestCases/sanity_check_pure_c.c | 5 +- test/asan/TestCases/scariness_score_test.cc | 194 +++++++++++++++++++++ test/asan/TestCases/set_shadow_test.c | 69 ++++++++ test/asan/TestCases/speculative_load.cc | 4 + test/asan/TestCases/strdup_oob_test.cc | 4 + test/asan/TestCases/strncasecmp_strict.c | 67 +++++++ test/asan/TestCases/strncmp_strict.c | 65 +++++++ test/asan/TestCases/strncpy-overflow.cc | 3 +- test/asan/TestCases/strstr-1.c | 2 +- test/asan/TestCases/strstr_strict.c | 2 +- test/asan/TestCases/suppressions-library.cc | 2 +- test/asan/TestCases/use-after-delete.cc | 3 +- test/asan/TestCases/use-after-free-right.cc | 3 +- test/asan/TestCases/use-after-free.cc | 3 +- test/asan/TestCases/use-after-scope-capture.cc | 2 +- test/asan/TestCases/use-after-scope-chars.cc | 15 -- test/asan/TestCases/use-after-scope-goto.cc | 73 ++++++++ test/asan/TestCases/use-after-scope-inlined.cc | 2 +- test/asan/TestCases/use-after-scope-loop-bug.cc | 9 +- .../asan/TestCases/use-after-scope-loop-removed.cc | 9 +- test/asan/TestCases/use-after-scope-temp.cc | 12 +- test/asan/TestCases/use-after-scope-temp2.cc | 20 +++ test/asan/TestCases/use-after-scope-types.cc | 74 ++++++++ test/asan/TestCases/use-after-scope.cc | 5 +- test/asan/TestCases/vla_chrome_testcase.cc | 2 +- test/asan/TestCases/vla_condition_overflow.cc | 2 +- test/asan/TestCases/vla_loop_overfow.cc | 2 +- 111 files changed, 1601 insertions(+), 514 deletions(-) create mode 100644 test/asan/TestCases/Darwin/cstring_section.c create mode 100644 test/asan/TestCases/Darwin/dead-strip.c create mode 100644 test/asan/TestCases/Darwin/dump_registers.cc create mode 100644 test/asan/TestCases/Darwin/malloc_destroy_zone.cc create mode 100644 test/asan/TestCases/Darwin/odr-lto.cc create mode 100644 test/asan/TestCases/Linux/auto_memory_profile_test.cc delete mode 100644 test/asan/TestCases/Linux/coverage_html_report.cc create mode 100644 test/asan/TestCases/Linux/cuda_test.cc create mode 100644 test/asan/TestCases/Linux/pthread_create_from_constructor.cc create mode 100644 test/asan/TestCases/Linux/release_to_os_test.cc delete mode 100644 test/asan/TestCases/Linux/scariness_score_test.cc create mode 100644 test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc create mode 100644 test/asan/TestCases/Posix/handle_abort_on_error.cc create mode 100644 test/asan/TestCases/Posix/no_asan_gen_globals.c create mode 100644 test/asan/TestCases/Windows/coverage-dll-stdio.cc delete mode 100644 test/asan/TestCases/Windows/default_options.cc create mode 100644 test/asan/TestCases/Windows/delay_dbghelp.cc create mode 100644 test/asan/TestCases/Windows/dll_global_dead_strip.c create mode 100644 test/asan/TestCases/Windows/global_dead_strip.c delete mode 100644 test/asan/TestCases/Windows/on_error_callback.cc create mode 100644 test/asan/TestCases/Windows/shadow_conflict_32.cc create mode 100644 test/asan/TestCases/Windows/tls_init.cc delete mode 100644 test/asan/TestCases/coverage-pc-buffer.cc create mode 100644 test/asan/TestCases/debug_double_free.cc create mode 100644 test/asan/TestCases/exitcode.cc create mode 100644 test/asan/TestCases/global-address.cpp create mode 100644 test/asan/TestCases/ill.cc delete mode 100644 test/asan/TestCases/no_asan_gen_globals.c create mode 100644 test/asan/TestCases/printf-m.c create mode 100644 test/asan/TestCases/scariness_score_test.cc create mode 100644 test/asan/TestCases/set_shadow_test.c create mode 100644 test/asan/TestCases/strncasecmp_strict.c create mode 100644 test/asan/TestCases/strncmp_strict.c delete mode 100644 test/asan/TestCases/use-after-scope-chars.cc create mode 100644 test/asan/TestCases/use-after-scope-goto.cc create mode 100644 test/asan/TestCases/use-after-scope-temp2.cc create mode 100644 test/asan/TestCases/use-after-scope-types.cc (limited to 'test/asan/TestCases') diff --git a/test/asan/TestCases/Android/coverage-android.cc b/test/asan/TestCases/Android/coverage-android.cc index 2a3359948691..cf4f33ebdb44 100644 --- a/test/asan/TestCases/Android/coverage-android.cc +++ b/test/asan/TestCases/Android/coverage-android.cc @@ -101,6 +101,10 @@ // RUN: %sancov rawunpack *.sancov.raw // RUN: %sancov print *.sancov |& FileCheck --check-prefix=CHECK3 %s +// PC counts in CHECK lines are platform dependent and match arm32 at the moment. +// sancov tool does not support Android well enough to match function names +// REQUIRES: arm + #include #include #include diff --git a/test/asan/TestCases/Darwin/cstring_section.c b/test/asan/TestCases/Darwin/cstring_section.c new file mode 100644 index 000000000000..952d6fcdd465 --- /dev/null +++ b/test/asan/TestCases/Darwin/cstring_section.c @@ -0,0 +1,17 @@ +// Test that AddressSanitizer moves constant strings into a separate section. + +// RUN: %clang_asan -c -o %t %s +// RUN: llvm-objdump -s %t | FileCheck %s + +// Check that "Hello.\n" is in __asan_cstring and not in __cstring. +// CHECK: Contents of section __asan_cstring: +// CHECK: 48656c6c {{.*}} Hello. +// CHECK: Contents of section __const: +// CHECK-NOT: 48656c6c {{.*}} Hello. +// CHECK: Contents of section __cstring: +// CHECK-NOT: 48656c6c {{.*}} Hello. + +int main(int argc, char *argv[]) { + argv[0] = "Hello.\n"; + return 0; +} diff --git a/test/asan/TestCases/Darwin/dead-strip.c b/test/asan/TestCases/Darwin/dead-strip.c new file mode 100644 index 000000000000..f87a5e52b1cf --- /dev/null +++ b/test/asan/TestCases/Darwin/dead-strip.c @@ -0,0 +1,22 @@ +// Test that AddressSanitizer does not re-animate dead globals when dead +// stripping is turned on. +// +// This test verifies that an out-of-bounds access on a global variable is +// detected after dead stripping has been performed. This proves that the +// runtime is able to register globals in the __DATA,__asan_globals section. + +// REQUIRES: osx-ld64-live_support +// RUN: %clang_asan -mmacosx-version-min=10.11 -Xlinker -dead_strip -o %t %s +// RUN: llvm-nm -format=posix %t | FileCheck --check-prefix NM-CHECK %s +// RUN: not %run %t 2>&1 | FileCheck --check-prefix ASAN-CHECK %s + +int alive[1] = {}; +int dead[1] = {}; +// NM-CHECK: {{^_alive }} +// NM-CHECK-NOT: {{^_dead }} + +int main(int argc, char *argv[]) { + alive[argc] = 0; + // ASAN-CHECK: {{0x.* is located 0 bytes to the right of global variable}} + return 0; +} diff --git a/test/asan/TestCases/Darwin/dump_registers.cc b/test/asan/TestCases/Darwin/dump_registers.cc new file mode 100644 index 000000000000..884ad2ed44c0 --- /dev/null +++ b/test/asan/TestCases/Darwin/dump_registers.cc @@ -0,0 +1,26 @@ +// Check that ASan dumps the CPU registers on a SIGSEGV. + +// RUN: %clangxx_asan %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s + +#include +#include + +int main() { + fprintf(stderr, "Hello\n"); + char *ptr; + + if (sizeof(void *) == 8) + ptr = (char *)0x6666666666666666; + else if (sizeof(void *) == 4) + ptr = (char *)0x55555555; + else + assert(0 && "Your computer is weird."); + + char c = *ptr; // BOOM + // CHECK: ERROR: AddressSanitizer: SEGV + // CHECK: Register values: + // CHECK: {{0x55555555|0x6666666666666666}} + fprintf(stderr, "World\n"); + return c; +} diff --git a/test/asan/TestCases/Darwin/malloc_destroy_zone.cc b/test/asan/TestCases/Darwin/malloc_destroy_zone.cc new file mode 100644 index 000000000000..9144bd689f74 --- /dev/null +++ b/test/asan/TestCases/Darwin/malloc_destroy_zone.cc @@ -0,0 +1,21 @@ +// RUN: %clangxx_asan %s -o %t && %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +int main() { + fprintf(stderr, "start\n"); + malloc_zone_t *zone = malloc_create_zone(0, 0); + fprintf(stderr, "zone = %p\n", zone); + malloc_set_zone_name(zone, "myzone"); + fprintf(stderr, "name changed\n"); + malloc_destroy_zone(zone); + fprintf(stderr, "done\n"); + return 0; +} + +// CHECK: start +// CHECK-NEXT: zone = 0x{{.*}} +// CHECK-NEXT: name changed +// CHECK-NEXT: done diff --git a/test/asan/TestCases/Darwin/odr-lto.cc b/test/asan/TestCases/Darwin/odr-lto.cc new file mode 100644 index 000000000000..40abec5827d5 --- /dev/null +++ b/test/asan/TestCases/Darwin/odr-lto.cc @@ -0,0 +1,45 @@ +// Check that -asan-use-private-alias and use_odr_indicator=1 silence the false +// positive ODR violation on Darwin with LTO. + +// 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 + +#include +#include +void putstest(); + +#if PART == 1 + +static const char *my_global = "test\n\00abc"; + +int main() +{ + fputs(my_global, stderr); + putstest(); + fprintf(stderr, "Done.\n"); + return 0; +} + +#else // PART == 1 + +static const char *my_other_global = "test\n\00abc"; + +void putstest() +{ + fputs(my_other_global, stderr); +} + +#endif // PART == 1 + +// CHECK-ODR: ERROR: AddressSanitizer: odr-violation +// CHECK-NO-ODR-NOT: ERROR: AddressSanitizer: odr-violation +// CHECK-NO-ODR: Done. diff --git a/test/asan/TestCases/Linux/abort_on_error.cc b/test/asan/TestCases/Linux/abort_on_error.cc index 67fa9b83e65d..3f70613e4c7c 100644 --- a/test/asan/TestCases/Linux/abort_on_error.cc +++ b/test/asan/TestCases/Linux/abort_on_error.cc @@ -9,6 +9,8 @@ // lit doesn't set ASAN_OPTIONS anyway. // RUN: not %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: android + #include int main() { char *x = (char*)malloc(10 * sizeof(char)); diff --git a/test/asan/TestCases/Linux/auto_memory_profile_test.cc b/test/asan/TestCases/Linux/auto_memory_profile_test.cc new file mode 100644 index 000000000000..3f8ad4673e75 --- /dev/null +++ b/test/asan/TestCases/Linux/auto_memory_profile_test.cc @@ -0,0 +1,32 @@ +// Tests heap_profile=1. +// Printing memory profiling only works in the configuration where we can +// detect leaks. +// REQUIRES: leak-detection +// +// RUN: %clangxx_asan %s -o %t +// RUN: %env_asan_opts=heap_profile=1 %run %t 2>&1 | FileCheck %s +#include + +#include +#include +#include + +char *sink[1000]; + +int main() { + + for (int i = 0; i < 3; i++) { + const size_t kSize = 13000000; + char *x = new char[kSize]; + memset(x, 0, kSize); + sink[i] = x; + sleep(1); + } +} + +// CHECK: HEAP PROFILE at RSS +// CHECK: 13000000 byte(s) +// CHECK: HEAP PROFILE at RSS +// CHECK: 26000000 byte(s) +// CHECK: HEAP PROFILE at RSS +// CHECK: 39000000 byte(s) diff --git a/test/asan/TestCases/Linux/coverage_html_report.cc b/test/asan/TestCases/Linux/coverage_html_report.cc deleted file mode 100644 index 78fbfb372403..000000000000 --- a/test/asan/TestCases/Linux/coverage_html_report.cc +++ /dev/null @@ -1,24 +0,0 @@ -// REQUIRES: has_sancovcc, x86_64-linux, asan-dynamic-runtime -// RUN: %clangxx_asan_static -fsanitize-coverage=func %s -o %t -// RUN: rm -rf %T/coverage_html_report -// RUN: mkdir -p %T/coverage_html_report -// RUN: cd %T/coverage_html_report -// RUN: %env_asan_opts=coverage=1:verbosity=1:html_cov_report=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-main -// RUN: ls *.html | FileCheck %s --check-prefix=CHECK-ls -// RUN: rm -r %T/coverage_html_report - -#include -#include - -void bar() { printf("bar\n"); } - -int main(int argc, char **argv) { - fprintf(stderr, "PID: %d\n", getpid()); - bar(); - return 0; -} - -// CHECK-main: PID: [[PID:[0-9]+]] -// CHECK-main: [[PID]].sancov: 2 PCs written -// CHECK-main: coverage report generated to ./coverage_html_report.cc.tmp.[[PID]].html -// CHECK-ls: coverage_html_report.cc.tmp.{{[0-9]+}}.html diff --git a/test/asan/TestCases/Linux/cuda_test.cc b/test/asan/TestCases/Linux/cuda_test.cc new file mode 100644 index 000000000000..e87f56b0c20e --- /dev/null +++ b/test/asan/TestCases/Linux/cuda_test.cc @@ -0,0 +1,37 @@ +// Emulate the behavior of the NVIDIA CUDA driver +// that mmaps memory inside the asan's shadow gap. +// +// REQUIRES: x86_64-target-arch +// +// RUN: %clangxx_asan %s -o %t +// RUN: not %env_asan_opts=protect_shadow_gap=1 %t 2>&1 | FileCheck %s --check-prefix=CHECK-PROTECT1 +// RUN: not %t 2>&1 | FileCheck %s --check-prefix=CHECK-PROTECT1 +// RUN: not %env_asan_opts=protect_shadow_gap=0 %t 2>&1 | FileCheck %s --check-prefix=CHECK-PROTECT0 +#include +#include +#include +#include + +#include "sanitizer/asan_interface.h" + +int main(void) { + uintptr_t Base = 0x200000000; + uintptr_t Size = 0x1100000000; + void *addr = + mmap((void *)Base, Size, PROT_READ | PROT_WRITE, + MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0); + assert(addr == (void*)Base); + // Make sure we can access memory in shadow gap. + // W/o protect_shadow_gap=0 we should fail here. + for (uintptr_t Addr = Base; Addr < Base + Size; Addr += Size / 100) + *(char*)Addr = 1; + // CHECK-PROTECT1: AddressSanitizer: SEGV on unknown address 0x0000bfff8000 + + // Poison a part of gap's shadow: + __asan_poison_memory_region((void*)Base, 4096); + // Now we should fail with use-after-poison. + *(char*)(Base + 1234) = 1; + // CHECK-PROTECT0: AddressSanitizer: use-after-poison on address 0x0002000004d2 +} + + diff --git a/test/asan/TestCases/Linux/local_alias.cc b/test/asan/TestCases/Linux/local_alias.cc index d941ff2f9171..8c80f878594d 100644 --- a/test/asan/TestCases/Linux/local_alias.cc +++ b/test/asan/TestCases/Linux/local_alias.cc @@ -6,7 +6,10 @@ // // FIXME: https://github.com/google/sanitizers/issues/316 // XFAIL: android -// XFAIL: mips64 +// +// 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 diff --git a/test/asan/TestCases/Linux/malloc_delete_mismatch.cc b/test/asan/TestCases/Linux/malloc_delete_mismatch.cc index 66eed33052c3..50d920e43f38 100644 --- a/test/asan/TestCases/Linux/malloc_delete_mismatch.cc +++ b/test/asan/TestCases/Linux/malloc_delete_mismatch.cc @@ -12,8 +12,7 @@ // Also works if no malloc context is available. // RUN: %env_asan_opts=alloc_dealloc_mismatch=1:malloc_context_size=0:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s // RUN: %env_asan_opts=alloc_dealloc_mismatch=1:malloc_context_size=0:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime #include static volatile char *x; diff --git a/test/asan/TestCases/Linux/memmem_test.cc b/test/asan/TestCases/Linux/memmem_test.cc index 54883004e0aa..661381cdd7b7 100644 --- a/test/asan/TestCases/Linux/memmem_test.cc +++ b/test/asan/TestCases/Linux/memmem_test.cc @@ -1,6 +1,6 @@ // RUN: %clangxx_asan %s -o %t -// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=A1 -// RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=A2 +// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=A1 +// RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=A2 // RUN: %env_asan_opts=intercept_memmem=0 %run %t #include @@ -12,10 +12,13 @@ int main(int argc, char **argv) { res = memmem(a1, sizeof(a1) + 1, a2, sizeof(a2)); // BOOM else res = memmem(a1, sizeof(a1), a2, sizeof(a2) + 1); // BOOM - // CHECK: AddressSanitizer: stack-buffer-overflow - // CHECK: {{#0.*memmem}} - // CHECK: {{#1.*main}} + // A1: AddressSanitizer: stack-buffer-overflow + // A1: {{#0.*memmem}} + // A1-NEXT: {{#1.*main}} // A1: 'a1' <== Memory access at offset + // + // A2: AddressSanitizer: stack-buffer-overflow + // A2: {{#0.*memmem}} // A2: 'a2' <== Memory access at offset return res == NULL; } diff --git a/test/asan/TestCases/Linux/new_delete_mismatch.cc b/test/asan/TestCases/Linux/new_delete_mismatch.cc index 1cfc0ef05312..3a71862fb732 100644 --- a/test/asan/TestCases/Linux/new_delete_mismatch.cc +++ b/test/asan/TestCases/Linux/new_delete_mismatch.cc @@ -1,8 +1,8 @@ // Check that we report new[] vs delete as alloc-dealloc-mismatch and not as // new-delete-type-mismatch when -fsized-deallocation is enabled. -// RUN: %clangxx_asan -g %s -o %t && not %run %t |& FileCheck %s -// RUN: %clangxx_asan -fsized-deallocation -g %s -o %t && not %run %t |& FileCheck %s +// RUN: %clangxx_asan -g %s -o %t && %env_asan_opts=alloc_dealloc_mismatch=1 not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -fsized-deallocation -g %s -o %t && %env_asan_opts=alloc_dealloc_mismatch=1 not %run %t 2>&1 | FileCheck %s #include diff --git a/test/asan/TestCases/Linux/odr-violation.cc b/test/asan/TestCases/Linux/odr-violation.cc index 143fb6e14344..d909143a86a1 100644 --- a/test/asan/TestCases/Linux/odr-violation.cc +++ b/test/asan/TestCases/Linux/odr-violation.cc @@ -1,6 +1,9 @@ // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 // XFAIL: android -// XFAIL: mips64 +// +// 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/print_memory_profile_test.cc b/test/asan/TestCases/Linux/print_memory_profile_test.cc index d30dbea1cf6d..8909ccad08d4 100644 --- a/test/asan/TestCases/Linux/print_memory_profile_test.cc +++ b/test/asan/TestCases/Linux/print_memory_profile_test.cc @@ -3,27 +3,31 @@ // REQUIRES: leak-detection // // RUN: %clangxx_asan %s -o %t -// RUN: %run %t 2>&1 | FileCheck %s +// RUN: %run %t 100 2>&1 | FileCheck %s --check-prefix=CHECK-100 +// RUN: %run %t 50 2>&1 | FileCheck %s --check-prefix=CHECK-50 #include #include +#include char *sink[1000]; -int main() { +int main(int argc, char **argv) { + if (argc < 2) + return 1; + int idx = 0; for (int i = 0; i < 17; i++) sink[idx++] = new char[131000]; for (int i = 0; i < 28; i++) sink[idx++] = new char[24000]; - __sanitizer_print_memory_profile(100); - __sanitizer_print_memory_profile(50); + __sanitizer_print_memory_profile(atoi(argv[1])); } -// CHECK: Live Heap Allocations: {{.*}}; showing top 100% -// CHECK: 2227000 byte(s) ({{.*}}%) in 17 allocation(s) -// CHECK: 672000 byte(s) ({{.*}}%) in 28 allocation(s) -// CHECK: Live Heap Allocations: {{.*}}; showing top 50% -// CHECK: 2227000 byte(s) ({{.*}}%) in 17 allocation(s) -// CHECK-NOT: 1008 byte +// CHECK-100: Live Heap Allocations: {{.*}}; showing top 100% +// CHECK-100: 2227000 byte(s) ({{.*}}%) in 17 allocation(s) +// CHECK-100: 672000 byte(s) ({{.*}}%) in 28 allocation(s) +// CHECK-50: Live Heap Allocations: {{.*}}; showing top 50% +// CHECK-50: 2227000 byte(s) ({{.*}}%) in 17 allocation(s) +// CHECK-50-NOT: allocation diff --git a/test/asan/TestCases/Linux/pthread_create_from_constructor.cc b/test/asan/TestCases/Linux/pthread_create_from_constructor.cc new file mode 100644 index 000000000000..8f9b0b4fed1a --- /dev/null +++ b/test/asan/TestCases/Linux/pthread_create_from_constructor.cc @@ -0,0 +1,49 @@ +// Test that ASan doesn't deadlock in __interceptor_pthread_create called +// from dlopened shared library constructor. The deadlock happens only in shared +// ASan runtime with recent Glibc (2.23 fits) when __interceptor_pthread_create +// grabs global Glibc's GL(dl_load_lock) and waits for tls_get_addr_tail that +// also tries to acquire it. +// +// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t-so.so +// RUN: %clangxx_asan %s -o %t +// RUN: %run %t 2>&1 + +// dlopen() can not be intercepted on Android +// UNSUPPORTED: android +// REQUIRES: x86-target-arch + +#ifdef BUILD_SO + +#include +#include +#include + +void *threadFn(void *) { + fprintf(stderr, "thread started\n"); + while (true) { + usleep(100000); + } + return 0; +} + +void __attribute__((constructor)) startPolling() { + fprintf(stderr, "initializing library\n"); + pthread_t t; + pthread_create(&t, 0, &threadFn, 0); + fprintf(stderr, "done\n"); +} + +#else + +#include +#include +#include + +int main(int argc, char **argv) { + std::string path = std::string(argv[0]) + "-so.so"; + void *handle = dlopen(path.c_str(), RTLD_LAZY); + if (!handle) + abort(); + return 0; +} +#endif diff --git a/test/asan/TestCases/Linux/quarantine_size_mb.cc b/test/asan/TestCases/Linux/quarantine_size_mb.cc index cbacec22fa1e..239eeabee170 100644 --- a/test/asan/TestCases/Linux/quarantine_size_mb.cc +++ b/test/asan/TestCases/Linux/quarantine_size_mb.cc @@ -4,7 +4,7 @@ // RUN: %env_asan_opts=quarantine_size_mb=10:verbosity=1:hard_rss_limit_mb=50 %run %t 2>&1 | FileCheck %s --check-prefix=Q10 // 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=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 #include char *g; diff --git a/test/asan/TestCases/Linux/release_to_os_test.cc b/test/asan/TestCases/Linux/release_to_os_test.cc new file mode 100644 index 000000000000..26402167d6b1 --- /dev/null +++ b/test/asan/TestCases/Linux/release_to_os_test.cc @@ -0,0 +1,46 @@ +// Tests ASAN_OPTIONS=allocator_release_to_os=1 +// + +// RUN: %clangxx_asan -std=c++11 %s -o %t +// RUN: %env_asan_opts=allocator_release_to_os_interval_ms=0 %run %t 2>&1 | FileCheck %s --check-prefix=RELEASE +// RUN: %env_asan_opts=allocator_release_to_os_interval_ms=-1 %run %t 2>&1 | FileCheck %s --check-prefix=NO_RELEASE +// +// REQUIRES: x86_64-target-arch +#include +#include +#include +#include +#include + +#include + +void MallocReleaseStress() { + const size_t kNumChunks = 10000; + const size_t kAllocSize = 100; + const size_t kNumIter = 100; + uintptr_t *chunks[kNumChunks] = {0}; + + for (size_t iter = 0; iter < kNumIter; iter++) { + std::random_shuffle(chunks, chunks + kNumChunks); + size_t to_replace = rand() % kNumChunks; + for (size_t i = 0; i < kNumChunks; i++) { + if (chunks[i]) + assert(chunks[i][0] == (uintptr_t)chunks[i]); + if (i < to_replace) { + delete [] chunks[i]; + chunks[i] = new uintptr_t[kAllocSize]; + chunks[i][0] = (uintptr_t)chunks[i]; + } + } + } + for (auto p : chunks) + delete[] p; +} + +int main() { + MallocReleaseStress(); + __asan_print_accumulated_stats(); +} + +// RELEASE: mapped:{{.*}}releases: {{[1-9]}} +// NO_RELEASE: mapped:{{.*}}releases: 0 diff --git a/test/asan/TestCases/Linux/scariness_score_test.cc b/test/asan/TestCases/Linux/scariness_score_test.cc deleted file mode 100644 index 24854132f539..000000000000 --- a/test/asan/TestCases/Linux/scariness_score_test.cc +++ /dev/null @@ -1,192 +0,0 @@ -// Test how we produce the scariness score. - -// RUN: %clangxx_asan -O0 %s -o %t -// RUN: export %env_asan_opts=detect_stack_use_after_return=1:handle_abort=1:print_scariness=1 -// Make sure the stack is limited (may not be the default under GNU make) -// RUN: ulimit -s 4096 -// RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK1 -// RUN: not %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK2 -// RUN: not %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK3 -// RUN: not %run %t 4 2>&1 | FileCheck %s --check-prefix=CHECK4 -// RUN: not %run %t 5 2>&1 | FileCheck %s --check-prefix=CHECK5 -// RUN: not %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK6 -// RUN: not %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK7 -// RUN: not %run %t 8 2>&1 | FileCheck %s --check-prefix=CHECK8 -// RUN: not %run %t 9 2>&1 | FileCheck %s --check-prefix=CHECK9 -// RUN: not %run %t 10 2>&1 | FileCheck %s --check-prefix=CHECK10 -// RUN: not %run %t 11 2>&1 | FileCheck %s --check-prefix=CHECK11 -// RUN: not %run %t 12 2>&1 | FileCheck %s --check-prefix=CHECK12 -// RUN: not %run %t 13 2>&1 | FileCheck %s --check-prefix=CHECK13 -// RUN: not %run %t 14 2>&1 | FileCheck %s --check-prefix=CHECK14 -// RUN: not %run %t 15 2>&1 | FileCheck %s --check-prefix=CHECK15 -// RUN: not %run %t 16 2>&1 | FileCheck %s --check-prefix=CHECK16 -// RUN: not %run %t 17 2>&1 | FileCheck %s --check-prefix=CHECK17 -// RUN: not %run %t 18 2>&1 | FileCheck %s --check-prefix=CHECK18 -// RUN: not %run %t 19 2>&1 | FileCheck %s --check-prefix=CHECK19 -// RUN: not %run %t 20 2>&1 | FileCheck %s --check-prefix=CHECK20 -// RUN: not %run %t 21 2>&1 | FileCheck %s --check-prefix=CHECK21 -// RUN: not %run %t 22 2>&1 | FileCheck %s --check-prefix=CHECK22 -// RUN: not %run %t 23 2>&1 | FileCheck %s --check-prefix=CHECK23 -// RUN: not %run %t 24 2>&1 | FileCheck %s --check-prefix=CHECK24 -// RUN: not %run %t 25 2>&1 | FileCheck %s --check-prefix=CHECK25 -// RUN: not %run %t 26 2>&1 | FileCheck %s --check-prefix=CHECK26 -// RUN: not %run %t 27 2>&1 | FileCheck %s --check-prefix=CHECK27 -// Parts of the test are too platform-specific: -// REQUIRES: x86_64-target-arch -// REQUIRES: shell -#include -#include -#include - -#include - -enum ReadOrWrite { Read = 0, Write = 1 }; - -struct S32 { - char x[32]; -}; - -template -void HeapBuferOverflow(int Idx, ReadOrWrite w) { - T *t = new T[100]; - static T sink; - if (w) - t[100 + Idx] = T(); - else - sink = t[100 + Idx]; - delete [] t; -} - -template -void HeapUseAfterFree(int Idx, ReadOrWrite w) { - T *t = new T[100]; - static T sink; - sink = t[0]; - delete [] t; - if (w) - t[Idx] = T(); - else - sink = t[Idx]; -} - -template -void StackBufferOverflow(int Idx, ReadOrWrite w) { - T t[100]; - static T sink; - sink = t[Idx]; - if (w) - t[100 + Idx] = T(); - else - sink = t[100 + Idx]; -} - -template -T *LeakStack() { - T t[100]; - static volatile T *x; - x = &t[0]; - return (T*)x; -} - -template -void StackUseAfterReturn(int Idx, ReadOrWrite w) { - static T sink; - T *t = LeakStack(); - if (w) - t[100 + Idx] = T(); - else - sink = t[100 + Idx]; -} - -char g1[100]; -short g2[100]; -int g4[100]; -int64_t g8[100]; -S32 gm[100]; - -void DoubleFree() { - int *x = new int; - static volatile int two = 2; - for (int i = 0; i < two; i++) - delete x; -} - -void StackOverflow(int Idx) { - int some_stack[10000]; - static volatile int *x; - x = &some_stack[0]; - if (Idx > 0) - StackOverflow(Idx - 1); -} - -void UseAfterPoison() { - int buf[100]; - __asan_poison_memory_region(buf, sizeof(buf)); - static volatile int sink; - sink = buf[42]; -} - -int main(int argc, char **argv) { - char arr[100]; - static volatile int zero = 0; - static volatile int *zero_ptr = 0; - static volatile int *wild_addr = (int*)0x10000000; // System-dependent. - if (argc != 2) return 1; - int kind = atoi(argv[1]); - switch (kind) { - case 1: HeapBuferOverflow(0, Read); break; - case 2: HeapBuferOverflow(0, Read); break; - case 3: HeapBuferOverflow(0, Write); break; - case 4: HeapBuferOverflow(2, Write); break; - case 5: HeapBuferOverflow(4, Write); break; - case 6: HeapUseAfterFree(0, Read); break; - case 7: HeapUseAfterFree(0, Write); break; - case 8: HeapUseAfterFree(0, Read); break; - case 9: HeapUseAfterFree(0, Write); break; - case 10: StackBufferOverflow(0, Write); break; - case 11: StackBufferOverflow(0, Read); break; - case 12: StackBufferOverflow(4, Write); break; - case 13: StackUseAfterReturn(0, Read); break; - case 14: StackUseAfterReturn(0, Write); break; - case 15: g1[zero + 100] = 0; break; - case 16: gm[0] = gm[zero + 100 + 1]; break; - case 17: DoubleFree(); break; - case 18: StackOverflow(1000000); break; - case 19: *zero_ptr = 0; break; - case 20: *wild_addr = 0; break; - case 21: zero = *wild_addr; break; - case 22: abort(); break; - case 23: ((void (*)(void))wild_addr)(); break; - case 24: delete (new int[10]); break; - case 25: free((char*)malloc(100) + 10); break; - case 26: memcpy(arr, arr+10, 20); break; - case 27: UseAfterPoison(); break; - // CHECK1: SCARINESS: 12 (1-byte-read-heap-buffer-overflow) - // CHECK2: SCARINESS: 17 (4-byte-read-heap-buffer-overflow) - // CHECK3: SCARINESS: 33 (2-byte-write-heap-buffer-overflow) - // CHECK4: SCARINESS: 52 (8-byte-write-heap-buffer-overflow-far-from-bounds) - // CHECK5: SCARINESS: 55 (multi-byte-write-heap-buffer-overflow-far-from-bounds) - // CHECK6: SCARINESS: 40 (1-byte-read-heap-use-after-free) - // CHECK7: SCARINESS: 46 (4-byte-write-heap-use-after-free) - // CHECK8: SCARINESS: 51 (8-byte-read-heap-use-after-free) - // CHECK9: SCARINESS: 55 (multi-byte-write-heap-use-after-free) - // CHECK10: SCARINESS: 46 (1-byte-write-stack-buffer-overflow) - // CHECK11: SCARINESS: 38 (8-byte-read-stack-buffer-overflow) - // CHECK12: SCARINESS: 61 (4-byte-write-stack-buffer-overflow-far-from-bounds) - // CHECK13: SCARINESS: 50 (1-byte-read-stack-use-after-return) - // CHECK14: SCARINESS: 65 (multi-byte-write-stack-use-after-return) - // CHECK15: SCARINESS: 31 (1-byte-write-global-buffer-overflow) - // CHECK16: SCARINESS: 36 (multi-byte-read-global-buffer-overflow-far-from-bounds) - // CHECK17: SCARINESS: 42 (double-free) - // CHECK18: SCARINESS: 10 (stack-overflow) - // CHECK19: SCARINESS: 10 (null-deref) - // CHECK20: SCARINESS: 30 (wild-addr-write) - // CHECK21: SCARINESS: 20 (wild-addr-read) - // CHECK22: SCARINESS: 10 (signal) - // CHECK23: SCARINESS: 60 (wild-jump) - // CHECK24: SCARINESS: 10 (alloc-dealloc-mismatch) - // CHECK25: SCARINESS: 40 (bad-free) - // CHECK26: SCARINESS: 10 (memcpy-param-overlap) - // CHECK27: SCARINESS: 27 (4-byte-read-use-after-poison) - } -} diff --git a/test/asan/TestCases/Linux/stack-trace-dlclose.cc b/test/asan/TestCases/Linux/stack-trace-dlclose.cc index 49c208978010..e604f1e4f73f 100644 --- a/test/asan/TestCases/Linux/stack-trace-dlclose.cc +++ b/test/asan/TestCases/Linux/stack-trace-dlclose.cc @@ -4,8 +4,7 @@ // RUN: %clangxx_asan -DSHARED %s -shared -o %T/stack_trace_dlclose.so -fPIC // RUN: %clangxx_asan -DSO_DIR=\"%T\" %s %libdl -o %t // RUN: %env_asan_opts=exitcode=0 %run %t 2>&1 | FileCheck %s -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime #include #include diff --git a/test/asan/TestCases/Linux/swapcontext_annotation.cc b/test/asan/TestCases/Linux/swapcontext_annotation.cc index 90aabaee205b..56e811942b88 100644 --- a/test/asan/TestCases/Linux/swapcontext_annotation.cc +++ b/test/asan/TestCases/Linux/swapcontext_annotation.cc @@ -1,12 +1,17 @@ // Check that ASan plays well with annotated makecontext/swapcontext. -// RUN: %clangxx_asan -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK +// RUN: %clangxx_asan -std=c++11 -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK +// RUN: %clangxx_asan -std=c++11 -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK +// RUN: %clangxx_asan -std=c++11 -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK + // // This test is too subtle to try on non-x86 arch for now. -// REQUIRES: x86_64-supported-target,i386-supported-target +// REQUIRES: x86-target-arch #include #include @@ -25,9 +30,12 @@ char *next_child_stack; const int kStackSize = 1 << 20; -void *main_thread_stack; +const void *main_thread_stack; size_t main_thread_stacksize; +const void *from_stack; +size_t from_stacksize; + __attribute__((noinline, noreturn)) void LongJump(jmp_buf env) { longjmp(env, 1); _exit(1); @@ -44,14 +52,18 @@ __attribute__((noinline)) void CallNoReturn() { void NextChild() { CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(nullptr, &from_stack, &from_stacksize); + + printf("NextChild from: %p %zu\n", from_stack, from_stacksize); char x[32] = {0}; // Stack gets poisoned. printf("NextChild: %p\n", x); CallNoReturn(); - __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); + __sanitizer_start_switch_fiber(nullptr, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); if (swapcontext(&next_child_context, &orig_context) < 0) { perror("swapcontext"); @@ -61,7 +73,9 @@ void NextChild() { void Child(int mode) { CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(nullptr, + &main_thread_stack, + &main_thread_stacksize); char x[32] = {0}; // Stack gets poisoned. printf("Child: %p\n", x); CallNoReturn(); @@ -70,21 +84,28 @@ void Child(int mode) { // something. // (c) Jump to another function which will then jump back to the main function if (mode == 0) { - __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); + __sanitizer_start_switch_fiber(nullptr, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); } else if (mode == 1) { - __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); + __sanitizer_start_switch_fiber(nullptr, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); if (swapcontext(&child_context, &orig_context) < 0) { perror("swapcontext"); _exit(1); } } else if (mode == 2) { + printf("NextChild stack: %p\n", next_child_stack); + getcontext(&next_child_context); next_child_context.uc_stack.ss_sp = next_child_stack; next_child_context.uc_stack.ss_size = kStackSize / 2; makecontext(&next_child_context, (void (*)())NextChild, 0); - __sanitizer_start_switch_fiber(next_child_context.uc_stack.ss_sp, + __sanitizer_start_switch_fiber(nullptr, + next_child_context.uc_stack.ss_sp, next_child_context.uc_stack.ss_size); CallNoReturn(); if (swapcontext(&child_context, &next_child_context) < 0) { @@ -105,7 +126,9 @@ int Run(int arg, int mode, char *child_stack) { } makecontext(&child_context, (void (*)())Child, 1, mode); CallNoReturn(); - __sanitizer_start_switch_fiber(child_context.uc_stack.ss_sp, + void* fake_stack_save; + __sanitizer_start_switch_fiber(&fake_stack_save, + child_context.uc_stack.ss_sp, child_context.uc_stack.ss_size); CallNoReturn(); if (swapcontext(&orig_context, &child_context) < 0) { @@ -113,8 +136,11 @@ int Run(int arg, int mode, char *child_stack) { _exit(1); } CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(fake_stack_save, + &from_stack, + &from_stacksize); CallNoReturn(); + printf("Main context from: %p %zu\n", from_stack, from_stacksize); // Touch childs's stack to make sure it's unpoisoned. for (int i = 0; i < kStackSize; i++) { @@ -125,17 +151,7 @@ int Run(int arg, int mode, char *child_stack) { void handler(int sig) { CallNoReturn(); } -void InitStackBounds() { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_getattr_np(pthread_self(), &attr); - pthread_attr_getstack(&attr, &main_thread_stack, &main_thread_stacksize); - pthread_attr_destroy(&attr); -} - int main(int argc, char **argv) { - InitStackBounds(); - // set up a signal that will spam and trigger __asan_handle_no_return at // tricky moments struct sigaction act = {}; @@ -162,12 +178,22 @@ int main(int argc, char **argv) { // CHECK-NOT: ASan is ignoring requested __asan_handle_no_return for (unsigned int i = 0; i < 30; ++i) { ret += Run(argc - 1, 0, stack); + // LOOPCHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] + // LOOPCHECK: Main context from: [[CHILD_STACK]] 524288 ret += Run(argc - 1, 1, stack); + // LOOPCHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] + // LOOPCHECK: Main context from: [[CHILD_STACK]] 524288 ret += Run(argc - 1, 2, stack); + // LOOPCHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] + // LOOPCHECK: NextChild stack: [[NEXT_CHILD_STACK:0x[0-9a-f]*]] + // LOOPCHECK: NextChild from: [[CHILD_STACK]] 524288 + // LOOPCHECK: Main context from: [[NEXT_CHILD_STACK]] 524288 ret += Run(argc - 1, 0, heap); ret += Run(argc - 1, 1, heap); ret += Run(argc - 1, 2, heap); + printf("Iteration %d passed\n", i); } + // CHECK: Test passed printf("Test passed\n"); diff --git a/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc b/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc new file mode 100644 index 000000000000..7176484ed21c --- /dev/null +++ b/test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc @@ -0,0 +1,40 @@ +// Test thread_local_quarantine_size_kb + +// RUN: %clangxx_asan %s -o %t +// RUN: %env_asan_opts=thread_local_quarantine_size_kb=256:verbosity=1 %run %t 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-VALUE +// RUN: %env_asan_opts=thread_local_quarantine_size_kb=64:quarantine_size_mb=64 %run %t 2>&1 | \ +// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD +// RUN: %env_asan_opts=thread_local_quarantine_size_kb=0:quarantine_size_mb=64 %run %t 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-NO-LOCAL-CACHE-HUGE-OVERHEAD + +#include +#include +#include +#include + +// The idea is allocate a lot of small blocks, totaling 5Mb of user memory +// total, and verify that quarantine does not incur too much memory overhead. +// There's always an overhead for red zones, shadow memory and such, but +// quarantine accounting should not significantly contribute to that. +static const int kNumAllocs = 20000; +static const int kAllocSize = 256; +static const size_t kHeapSizeLimit = 12 << 20; + +int main() { + size_t old_heap_size = __sanitizer_get_heap_size(); + for (int i = 0; i < kNumAllocs; i++) { + char *g = new char[kAllocSize]; + memset(g, -1, kAllocSize); + delete [] (g); + } + size_t new_heap_size = __sanitizer_get_heap_size(); + fprintf(stderr, "heap size: new: %zd old: %zd\n", new_heap_size, + old_heap_size); + if (new_heap_size - old_heap_size > kHeapSizeLimit) + fprintf(stderr, "Heap size limit exceeded"); +} + +// CHECK-VALUE: thread_local_quarantine_size_kb=256K +// CHECK-SMALL-LOCAL-CACHE-SMALL-OVERHEAD-NOT: Heap size limit exceeded +// CHECK-NO-LOCAL-CACHE-HUGE-OVERHEAD: Heap size limit exceeded diff --git a/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc index dd59e4a60774..cb9ca53e8a9a 100644 --- a/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc +++ b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc @@ -7,8 +7,8 @@ // RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so // RUN: %clangxx_asan -O0 %s %libdl -o %t // RUN: %env_asan_opts=symbolize=0 not %run %t 2>&1 | %asan_symbolize | FileCheck %s -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// UNSUPPORTED: x86_64h-darwin,x86_64-darwin +// REQUIRES: stable-runtime #if !defined(SHARED_LIB) #include diff --git a/test/asan/TestCases/Posix/coverage-fork.cc b/test/asan/TestCases/Posix/coverage-fork.cc index 799d71638a26..40ce72ef5003 100644 --- a/test/asan/TestCases/Posix/coverage-fork.cc +++ b/test/asan/TestCases/Posix/coverage-fork.cc @@ -3,7 +3,7 @@ // RUN: mkdir -p %T/coverage-fork && cd %T/coverage-fork // RUN: %env_asan_opts=coverage=1:coverage_direct=0:verbosity=1 %run %t 2>&1 | FileCheck %s // -// XFAIL: android +// UNSUPPORTED: android #include #include diff --git a/test/asan/TestCases/Posix/halt_on_error-signals.c b/test/asan/TestCases/Posix/halt_on_error-signals.c index 60916f6570fc..6bdf30bb4dd3 100644 --- a/test/asan/TestCases/Posix/halt_on_error-signals.c +++ b/test/asan/TestCases/Posix/halt_on_error-signals.c @@ -3,7 +3,7 @@ // RUN: %clang_asan -fsanitize-recover=address -pthread %s -o %t // // RUN: rm -f %t.log -// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 100 >%t.log 2>&1 || true +// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 100 >>%t.log 2>&1 || true // Collision will almost always get triggered but we still need to check the unlikely case: // RUN: FileCheck --check-prefix=CHECK-COLLISION %s < %t.log || FileCheck --check-prefix=CHECK-NO-COLLISION %s < %t.log diff --git a/test/asan/TestCases/Posix/halt_on_error-torture.cc b/test/asan/TestCases/Posix/halt_on_error-torture.cc index d3af1d027703..5d7eff06e34e 100644 --- a/test/asan/TestCases/Posix/halt_on_error-torture.cc +++ b/test/asan/TestCases/Posix/halt_on_error-torture.cc @@ -2,18 +2,21 @@ // // RUN: %clangxx_asan -fsanitize-recover=address -pthread %s -o %t // -// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 1 10 >1.txt 2>&1 +// RUN: rm -f 1.txt +// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 1 10 >>1.txt 2>&1 // RUN: FileCheck %s < 1.txt // RUN: [ $(grep -c 'ERROR: AddressSanitizer: use-after-poison' 1.txt) -eq 10 ] // RUN: FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt // // Collisions are unlikely but still possible so we need the ||. -// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 10 20 >10.txt 2>&1 || true +// RUN: rm -f 10.txt +// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 10 20 >>10.txt 2>&1 || true // RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 10.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 10.txt // // Collisions are unlikely but still possible so we need the ||. -// RUN: %env_asan_opts=halt_on_error=false %run %t 10 20 >10.txt 2>&1 || true -// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 10.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 10.txt +// RUN: rm -f 20.txt +// RUN: %env_asan_opts=halt_on_error=false %run %t 10 20 >>20.txt 2>&1 || true +// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 20.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 20.txt #include #include diff --git a/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc b/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc index 98b034812ef6..98ef851657b7 100644 --- a/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc +++ b/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc @@ -6,14 +6,16 @@ // RUN: %env_asan_opts=halt_on_error=false %run %t 2>&1 | FileCheck %s // // Check that we die after reaching different reports number threshold. -// RUN: %env_asan_opts=halt_on_error=false not %run %t 1 > %t1.log 2>&1 +// RUN: rm -f %t1.log +// RUN: %env_asan_opts=halt_on_error=false not %run %t 1 >> %t1.log 2>&1 // RUN: [ $(grep -c 'ERROR: AddressSanitizer: stack-buffer-overflow' %t1.log) -eq 25 ] // // Check suppress_equal_pcs=true behavior is equal to default one. // RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=true %run %t 2>&1 | FileCheck %s // // Check suppress_equal_pcs=false behavior isn't equal to default one. -// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t > %t2.log 2>&1 +// RUN: rm -f %t2.log +// RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t >> %t2.log 2>&1 // RUN: [ $(grep -c 'ERROR: AddressSanitizer: stack-buffer-overflow' %t2.log) -eq 30 ] #define ACCESS_ARRAY_FIVE_ELEMENTS(array, i) \ diff --git a/test/asan/TestCases/Posix/handle_abort_on_error.cc b/test/asan/TestCases/Posix/handle_abort_on_error.cc new file mode 100644 index 000000000000..fa8cdd4ce0c8 --- /dev/null +++ b/test/asan/TestCases/Posix/handle_abort_on_error.cc @@ -0,0 +1,9 @@ +// Regression test: this used to abort() in SIGABRT handler in an infinite loop. +// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=handle_abort=1,abort_on_error=1 not --crash %run %t 2>&1 | FileCheck %s + +#include + +int main() { + abort(); + // CHECK: ERROR: AddressSanitizer: ABRT +} diff --git a/test/asan/TestCases/Posix/no_asan_gen_globals.c b/test/asan/TestCases/Posix/no_asan_gen_globals.c new file mode 100644 index 000000000000..c686f83ac4a8 --- /dev/null +++ b/test/asan/TestCases/Posix/no_asan_gen_globals.c @@ -0,0 +1,12 @@ +// 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. + +// 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_ diff --git a/test/asan/TestCases/Posix/start-deactivated.cc b/test/asan/TestCases/Posix/start-deactivated.cc index 187ee5e549ef..9691404ebcea 100644 --- a/test/asan/TestCases/Posix/start-deactivated.cc +++ b/test/asan/TestCases/Posix/start-deactivated.cc @@ -2,8 +2,8 @@ // Main executable is uninstrumented, but linked to ASan runtime. The shared // library is instrumented. Memory errors before dlopen are not detected. -// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so -// RUN: %clangxx -O0 %s -c -o %t.o +// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -std=c++11 -fPIC -shared -o %t-so.so +// RUN: %clangxx -O0 %s -std=c++11 -c -o %t.o // RUN: %clangxx_asan -O0 %t.o %libdl -o %t // RUN: %env_asan_opts=start_deactivated=1,allocator_may_return_null=0 \ // RUN: ASAN_ACTIVATION_OPTIONS=allocator_may_return_null=1 not %run %t 2>&1 | FileCheck %s @@ -32,18 +32,25 @@ #include "sanitizer/asan_interface.h" -void test_malloc_shadow() { - char *p = (char *)malloc(100); - char *q = (char *)__asan_region_is_poisoned(p + 95, 8); - fprintf(stderr, "=%zd=\n", q ? q - (p + 95) : -1); - free(p); +constexpr unsigned nPtrs = 200; +char *ptrs[nPtrs]; + +void test_malloc_shadow(char *p, size_t sz, bool expect_redzones) { + assert((char *)__asan_region_is_poisoned(p - 1, sz + 1) == + (expect_redzones ? p - 1 : nullptr)); + assert((char *)__asan_region_is_poisoned(p, sz) == nullptr); + assert((char *)__asan_region_is_poisoned(p, sz + 1) == + (expect_redzones ? p + sz : nullptr)); } typedef void (*Fn)(); int main(int argc, char *argv[]) { - test_malloc_shadow(); - // CHECK: =-1= + // Before activation: no redzones. + for (size_t sz = 1; sz < nPtrs; ++sz) { + ptrs[sz] = (char *)malloc(sz); + test_malloc_shadow(ptrs[sz], sz, false); + } std::string path = std::string(argv[0]) + "-so.so"; void *dso = dlopen(path.c_str(), RTLD_NOW); @@ -52,9 +59,6 @@ int main(int argc, char *argv[]) { return 1; } - test_malloc_shadow(); - // CHECK: =5= - // After this line ASan is activated and starts detecting errors. void *fn = dlsym(dso, "do_another_bad_thing"); if (!fn) { @@ -62,6 +66,19 @@ int main(int argc, char *argv[]) { return 1; } + // After activation: redzones. + { + char *p = (char *)malloc(100); + test_malloc_shadow(p, 100, true); + free(p); + } + + // Pre-existing allocations got redzones, too. + for (size_t sz = 1; sz < nPtrs; ++sz) { + test_malloc_shadow(ptrs[sz], sz, true); + free(ptrs[sz]); + } + // Test that ASAN_ACTIVATION_OPTIONS=allocator_may_return_null=1 has effect. void *p = malloc((unsigned long)-2); assert(!p); diff --git a/test/asan/TestCases/Windows/bind_io_completion_callback.cc b/test/asan/TestCases/Windows/bind_io_completion_callback.cc index 44b92ab91465..ef7e45867ede 100644 --- a/test/asan/TestCases/Windows/bind_io_completion_callback.cc +++ b/test/asan/TestCases/Windows/bind_io_completion_callback.cc @@ -1,11 +1,6 @@ // Make sure we can throw exceptions from work items executed via // BindIoCompletionCallback. // -// Clang doesn't support exceptions on Windows yet, so for the time being we -// build this program in two parts: the code with exceptions is built with CL, -// the rest is built with Clang. This represents the typical scenario when we -// build a large project using "clang-cl -fallback -fsanitize=address". -// // RUN: %clangxx_asan %s -o %t.exe // RUN: %run %t.exe 2>&1 | FileCheck %s diff --git a/test/asan/TestCases/Windows/coverage-dll-stdio.cc b/test/asan/TestCases/Windows/coverage-dll-stdio.cc new file mode 100644 index 000000000000..5e12e3855449 --- /dev/null +++ b/test/asan/TestCases/Windows/coverage-dll-stdio.cc @@ -0,0 +1,16 @@ +// Test that coverage and MSVC CRT stdio work from a DLL. This ensures that the +// __local_stdio_printf_options function isn't instrumented for coverage. + +// RUN: rm -rf %t && mkdir %t && cd %t +// RUN: %clang_cl_asan -fsanitize-coverage=func -O0 %p/dll_host.cc -Fet.exe +// RUN: %clang_cl_asan -fsanitize-coverage=func -LD -O0 %s -Fet.dll +// RUN: %run ./t.exe t.dll 2>&1 | FileCheck %s + +#include + +extern "C" __declspec(dllexport) +int test_function() { + printf("hello world\n"); + // CHECK: hello world + return 0; +} diff --git a/test/asan/TestCases/Windows/default_options.cc b/test/asan/TestCases/Windows/default_options.cc deleted file mode 100644 index 6e0a28f33692..000000000000 --- a/test/asan/TestCases/Windows/default_options.cc +++ /dev/null @@ -1,18 +0,0 @@ -// RUN: %clangxx_asan -O2 %s -o %t -// RUN: %run %t 2>&1 | FileCheck %s - -// FIXME: merge this with the common default_options test when we can run common -// tests on Windows. - -const char *kAsanDefaultOptions="verbosity=1 help=1"; - -extern "C" -__attribute__((no_sanitize_address)) -const char *__asan_default_options() { - // CHECK: Available flags for AddressSanitizer: - return kAsanDefaultOptions; -} - -int main() { - return 0; -} diff --git a/test/asan/TestCases/Windows/delay_dbghelp.cc b/test/asan/TestCases/Windows/delay_dbghelp.cc new file mode 100644 index 000000000000..81cd2d389c3b --- /dev/null +++ b/test/asan/TestCases/Windows/delay_dbghelp.cc @@ -0,0 +1,18 @@ +// Build an executable with ASan, then extract the DLLs that it depends on. +// RUN: %clang_cl_asan %s -Fe%t.exe +// RUN: llvm-readobj -coff-imports %t.exe | grep Name: | sed -e 's/ *Name: *//' > %t +// +// Make sure the binary doesn't depend on dbghelp directly. +// RUN: not grep dbghelp.dll %t +// +// Make sure any clang_rt DLLs it depends on don't depend on dbghelp. In the +// static build, there won't be any clang_rt DLLs. +// RUN: not grep cl""ang_rt %t || \ +// RUN: grep cl""ang_rt %t | xargs which | \ +// RUN: xargs llvm-readobj -coff-imports | not grep dbghelp.dll %t + +extern "C" int puts(const char *); + +int main() { + puts("main"); +} diff --git a/test/asan/TestCases/Windows/dll_global_dead_strip.c b/test/asan/TestCases/Windows/dll_global_dead_strip.c new file mode 100644 index 000000000000..2664f5baff6c --- /dev/null +++ b/test/asan/TestCases/Windows/dll_global_dead_strip.c @@ -0,0 +1,28 @@ +// RUN: %clang_cl_asan -O0 %p/dll_host.cc -Fe%t +// +// RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll +// RUN: %env_asan_opts=report_globals=2 %run %t %t.dll 2>&1 | FileCheck %s --check-prefix=NOSTRIP +// RUN: %clang_cl_asan -LD -O2 %s -Fe%t.dll -link -opt:ref +// RUN: %env_asan_opts=report_globals=2 %run %t %t.dll 2>&1 | FileCheck %s --check-prefix=STRIP + +#include + +int dead_global = 42; +int live_global = 0; + +__declspec(dllexport) +int test_function() { + puts("main"); + return live_global; +} + +// Check that our global registration scheme works with MSVC's linker dead +// stripping (/OPT:REF). + +// NOSTRIP: Added Global{{.*}}name=dead_global +// NOSTRIP: Added Global{{.*}}name=live_global +// NOSTRIP: main + +// STRIP-NOT: Added Global{{.*}}name=dead_global +// STRIP: Added Global{{.*}}name=live_global +// STRIP: main diff --git a/test/asan/TestCases/Windows/dll_host.cc b/test/asan/TestCases/Windows/dll_host.cc index 71721fe29e88..6a029c96d4d8 100644 --- a/test/asan/TestCases/Windows/dll_host.cc +++ b/test/asan/TestCases/Windows/dll_host.cc @@ -5,20 +5,41 @@ // RUN: %clang_cl_asan -O0 %s -Fe%t // // Get the list of ASan wrappers exported by the main module RTL: -// RUN: dumpbin /EXPORTS %t | grep -o "__asan_wrap[^ ]*" | grep -v @ | sort | uniq > %t.exported_wrappers +// note: The mangling decoration (i.e. @4 )is removed because calling convention +// differ from 32-bit and 64-bit. +// RUN: dumpbin /EXPORTS %t | grep -o "__asan_wrap[^ ]*" | sed -e s/@.*// > %t.exported_wrappers1 // FIXME: we should really check the other __asan exports too. -// RUN: dumpbin /EXPORTS %t | grep -o "__sanitizer_[^ ]*" | grep -v @ | sort | uniq >> %t.exported_wrappers +// RUN: dumpbin /EXPORTS %t | grep -o "__sanitizer_[^ ]*" | sed -e s/@.*// > %t.exported_wrappers2 // // Get the list of ASan wrappers imported by the DLL RTL: // [BEWARE: be really careful with the sed commands, as this test can be run // from different environemnts with different shells and seds] -// RUN: grep INTERCEPT_LIBRARY_FUNCTION %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed -e s/.*(/__asan_wrap_/ | sed -e s/).*// | sort | uniq > %t.dll_imports -// RUN: grep "^INTERFACE_FUNCTION.*sanitizer" %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed -e s/.*(// | sed -e s/).*// | sort | uniq >> %t.dll_imports +// RUN: grep INTERCEPT_LIBRARY_FUNCTION %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed -e s/.*(/__asan_wrap_/ | sed -e s/).*// > %t.dll_imports1 +// RUN: grep "^INTERFACE_FUNCTION.*sanitizer" %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed -e s/.*(// | sed -e s/).*// > %t.dll_imports2 +// +// Add functions interecepted in asan_malloc.win.cc and asan_win.cc. +// RUN: grep '[I]MPORT:' %s | sed -e 's/.*[I]MPORT: //' > %t.dll_imports3 +// IMPORT: __asan_wrap_HeapAlloc +// IMPORT: __asan_wrap_HeapFree +// IMPORT: __asan_wrap_HeapReAlloc +// IMPORT: __asan_wrap_HeapSize +// IMPORT: __asan_wrap_CreateThread +// IMPORT: __asan_wrap_RaiseException +// IMPORT: __asan_wrap_RtlRaiseException +// +// The exception handlers differ in 32-bit and 64-bit, so we ignore them: +// RUN: grep '[E]XPORT:' %s | sed -e 's/.*[E]XPORT: //' > %t.exported_wrappers3 +// EXPORT: __asan_wrap__except_handler3 +// EXPORT: __asan_wrap__except_handler4 +// EXPORT: __asan_wrap___C_specific_handler +// +// RUN: cat %t.dll_imports1 %t.dll_imports2 %t.dll_imports3 | sort | uniq > %t.dll_imports-sorted +// RUN: cat %t.exported_wrappers1 %t.exported_wrappers2 %t.exported_wrappers3 | sort | uniq > %t.exported_wrappers-sorted // // Now make sure the DLL thunk imports everything: // RUN: echo // RUN: echo "=== NOTE === If you see a mismatch below, please update asan_win_dll_thunk.cc" -// RUN: diff %t.dll_imports %t.exported_wrappers +// RUN: diff %t.dll_imports-sorted %t.exported_wrappers-sorted // REQUIRES: asan-static-runtime #include diff --git a/test/asan/TestCases/Windows/dll_intercept_memchr.cc b/test/asan/TestCases/Windows/dll_intercept_memchr.cc index 1435bdc50127..4f794a212706 100644 --- a/test/asan/TestCases/Windows/dll_intercept_memchr.cc +++ b/test/asan/TestCases/Windows/dll_intercept_memchr.cc @@ -2,6 +2,12 @@ // RUN: %clang_cl_asan -LD -O0 %s -Fe%t.dll // RUN: not %run %t %t.dll 2>&1 | FileCheck %s +// On windows 64-bit, the memchr function is written in assembly and is not +// hookable with the interception library. There is not enough padding before +// the function and there is a short jump on the second instruction which +// doesn't not allow enough space to encode a 64-bit indirect jump. +// UNSUPPORTED: x86_64-windows + #include extern "C" __declspec(dllexport) diff --git a/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc b/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc index c5f44df3faaf..4e28905923cc 100644 --- a/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc +++ b/test/asan/TestCases/Windows/dll_intercept_memcpy_indirect.cc @@ -24,7 +24,7 @@ int test_function() { call_memcpy(&memcpy, buff2, buff1, 6); // CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] // CHECK: WRITE of size 6 at [[ADDR]] thread T0 -// CHECK-NEXT: __asan_{{.*}}memcpy +// CHECK-NEXT: __asan_{{.*}}mem{{.*}} // CHECK-NEXT: call_memcpy // CHECK-NEXT: test_function {{.*}}dll_intercept_memcpy_indirect.cc:[[@LINE-5]] // CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame diff --git a/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc b/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc index 8306a737bfff..b514c994c1df 100644 --- a/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc +++ b/test/asan/TestCases/Windows/dll_operator_array_new_with_dtor_left_oob.cc @@ -10,7 +10,7 @@ struct C { extern "C" __declspec(dllexport) int test_function() { C *buffer = new C[42]; - buffer[-2].x = 42; + buffer[-(1 + sizeof(void*) / 4)].x = 42; // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] // CHECK: WRITE of size 4 at [[ADDR]] thread T0 // CHECK-NEXT: test_function {{.*}}dll_operator_array_new_with_dtor_left_oob.cc:[[@LINE-3]] @@ -19,7 +19,7 @@ int test_function() { // FIXME: Currently it says "4 bytes ... left of 172-byte region", // should be "8 bytes ... left of 168-byte region", see // https://code.google.com/p/address-sanitizer/issues/detail?id=314 -// CHECK: [[ADDR]] is located {{.*}} bytes to the left of 172-byte region +// CHECK: [[ADDR]] is located {{.*}} bytes to the left of {{(172|176)}}-byte region // FIXME: Should get rid of the malloc/free frames called from the inside of // operator new/delete in DLLs when using -MT CRT. // FIXME: The operator new frame should have []. diff --git a/test/asan/TestCases/Windows/free_hook_realloc.cc b/test/asan/TestCases/Windows/free_hook_realloc.cc index 297218bf8e99..11e8c9975cf3 100644 --- a/test/asan/TestCases/Windows/free_hook_realloc.cc +++ b/test/asan/TestCases/Windows/free_hook_realloc.cc @@ -5,6 +5,9 @@ // FIXME: merge this with the common free_hook_realloc test when we can run // common tests on Windows. +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + #include #include #include diff --git a/test/asan/TestCases/Windows/global_dead_strip.c b/test/asan/TestCases/Windows/global_dead_strip.c new file mode 100644 index 000000000000..e68549050be6 --- /dev/null +++ b/test/asan/TestCases/Windows/global_dead_strip.c @@ -0,0 +1,23 @@ +// RUN: %clang_cl_asan /O0 %s /Fe%t.exe +// RUN: %env_asan_opts=report_globals=2 %t.exe 2>&1 | FileCheck %s --check-prefix=NOSTRIP +// RUN: %clang_cl_asan /O2 %s /Fe%t.exe -link -opt:ref +// RUN: %env_asan_opts=report_globals=2 %t.exe 2>&1 | FileCheck %s --check-prefix=STRIP + +#include +int dead_global = 42; +int live_global = 0; +int main() { + puts("main"); + return live_global; +} + +// Check that our global registration scheme works with MSVC's linker dead +// stripping (/OPT:REF). + +// NOSTRIP: Added Global{{.*}}name=dead_global +// NOSTRIP: Added Global{{.*}}name=live_global +// NOSTRIP: main + +// STRIP-NOT: Added Global{{.*}}name=dead_global +// STRIP: Added Global{{.*}}name=live_global +// STRIP: main diff --git a/test/asan/TestCases/Windows/intercept_memcpy.cc b/test/asan/TestCases/Windows/intercept_memcpy.cc index 9ee984b1873d..6e45e7fc6b30 100644 --- a/test/asan/TestCases/Windows/intercept_memcpy.cc +++ b/test/asan/TestCases/Windows/intercept_memcpy.cc @@ -22,8 +22,8 @@ int main() { call_memcpy(&memcpy, buff2, buff1, 6); // CHECK: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] // CHECK: WRITE of size 6 at [[ADDR]] thread T0 -// CHECK-NEXT: __asan_{{.*}}memcpy -// CHECK-NEXT: call_memcpy +// CHECK-NEXT: __asan_{{.*}}mem{{.*}} +// CHECK-NEXT: call_mem{{.*}} // CHECK-NEXT: main {{.*}}intercept_memcpy.cc:[[@LINE-5]] // CHECK: Address [[ADDR]] is located in stack of thread T0 at offset {{.*}} in frame // CHECK-NEXT: #0 {{.*}} main diff --git a/test/asan/TestCases/Windows/on_error_callback.cc b/test/asan/TestCases/Windows/on_error_callback.cc deleted file mode 100644 index 9e690a342b56..000000000000 --- a/test/asan/TestCases/Windows/on_error_callback.cc +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s - -// FIXME: merge this with the common on_error_callback test when we can run -// common tests on Windows. - -#include -#include - -extern "C" -void __asan_on_error() { - fprintf(stderr, "__asan_on_error called"); - fflush(0); -} - -int main() { - char *x = (char*)malloc(10 * sizeof(char)); - free(x); - return x[5]; - // CHECK: __asan_on_error called -} diff --git a/test/asan/TestCases/Windows/oom.cc b/test/asan/TestCases/Windows/oom.cc index 3475af79e6a4..59cc7ed0e9d1 100644 --- a/test/asan/TestCases/Windows/oom.cc +++ b/test/asan/TestCases/Windows/oom.cc @@ -1,5 +1,6 @@ // RUN: %clang_cl_asan -O0 %s -Fe%t // RUN: not %run %t 2>&1 | FileCheck %s +// REQUIRES: asan-32-bits #include diff --git a/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc b/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc index 63f2929bd89b..aae9d5ec82be 100644 --- a/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc +++ b/test/asan/TestCases/Windows/operator_array_new_with_dtor_left_oob.cc @@ -8,7 +8,7 @@ struct C { int main() { C *buffer = new C[42]; - buffer[-2].x = 42; + buffer[-(1 + sizeof(void*) / 4)].x = 42; // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] // CHECK: WRITE of size 4 at [[ADDR]] thread T0 // CHECK-NEXT: {{#0 .* main .*operator_array_new_with_dtor_left_oob.cc}}:[[@LINE-3]] @@ -16,7 +16,7 @@ int main() { // FIXME: Currently it says "4 bytes ... left of 172-byte region", // should be "8 bytes ... left of 168-byte region", see // https://code.google.com/p/address-sanitizer/issues/detail?id=314 -// CHECK: [[ADDR]] is located {{.*}} bytes to the left of 172-byte region +// CHECK: [[ADDR]] is located {{.*}} bytes to the left of {{(172|176)}}-byte region // CHECK-LABEL: allocated by thread T0 here: // FIXME: The 'operator new' frame should have []. // CHECK-NEXT: {{#0 .* operator new}} diff --git a/test/asan/TestCases/Windows/queue_user_work_item.cc b/test/asan/TestCases/Windows/queue_user_work_item.cc index 2a0b622f6218..2a8beb828ee2 100644 --- a/test/asan/TestCases/Windows/queue_user_work_item.cc +++ b/test/asan/TestCases/Windows/queue_user_work_item.cc @@ -1,11 +1,6 @@ // Make sure we can throw exceptions from work items executed via // QueueUserWorkItem. // -// Clang doesn't support exceptions on Windows yet, so for the time being we -// build this program in two parts: the code with exceptions is built with CL, -// the rest is built with Clang. This represents the typical scenario when we -// build a large project using "clang-cl -fallback -fsanitize=address". -// // RUN: %clangxx_asan %s -o %t.exe // RUN: %run %t.exe 2>&1 | FileCheck %s diff --git a/test/asan/TestCases/Windows/queue_user_work_item_report.cc b/test/asan/TestCases/Windows/queue_user_work_item_report.cc index e500a919fdae..26bd5e09d3eb 100644 --- a/test/asan/TestCases/Windows/queue_user_work_item_report.cc +++ b/test/asan/TestCases/Windows/queue_user_work_item_report.cc @@ -12,8 +12,6 @@ DWORD CALLBACK work_item(LPVOID) { // CHECK: AddressSanitizer: stack-buffer-underflow on address [[ADDR:0x[0-9a-f]+]] // CHECK: WRITE of size 1 at [[ADDR]] thread T1 // CHECK: {{#0 .* work_item.*queue_user_work_item_report.cc}}:[[@LINE-3]] -// CHECK: Address [[ADDR]] is located in stack of thread T1 at offset {{.*}} in frame -// CHECK: work_item SetEvent(done); return 0; } diff --git a/test/asan/TestCases/Windows/report_after_syminitialize.cc b/test/asan/TestCases/Windows/report_after_syminitialize.cc index 20bf69514179..eec50297478c 100644 --- a/test/asan/TestCases/Windows/report_after_syminitialize.cc +++ b/test/asan/TestCases/Windows/report_after_syminitialize.cc @@ -4,6 +4,8 @@ #include #include +#pragma comment(lib, "dbghelp") + int main() { // Make sure the RTL recovers from "no options enabled" dbghelp setup. SymSetOptions(0); @@ -16,8 +18,8 @@ int main() { // CHECK: ERROR: AddressSanitizer: access-violation on unknown address // CHECK: The signal is caused by a WRITE memory access. // CHECK: Hint: address points to the zero page. - // CHECK-NEXT: {{WARNING: Failed to use and restart external symbolizer}} - // CHECK-NEXT: {{WARNING: .*DbgHelp}} + // CHECK: {{WARNING: .*DbgHelp}} + // CHECK: {{WARNING: Failed to use and restart external symbolizer}} // CHECK: {{#0 0x.* in main.*report_after_syminitialize.cc:}}[[@LINE-6]] // CHECK: AddressSanitizer can not provide additional info. } diff --git a/test/asan/TestCases/Windows/shadow_conflict_32.cc b/test/asan/TestCases/Windows/shadow_conflict_32.cc new file mode 100644 index 000000000000..7c6d94b37483 --- /dev/null +++ b/test/asan/TestCases/Windows/shadow_conflict_32.cc @@ -0,0 +1,29 @@ +// Load this DLL at the default 32-bit ASan shadow base, and test how we dump +// the process memory layout. +// REQUIRES: asan-32-bits +// +// RUN: %clang_cl_asan -DBUILD_DLL -LD %s -Fe%t_dll.dll -link -base:0x30000000 -fixed -dynamicbase:no +// RUN: %clang_cl_asan %s -Fe%t.exe -link %t_dll.lib +// RUN: not %run %t.exe 2>&1 | FileCheck %s + +#ifndef BUILD_DLL +#include + +extern "C" __declspec(dllimport) int test_function(); + +int main() { + fprintf(stderr, "should have failed to initialize, DLL got loaded near 0x%p\n", + (void *)&test_function); +} + +#else +extern "C" __declspec(dllexport) int test_function() { return 0; } +#endif + +// CHECK: =={{[0-9]+}}==Shadow memory range interleaves with an existing memory mapping. ASan cannot proceed correctly. ABORTING. +// CHECK: =={{[0-9]+}}==ASan shadow was supposed to be located in the [0x2fff0000-0x3fffffff] range. +// CHECK: =={{[0-9]+}}==Dumping process modules + +// CHECK-DAG: {{0x30000000-0x300.....}} {{.*}}\shadow_conflict_32.cc.tmp_dll.dll +// CHECK-DAG: {{0x........-0x........}} {{.*}}\shadow_conflict_32.cc.tmp.exe +// CHECK-DAG: {{0x........-0x........}} {{.*}}\ntdll.dll diff --git a/test/asan/TestCases/Windows/shadow_mapping_failure.cc b/test/asan/TestCases/Windows/shadow_mapping_failure.cc index 9b83947442ed..510f169401dc 100644 --- a/test/asan/TestCases/Windows/shadow_mapping_failure.cc +++ b/test/asan/TestCases/Windows/shadow_mapping_failure.cc @@ -1,5 +1,6 @@ // RUN: %clang_cl_asan -O0 %s -Fe%t // RUN: not %run %t 2>&1 | FileCheck %s +// REQUIRES: asan-32-bits #include diff --git a/test/asan/TestCases/Windows/tls_init.cc b/test/asan/TestCases/Windows/tls_init.cc new file mode 100644 index 000000000000..c29c4a377834 --- /dev/null +++ b/test/asan/TestCases/Windows/tls_init.cc @@ -0,0 +1,51 @@ +// RUN: %clang_cl_asan %s -Fe%t.exe +// RUN: %run %t.exe | FileCheck %s + +// CHECK: my_thread_callback +// CHECK: ran_before_main: 1 + +#include +#include +#include + +#pragma comment (lib, "dbghelp") + +static bool ran_before_main = false; + +extern "C" void __asan_init(void); + +static void NTAPI /*__attribute__((no_sanitize_address))*/ +my_thread_callback(PVOID module, DWORD reason, PVOID reserved) { + ran_before_main = true; + static const char str[] = "my_thread_callback\n"; + + // Fail the test if we aren't called for the expected reason or we can't write + // stdout. + if (reason != DLL_PROCESS_ATTACH) + return; + HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); + if (!out || out == INVALID_HANDLE_VALUE) + return; + + DWORD written = 0; + WriteFile(out, &str[0], sizeof(str), &written, NULL); +} + +extern "C" { +#pragma const_seg(".CRT$XLC") +extern const PIMAGE_TLS_CALLBACK p_thread_callback; +const PIMAGE_TLS_CALLBACK p_thread_callback = my_thread_callback; +#pragma const_seg() +} + +#ifdef _WIN64 +#pragma comment(linker, "/INCLUDE:_tls_used") +#pragma comment(linker, "/INCLUDE:p_thread_callback") +#else +#pragma comment(linker, "/INCLUDE:__tls_used") +#pragma comment(linker, "/INCLUDE:_p_thread_callback") +#endif + +int main() { + printf("ran_before_main: %d\n", ran_before_main); +} diff --git a/test/asan/TestCases/Windows/unsymbolized.cc b/test/asan/TestCases/Windows/unsymbolized.cc index e44b4bbabb87..5854dc56d2e9 100644 --- a/test/asan/TestCases/Windows/unsymbolized.cc +++ b/test/asan/TestCases/Windows/unsymbolized.cc @@ -20,6 +20,6 @@ int do_uaf(void) { free(x); return x[5]; // CHECK: AddressSanitizer: heap-use-after-free - // CHECK: #0 {{0x[a-f0-9]+ \(.*[\\/]unsymbolized.cc.*.exe\+0x40[a-f0-9]{4}\)}} - // CHECK: #1 {{0x[a-f0-9]+ \(.*[\\/]unsymbolized.cc.*.exe\+0x40[a-f0-9]{4}\)}} + // CHECK: #0 {{0x[a-f0-9]+ \(.*[\\/]unsymbolized.cc.*.exe\+(0x40|0x14000)[a-f0-9]{4}\)}} + // CHECK: #1 {{0x[a-f0-9]+ \(.*[\\/]unsymbolized.cc.*.exe\+(0x40|0x14000)[a-f0-9]{4}\)}} } diff --git a/test/asan/TestCases/alloca_big_alignment.cc b/test/asan/TestCases/alloca_big_alignment.cc index 2ede3f949b24..0b49424bfae5 100644 --- a/test/asan/TestCases/alloca_big_alignment.cc +++ b/test/asan/TestCases/alloca_big_alignment.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s // diff --git a/test/asan/TestCases/alloca_detect_custom_size_.cc b/test/asan/TestCases/alloca_detect_custom_size_.cc index 2b0f573de3d0..271359bf7097 100644 --- a/test/asan/TestCases/alloca_detect_custom_size_.cc +++ b/test/asan/TestCases/alloca_detect_custom_size_.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s // diff --git a/test/asan/TestCases/alloca_instruments_all_paddings.cc b/test/asan/TestCases/alloca_instruments_all_paddings.cc index e2c7fafb193e..5bf6f80ac4ce 100644 --- a/test/asan/TestCases/alloca_instruments_all_paddings.cc +++ b/test/asan/TestCases/alloca_instruments_all_paddings.cc @@ -1,5 +1,5 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t -// RUN: %clangxx_asan -O3 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t +// RUN: %clangxx_asan -O3 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: %run %t 2>&1 // diff --git a/test/asan/TestCases/alloca_loop_unpoisoning.cc b/test/asan/TestCases/alloca_loop_unpoisoning.cc index 539279292674..1efada10979a 100644 --- a/test/asan/TestCases/alloca_loop_unpoisoning.cc +++ b/test/asan/TestCases/alloca_loop_unpoisoning.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: %run %t 2>&1 // // REQUIRES: stable-runtime diff --git a/test/asan/TestCases/alloca_overflow_partial.cc b/test/asan/TestCases/alloca_overflow_partial.cc index 590f35465dad..afac40ce6b9a 100644 --- a/test/asan/TestCases/alloca_overflow_partial.cc +++ b/test/asan/TestCases/alloca_overflow_partial.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s // diff --git a/test/asan/TestCases/alloca_overflow_right.cc b/test/asan/TestCases/alloca_overflow_right.cc index caec846838ef..615dd1485be1 100644 --- a/test/asan/TestCases/alloca_overflow_right.cc +++ b/test/asan/TestCases/alloca_overflow_right.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s // diff --git a/test/asan/TestCases/alloca_safe_access.cc b/test/asan/TestCases/alloca_safe_access.cc index 240454fd55e4..1cd0dada7b45 100644 --- a/test/asan/TestCases/alloca_safe_access.cc +++ b/test/asan/TestCases/alloca_safe_access.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: %run %t 2>&1 // diff --git a/test/asan/TestCases/alloca_underflow_left.cc b/test/asan/TestCases/alloca_underflow_left.cc index 6e7061f7cfe2..8720e8cce24b 100644 --- a/test/asan/TestCases/alloca_underflow_left.cc +++ b/test/asan/TestCases/alloca_underflow_left.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s // diff --git a/test/asan/TestCases/alloca_vla_interact.cc b/test/asan/TestCases/alloca_vla_interact.cc index 3873c3fceea8..4717c9d977ed 100644 --- a/test/asan/TestCases/alloca_vla_interact.cc +++ b/test/asan/TestCases/alloca_vla_interact.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: %run %t 2>&1 // // REQUIRES: stable-runtime diff --git a/test/asan/TestCases/atexit_stats.cc b/test/asan/TestCases/atexit_stats.cc index 42a3fbf23f55..f0b5830b405a 100644 --- a/test/asan/TestCases/atexit_stats.cc +++ b/test/asan/TestCases/atexit_stats.cc @@ -2,9 +2,9 @@ // RUN: %clangxx_asan -O3 %s -o %t // RUN: %env_asan_opts=atexit=1:print_stats=1 %run %t 2>&1 | FileCheck %s // -// No atexit output on Android due to +// No atexit output in older versions of Android due to // https://code.google.com/p/address-sanitizer/issues/detail?id=263 -// XFAIL: android +// UNSUPPORTED: android #include #if !defined(__APPLE__) && !defined(__FreeBSD__) diff --git a/test/asan/TestCases/coverage-order-pcs.cc b/test/asan/TestCases/coverage-order-pcs.cc index dcab69474a6c..e81c91045455 100644 --- a/test/asan/TestCases/coverage-order-pcs.cc +++ b/test/asan/TestCases/coverage-order-pcs.cc @@ -19,7 +19,7 @@ // // RUN: rm -rf $DIR // Ordering works only in 64-bit mode for now. -// REQUIRES: asan-64-bits +// REQUIRES: asan-64-bits, shell // UNSUPPORTED: android #include diff --git a/test/asan/TestCases/coverage-pc-buffer.cc b/test/asan/TestCases/coverage-pc-buffer.cc deleted file mode 100644 index 5895a5c45d15..000000000000 --- a/test/asan/TestCases/coverage-pc-buffer.cc +++ /dev/null @@ -1,65 +0,0 @@ -// Test __sanitizer_coverage_pc_buffer(). - -// RUN: %clangxx_asan -fsanitize-coverage=edge %s -o %t && %run %t - -// UNSUPPORTED: android - -#include -#include -#include - -static volatile int sink; -__attribute__((noinline)) void bar() { sink = 2; } -__attribute__((noinline)) void foo() { sink = 1; } - -void assertNotZeroPcs(uintptr_t *buf, uintptr_t size) { - assert(buf); - for (uintptr_t i = 0; i < size; ++i) - assert(buf[i]); -} - -int main() { - { - uintptr_t *buf = NULL; - uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf); - assertNotZeroPcs(buf, sz); - assert(sz); - } - - { - uintptr_t *buf = NULL; - uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf); - // call functions for the first time. - foo(); - bar(); - uintptr_t *buf1 = NULL; - uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1); - assertNotZeroPcs(buf1, sz1); - assert(buf1 == buf); - assert(sz1 > sz); - } - - { - uintptr_t *buf = NULL; - uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf); - // second call shouldn't increase coverage. - bar(); - uintptr_t *buf1 = NULL; - uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1); - assertNotZeroPcs(buf1, sz1); - assert(buf1 == buf); - assert(sz1 == sz); - } - - { - uintptr_t *buf = NULL; - uintptr_t sz = __sanitizer_get_coverage_pc_buffer(&buf); - // reset coverage to 0. - __sanitizer_reset_coverage(); - uintptr_t *buf1 = NULL; - uintptr_t sz1 = __sanitizer_get_coverage_pc_buffer(&buf1); - assertNotZeroPcs(buf1, sz1); - assert(buf1 == buf); - assert(sz1 < sz); - } -} diff --git a/test/asan/TestCases/coverage-tracing.cc b/test/asan/TestCases/coverage-tracing.cc index b7755f847dbb..278cfb141f07 100644 --- a/test/asan/TestCases/coverage-tracing.cc +++ b/test/asan/TestCases/coverage-tracing.cc @@ -24,7 +24,7 @@ // RUN: not diff b.points bf.points // RUN: rm -rf %T/coverage-tracing // -// REQUIRES: asan-64-bits +// REQUIRES: asan-64-bits, shell // UNSUPPORTED: android #include diff --git a/test/asan/TestCases/debug_double_free.cc b/test/asan/TestCases/debug_double_free.cc new file mode 100644 index 000000000000..c3699b9762d8 --- /dev/null +++ b/test/asan/TestCases/debug_double_free.cc @@ -0,0 +1,50 @@ +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + +// If we use %p with MSVC, it comes out all upper case. Use %08x to get +// lowercase hex. +#ifdef _MSC_VER +# ifdef _WIN64 +# define PTR_FMT "0x%08llx" +# else +# define PTR_FMT "0x%08x" +# endif +#else +# define PTR_FMT "%p" +#endif + +char *heap_ptr; + +int main() { + // Disable stderr buffering. Needed on Windows. + setvbuf(stderr, NULL, _IONBF, 0); + + heap_ptr = (char *)malloc(10); + fprintf(stderr, "heap_ptr: " PTR_FMT "\n", heap_ptr); + // CHECK: heap_ptr: 0x[[ADDR:[0-9a-f]+]] + + free(heap_ptr); + free(heap_ptr); // BOOM + return 0; +} + +void __asan_on_error() { + int present = __asan_report_present(); + void *addr = __asan_get_report_address(); + const char *description = __asan_get_report_description(); + + fprintf(stderr, "%s\n", (present == 1) ? "report present" : ""); + // CHECK: report present + fprintf(stderr, "addr: " PTR_FMT "\n", addr); + // CHECK: addr: {{0x0*}}[[ADDR]] + fprintf(stderr, "description: %s\n", description); + // CHECK: description: double-free +} + +// CHECK: AddressSanitizer: attempting double-free on {{0x0*}}[[ADDR]] in thread T0 diff --git a/test/asan/TestCases/debug_mapping.cc b/test/asan/TestCases/debug_mapping.cc index bd05f6aab353..40083f02853f 100644 --- a/test/asan/TestCases/debug_mapping.cc +++ b/test/asan/TestCases/debug_mapping.cc @@ -6,6 +6,12 @@ #include #include +#if _WIN64 +#define PTR "%llx" +#else +#define PTR "%lx" +#endif + // printed because of verbosity=1 // CHECK: SHADOW_SCALE: [[SCALE:[0-9]+]] // CHECK: SHADOW_OFFSET: [[OFFSET:0x[0-9a-f]+]] @@ -15,7 +21,7 @@ int main() { __asan_get_shadow_mapping(&scale, &offset); fprintf(stderr, "scale: %d\n", (int)scale); - fprintf(stderr, "offset: 0x%lx\n", offset); + fprintf(stderr, "offset: 0x" PTR "\n", (void*)offset); // CHECK: scale: [[SCALE]] // CHECK: offset: [[OFFSET]] diff --git a/test/asan/TestCases/debug_report.cc b/test/asan/TestCases/debug_report.cc index 124ae5d76642..34bc06eba62c 100644 --- a/test/asan/TestCases/debug_report.cc +++ b/test/asan/TestCases/debug_report.cc @@ -6,6 +6,9 @@ #include #include +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + int main() { // Disable stderr buffering. Needed on Windows. setvbuf(stderr, NULL, _IONBF, 0); diff --git a/test/asan/TestCases/debug_stacks.cc b/test/asan/TestCases/debug_stacks.cc index 857e905094be..7c320bfcb2d9 100644 --- a/test/asan/TestCases/debug_stacks.cc +++ b/test/asan/TestCases/debug_stacks.cc @@ -5,6 +5,12 @@ // FIXME: Figure out why allocation/free stack traces may be too short on ARM. // REQUIRES: stable-runtime +#if _WIN64 +#define PTR "%llx" +#else +#define PTR "%lx" +#endif + #include #include #include @@ -35,9 +41,9 @@ int main() { // CHECK: alloc stack retval ok fprintf(stderr, "thread id = %d\n", thread_id); // CHECK: thread id = 0 - fprintf(stderr, "0x%lx\n", trace[0]); + fprintf(stderr, "0x" PTR "\n", trace[0]); // CHECK: [[ALLOC_FRAME_0:0x[0-9a-f]+]] - fprintf(stderr, "0x%lx\n", trace[1]); + fprintf(stderr, "0x" PTR "\n", trace[1]); // CHECK: [[ALLOC_FRAME_1:0x[0-9a-f]+]] num_frames = 100; @@ -48,9 +54,9 @@ int main() { // CHECK: free stack retval ok fprintf(stderr, "thread id = %d\n", thread_id); // CHECK: thread id = 0 - fprintf(stderr, "0x%lx\n", trace[0]); + fprintf(stderr, "0x" PTR "\n", trace[0]); // CHECK: [[FREE_FRAME_0:0x[0-9a-f]+]] - fprintf(stderr, "0x%lx\n", trace[1]); + fprintf(stderr, "0x" PTR "\n", trace[1]); // CHECK: [[FREE_FRAME_1:0x[0-9a-f]+]] mem[0] = 'A'; // BOOM diff --git a/test/asan/TestCases/deep_stack_uaf.cc b/test/asan/TestCases/deep_stack_uaf.cc index 95032f2bd4f5..bdf0dbdb4a4b 100644 --- a/test/asan/TestCases/deep_stack_uaf.cc +++ b/test/asan/TestCases/deep_stack_uaf.cc @@ -2,8 +2,7 @@ // RUN: %clangxx_asan -O0 %s -o %t 2>&1 // RUN: %env_asan_opts=malloc_context_size=120:redzone=512 not %run %t 2>&1 | FileCheck %s -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime #include #include diff --git a/test/asan/TestCases/default_options.cc b/test/asan/TestCases/default_options.cc index a3aa6637e8ac..27af76d7fe38 100644 --- a/test/asan/TestCases/default_options.cc +++ b/test/asan/TestCases/default_options.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_asan -O2 %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + const char *kAsanDefaultOptions="verbosity=1 help=1"; extern "C" diff --git a/test/asan/TestCases/double-free.cc b/test/asan/TestCases/double-free.cc index 9bd418fc6c80..2a26b23fb1f1 100644 --- a/test/asan/TestCases/double-free.cc +++ b/test/asan/TestCases/double-free.cc @@ -7,9 +7,7 @@ // RUN: %clangxx_asan -O0 -fsanitize-recover=address %s -o %t 2>&1 // RUN: %env_asan_opts=halt_on_error=false %run %t 2>&1 | FileCheck %s --check-prefix CHECK-RECOVER - -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime #include #include diff --git a/test/asan/TestCases/exitcode.cc b/test/asan/TestCases/exitcode.cc new file mode 100644 index 000000000000..cb10540999b7 --- /dev/null +++ b/test/asan/TestCases/exitcode.cc @@ -0,0 +1,130 @@ +// RUN: %clangxx_asan -g %stdcxx11 -Wno-deprecated-declarations %s -o %t +// RUN: %env_asan_opts=exitcode=42 %run %t | FileCheck %s + +// Android doesn't have spawn.h or posix_spawn. +// UNSUPPORTED: android + +// CHECK: got expected 42 exit code + +#include +#include + +#ifdef _WIN32 +#include + +int spawn_child(char **argv) { + // Set an environment variable to tell the child process to interrupt + // itself. + if (!SetEnvironmentVariableW(L"CRASH_FOR_TEST", L"1")) { + printf("SetEnvironmentVariableW failed (0x%8lx).\n", GetLastError()); + fflush(stdout); + exit(1); + } + + STARTUPINFOW si; + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + + if (!CreateProcessW(nullptr, // No module name (use command line) + GetCommandLineW(), // Command line + nullptr, // Process handle not inheritable + nullptr, // Thread handle not inheritable + TRUE, // Set handle inheritance to TRUE + 0, // No flags + nullptr, // Use parent's environment block + nullptr, // Use parent's starting directory + &si, &pi)) { + printf("CreateProcess failed (0x%08lx).\n", GetLastError()); + fflush(stdout); + exit(1); + } + + WaitForSingleObject(pi.hProcess, INFINITE); + + DWORD exit_code; + if (!GetExitCodeProcess(pi.hProcess, &exit_code)) { + printf("GetExitCodeProcess failed (0x%08lx).\n", GetLastError()); + fflush(stdout); + exit(1); + } + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + return exit_code; +} +#else +#include +#include +#include + +#if defined(__APPLE__) +#include +#endif + +#if defined(__APPLE__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) +#define USE_NSGETENVIRON 1 +#else +#define USE_NSGETENVIRON 0 +#endif + +#if !USE_NSGETENVIRON +extern char **environ; +#else +#include // _NSGetEnviron +#endif + +int spawn_child(char **argv) { + setenv("CRASH_FOR_TEST", "1", 1); + +#if !USE_NSGETENVIRON + char **envp = environ; +#else + char **envp = *_NSGetEnviron(); +#endif + + pid_t pid; + int err = posix_spawn(&pid, argv[0], nullptr, nullptr, argv, envp); + if (err) { + printf("posix_spawn failed: %d\n", err); + fflush(stdout); + exit(1); + } + + // Wait until the child exits. + int status; + pid_t wait_result_pid; + do { + wait_result_pid = waitpid(pid, &status, 0); + } while (wait_result_pid == -1 && errno == EINTR); + + if (wait_result_pid != pid || !WIFEXITED(status)) { + printf("error in waitpid\n"); + fflush(stdout); + exit(1); + } + + // Return the exit status. + return WEXITSTATUS(status); +} +#endif + +int main(int argc, char **argv) { + int r = 0; + if (getenv("CRASH_FOR_TEST")) { + // Generate an asan report to test ASAN_OPTIONS=exitcode=42 + int *p = new int; + delete p; + r = *p; + } else { + int exit_code = spawn_child(argv); + if (exit_code == 42) { + printf("got expected 42 exit code\n"); + fflush(stdout); + } + } + return r; +} diff --git a/test/asan/TestCases/global-address.cpp b/test/asan/TestCases/global-address.cpp new file mode 100644 index 000000000000..0e56ca10c39c --- /dev/null +++ b/test/asan/TestCases/global-address.cpp @@ -0,0 +1,12 @@ +// RUN: %clangxx_asan -o %t %s +// RUN: not %run %t 2>&1 | FileCheck %s +#include + +int g_i = 42; +int main() { + // CHECK: AddressSanitizer: attempting to call __sanitizer_get_allocated_size() for pointer which is not owned + // CHECK-NOT: ASAN:DEADLYSIGNAL + // CHECK: SUMMARY: AddressSanitizer: bad-__sanitizer_get_allocated_size + // CHECK-NOT: ASAN:DEADLYSIGNAL + return (int)__sanitizer_get_allocated_size(&g_i); +} diff --git a/test/asan/TestCases/ill.cc b/test/asan/TestCases/ill.cc new file mode 100644 index 000000000000..d7b535091671 --- /dev/null +++ b/test/asan/TestCases/ill.cc @@ -0,0 +1,31 @@ +// Test the handle_sigill option. +// +// RUN: %clangxx_asan %s -o %t && %env_asan_opts=handle_sigill=0 not --crash %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0 +// RUN: %clangxx_asan %s -o %t && %env_asan_opts=handle_sigill=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 +// REQUIRES: x86-target-arch + +#ifdef _WIN32 +#include +#endif + +int main(int argc, char **argv) { +#ifdef _WIN32 + // Sometimes on Windows this test generates a WER fault dialog. Suppress that. + UINT new_flags = SEM_FAILCRITICALERRORS | + SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX; + // Preserve existing error mode, as discussed at + // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx + UINT existing_flags = SetErrorMode(new_flags); + SetErrorMode(existing_flags | new_flags); +#endif + + if (argc) + __builtin_trap(); + // Unreachable code to avoid confusing the Windows unwinder. +#ifdef _WIN32 + SetErrorMode(0); +#endif +} +// CHECK0-NOT: ERROR: AddressSanitizer +// CHECK1: ERROR: AddressSanitizer: {{ILL|illegal-instruction}} on unknown address {{0x0*}} diff --git a/test/asan/TestCases/initialization-bug.cc b/test/asan/TestCases/initialization-bug.cc index 6f361cb2bad8..b28174f59aeb 100644 --- a/test/asan/TestCases/initialization-bug.cc +++ b/test/asan/TestCases/initialization-bug.cc @@ -1,12 +1,12 @@ // Test to make sure basic initialization order errors are caught. -// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t-INIT-ORDER-EXE +// RUN: %clangxx_asan %macos_min_target_10_11 -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t-INIT-ORDER-EXE // RUN: %env_asan_opts=check_initialization_order=true not %run %t-INIT-ORDER-EXE 2>&1 | FileCheck %s // Do not test with optimization -- the error may be optimized away. // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=186 -// XFAIL: darwin,win32 +// XFAIL: win32 // The test is expected to fail on OS X Yosemite and older // UNSUPPORTED: osx-no-ld64-live_support diff --git a/test/asan/TestCases/interception_failure_test.cc b/test/asan/TestCases/interception_failure_test.cc index 63d874667836..d85500b50486 100644 --- a/test/asan/TestCases/interception_failure_test.cc +++ b/test/asan/TestCases/interception_failure_test.cc @@ -5,13 +5,20 @@ // RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -O2 %s -o %t && %run %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -O3 %s -o %t && %run %t 2>&1 | FileCheck %s -// On Windows, defining strtoll results in linker errors. -// XFAIL: freebsd,win32 +// XFAIL: freebsd + +// On Windows, defining strtoll in a static build results in linker errors, but +// it works with the dynamic runtime. +// XFAIL: win32-static-asan + #include #include +#include extern "C" long strtol(const char *nptr, char **endptr, int base) { fprintf(stderr, "my_strtol_interceptor\n"); + if (endptr) + *endptr = (char*)nptr + strlen(nptr); return 0; } diff --git a/test/asan/TestCases/intra-object-overflow.cc b/test/asan/TestCases/intra-object-overflow.cc index e48a261f55cc..4032cc144858 100644 --- a/test/asan/TestCases/intra-object-overflow.cc +++ b/test/asan/TestCases/intra-object-overflow.cc @@ -4,6 +4,8 @@ // // FIXME: fix 32-bits. // REQUIRES: asan-64-bits +// FIXME: Implement ASan intra-object padding in Clang's MS record layout +// UNSUPPORTED: win32 #include #include class Foo { diff --git a/test/asan/TestCases/invalid-free.cc b/test/asan/TestCases/invalid-free.cc index dd59f5af32f2..be45e438bd45 100644 --- a/test/asan/TestCases/invalid-free.cc +++ b/test/asan/TestCases/invalid-free.cc @@ -4,8 +4,7 @@ // Also works if no malloc context is available. // RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=0 not %run %t 2>&1 | FileCheck %s // RUN: %env_asan_opts=malloc_context_size=0:fast_unwind_on_malloc=1 not %run %t 2>&1 | FileCheck %s -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime #include #include diff --git a/test/asan/TestCases/large_func_test.cc b/test/asan/TestCases/large_func_test.cc index 8d9afaeb4a75..1f5f7ccd5a6d 100644 --- a/test/asan/TestCases/large_func_test.cc +++ b/test/asan/TestCases/large_func_test.cc @@ -2,8 +2,7 @@ // RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK // RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK // RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime #include __attribute__((noinline)) diff --git a/test/asan/TestCases/no_asan_gen_globals.c b/test/asan/TestCases/no_asan_gen_globals.c deleted file mode 100644 index 2b13deace4b5..000000000000 --- a/test/asan/TestCases/no_asan_gen_globals.c +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -// 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_ diff --git a/test/asan/TestCases/on_error_callback.cc b/test/asan/TestCases/on_error_callback.cc index 88a4d2dca49f..f37d1eb7f7f8 100644 --- a/test/asan/TestCases/on_error_callback.cc +++ b/test/asan/TestCases/on_error_callback.cc @@ -1,5 +1,8 @@ // RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + #include #include diff --git a/test/asan/TestCases/printf-m.c b/test/asan/TestCases/printf-m.c new file mode 100644 index 000000000000..9cd5ae1c288e --- /dev/null +++ b/test/asan/TestCases/printf-m.c @@ -0,0 +1,14 @@ +// RUN: %clang_asan -O2 %s -o %t && %run %t + +// FIXME: printf is not intercepted on Windows yet. +// UNSUPPORTED: win32 + +#include + +int main() { + char s[5] = {'w', 'o', 'r', 'l', 'd'}; + // Test that %m does not consume an argument. If it does, %s would apply to + // the 5-character buffer, resulting in a stack-buffer-overflow report. + printf("%m %s, %.5s\n", "hello", s); + return 0; +} diff --git a/test/asan/TestCases/sanity_check_pure_c.c b/test/asan/TestCases/sanity_check_pure_c.c index c3a43c8cacb2..9d74996e43c5 100644 --- a/test/asan/TestCases/sanity_check_pure_c.c +++ b/test/asan/TestCases/sanity_check_pure_c.c @@ -3,10 +3,9 @@ // RUN: not %run %t 2>&1 | FileCheck %s // Sanity checking a test in pure C with -pie. -// RUN: %clang_asan -O2 %s -pie -fPIE -o %t +// RUN: %clang_asan -O2 %s %pie %fPIE -o %t // RUN: not %run %t 2>&1 | FileCheck %s -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime #include int main() { diff --git a/test/asan/TestCases/scariness_score_test.cc b/test/asan/TestCases/scariness_score_test.cc new file mode 100644 index 000000000000..dee7a13b7b3b --- /dev/null +++ b/test/asan/TestCases/scariness_score_test.cc @@ -0,0 +1,194 @@ +// Test how we produce the scariness score. + +// RUN: %clangxx_asan -O0 %s -o %t +// On OSX and Windows, alloc_dealloc_mismatch=1 isn't 100% reliable, so it's +// off by default. It's safe for these tests, though, so we turn it on. +// RUN: export %env_asan_opts=detect_stack_use_after_return=1:handle_abort=1:print_scariness=1:alloc_dealloc_mismatch=1 +// Make sure the stack is limited (may not be the default under GNU make) +// RUN: ulimit -s 4096 +// RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK1 +// RUN: not %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK2 +// RUN: not %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK3 +// RUN: not %run %t 4 2>&1 | FileCheck %s --check-prefix=CHECK4 +// RUN: not %run %t 5 2>&1 | FileCheck %s --check-prefix=CHECK5 +// RUN: not %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK6 +// RUN: not %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK7 +// RUN: not %run %t 8 2>&1 | FileCheck %s --check-prefix=CHECK8 +// RUN: not %run %t 9 2>&1 | FileCheck %s --check-prefix=CHECK9 +// RUN: not %run %t 10 2>&1 | FileCheck %s --check-prefix=CHECK10 +// RUN: not %run %t 11 2>&1 | FileCheck %s --check-prefix=CHECK11 +// RUN: not %run %t 12 2>&1 | FileCheck %s --check-prefix=CHECK12 +// RUN: not %run %t 13 2>&1 | FileCheck %s --check-prefix=CHECK13 +// RUN: not %run %t 14 2>&1 | FileCheck %s --check-prefix=CHECK14 +// RUN: not %run %t 15 2>&1 | FileCheck %s --check-prefix=CHECK15 +// RUN: not %run %t 16 2>&1 | FileCheck %s --check-prefix=CHECK16 +// RUN: not %run %t 17 2>&1 | FileCheck %s --check-prefix=CHECK17 +// RUN: not %run %t 18 2>&1 | FileCheck %s --check-prefix=CHECK18 +// RUN: not %run %t 19 2>&1 | FileCheck %s --check-prefix=CHECK19 +// RUN: not %run %t 20 2>&1 | FileCheck %s --check-prefix=CHECK20 +// RUN: not %run %t 21 2>&1 | FileCheck %s --check-prefix=CHECK21 +// RUN: not %run %t 22 2>&1 | FileCheck %s --check-prefix=CHECK22 +// RUN: not %run %t 23 2>&1 | FileCheck %s --check-prefix=CHECK23 +// RUN: not %run %t 24 2>&1 | FileCheck %s --check-prefix=CHECK24 +// RUN: not %run %t 25 2>&1 | FileCheck %s --check-prefix=CHECK25 +// RUN: not %run %t 26 2>&1 | FileCheck %s --check-prefix=CHECK26 +// RUN: not %run %t 27 2>&1 | FileCheck %s --check-prefix=CHECK27 +// Parts of the test are too platform-specific: +// REQUIRES: x86_64-target-arch +// REQUIRES: shell +#include +#include +#include + +#include + +enum ReadOrWrite { Read = 0, Write = 1 }; + +struct S32 { + char x[32]; +}; + +template +void HeapBuferOverflow(int Idx, ReadOrWrite w) { + T *t = new T[100]; + static T sink; + if (w) + t[100 + Idx] = T(); + else + sink = t[100 + Idx]; + delete [] t; +} + +template +void HeapUseAfterFree(int Idx, ReadOrWrite w) { + T *t = new T[100]; + static T sink; + sink = t[0]; + delete [] t; + if (w) + t[Idx] = T(); + else + sink = t[Idx]; +} + +template +void StackBufferOverflow(int Idx, ReadOrWrite w) { + T t[100]; + static T sink; + sink = t[Idx]; + if (w) + t[100 + Idx] = T(); + else + sink = t[100 + Idx]; +} + +template +T *LeakStack() { + T t[100]; + static volatile T *x; + x = &t[0]; + return (T*)x; +} + +template +void StackUseAfterReturn(int Idx, ReadOrWrite w) { + static T sink; + T *t = LeakStack(); + if (w) + t[100 + Idx] = T(); + else + sink = t[100 + Idx]; +} + +char g1[100]; +short g2[100]; +int g4[100]; +int64_t g8[100]; +S32 gm[100]; + +void DoubleFree() { + int *x = new int; + static volatile int two = 2; + for (int i = 0; i < two; i++) + delete x; +} + +void StackOverflow(int Idx) { + int some_stack[10000]; + static volatile int *x; + x = &some_stack[0]; + if (Idx > 0) + StackOverflow(Idx - 1); +} + +void UseAfterPoison() { + int buf[100]; + __asan_poison_memory_region(buf, sizeof(buf)); + static volatile int sink; + sink = buf[42]; +} + +int main(int argc, char **argv) { + char arr[100]; + static volatile int zero = 0; + static volatile int *zero_ptr = 0; + static volatile int *wild_addr = (int*)0x10000000; // System-dependent. + if (argc != 2) return 1; + int kind = atoi(argv[1]); + switch (kind) { + case 1: HeapBuferOverflow(0, Read); break; + case 2: HeapBuferOverflow(0, Read); break; + case 3: HeapBuferOverflow(0, Write); break; + case 4: HeapBuferOverflow(2, Write); break; + case 5: HeapBuferOverflow(4, Write); break; + case 6: HeapUseAfterFree(0, Read); break; + case 7: HeapUseAfterFree(0, Write); break; + case 8: HeapUseAfterFree(0, Read); break; + case 9: HeapUseAfterFree(0, Write); break; + case 10: StackBufferOverflow(0, Write); break; + case 11: StackBufferOverflow(0, Read); break; + case 12: StackBufferOverflow(4, Write); break; + case 13: StackUseAfterReturn(0, Read); break; + case 14: StackUseAfterReturn(0, Write); break; + case 15: g1[zero + 100] = 0; break; + case 16: gm[0] = gm[zero + 100 + 1]; break; + case 17: DoubleFree(); break; + case 18: StackOverflow(1000000); break; + case 19: *zero_ptr = 0; break; + case 20: *wild_addr = 0; break; + case 21: zero = *wild_addr; break; + case 22: ((void (*)(void))wild_addr)(); break; + case 23: delete (new int[10]); break; + case 24: free((char*)malloc(100) + 10); break; + case 25: memcpy(arr, arr+10, 20); break; + case 26: UseAfterPoison(); break; + case 27: abort(); + // CHECK1: SCARINESS: 12 (1-byte-read-heap-buffer-overflow) + // CHECK2: SCARINESS: 17 (4-byte-read-heap-buffer-overflow) + // CHECK3: SCARINESS: 33 (2-byte-write-heap-buffer-overflow) + // CHECK4: SCARINESS: 52 (8-byte-write-heap-buffer-overflow-far-from-bounds) + // CHECK5: SCARINESS: 55 (multi-byte-write-heap-buffer-overflow-far-from-bounds) + // CHECK6: SCARINESS: 40 (1-byte-read-heap-use-after-free) + // CHECK7: SCARINESS: 46 (4-byte-write-heap-use-after-free) + // CHECK8: SCARINESS: 51 (8-byte-read-heap-use-after-free) + // CHECK9: SCARINESS: 55 (multi-byte-write-heap-use-after-free) + // CHECK10: SCARINESS: 46 (1-byte-write-stack-buffer-overflow) + // CHECK11: SCARINESS: 38 (8-byte-read-stack-buffer-overflow) + // CHECK12: SCARINESS: 61 (4-byte-write-stack-buffer-overflow-far-from-bounds) + // CHECK13: SCARINESS: 50 (1-byte-read-stack-use-after-return) + // CHECK14: SCARINESS: 65 (multi-byte-write-stack-use-after-return) + // CHECK15: SCARINESS: 31 (1-byte-write-global-buffer-overflow) + // CHECK16: SCARINESS: 36 (multi-byte-read-global-buffer-overflow-far-from-bounds) + // CHECK17: SCARINESS: 42 (double-free) + // CHECK18: SCARINESS: 10 (stack-overflow) + // CHECK19: SCARINESS: 10 (null-deref) + // CHECK20: SCARINESS: 30 (wild-addr-write) + // CHECK21: SCARINESS: 20 (wild-addr-read) + // CHECK22: SCARINESS: 60 (wild-jump) + // CHECK23: SCARINESS: 10 (alloc-dealloc-mismatch) + // CHECK24: SCARINESS: 40 (bad-free) + // CHECK25: SCARINESS: 10 (memcpy-param-overlap) + // CHECK26: SCARINESS: 27 (4-byte-read-use-after-poison) + // CHECK27: SCARINESS: 10 (signal) + } +} diff --git a/test/asan/TestCases/set_shadow_test.c b/test/asan/TestCases/set_shadow_test.c new file mode 100644 index 000000000000..daa79a66a389 --- /dev/null +++ b/test/asan/TestCases/set_shadow_test.c @@ -0,0 +1,69 @@ +// RUN: %clang_asan -O0 %s -o %t +// RUN: %run %t 0x00 2>&1 | FileCheck %s -check-prefix=X00 +// RUN: not %run %t 0xf1 2>&1 | FileCheck %s -check-prefix=XF1 +// RUN: not %run %t 0xf2 2>&1 | FileCheck %s -check-prefix=XF2 +// RUN: not %run %t 0xf3 2>&1 | FileCheck %s -check-prefix=XF3 +// RUN: not %run %t 0xf5 2>&1 | FileCheck %s -check-prefix=XF5 +// RUN: not %run %t 0xf8 2>&1 | FileCheck %s -check-prefix=XF8 + +// XFAIL: win32 + +#include +#include +#include +#include +#include + +void __asan_set_shadow_00(size_t addr, size_t size); +void __asan_set_shadow_f1(size_t addr, size_t size); +void __asan_set_shadow_f2(size_t addr, size_t size); +void __asan_set_shadow_f3(size_t addr, size_t size); +void __asan_set_shadow_f5(size_t addr, size_t size); +void __asan_set_shadow_f8(size_t addr, size_t size); + +char a __attribute__((aligned(8))); + +void f(long arg) { + size_t shadow_offset; + size_t shadow_scale; + __asan_get_shadow_mapping(&shadow_scale, &shadow_offset); + size_t addr = (((size_t)&a) >> shadow_scale) + shadow_offset; + + switch (arg) { + // X00-NOT: AddressSanitizer + // X00: PASS + case 0x00: + return __asan_set_shadow_00(addr, 1); + // XF1: AddressSanitizer: stack-buffer-underflow + // XF1: [f1] + case 0xf1: + return __asan_set_shadow_f1(addr, 1); + // XF2: AddressSanitizer: stack-buffer-overflow + // XF2: [f2] + case 0xf2: + return __asan_set_shadow_f2(addr, 1); + // XF3: AddressSanitizer: stack-buffer-overflow + // XF3: [f3] + case 0xf3: + return __asan_set_shadow_f3(addr, 1); + // XF5: AddressSanitizer: stack-use-after-return + // XF5: [f5] + case 0xf5: + return __asan_set_shadow_f5(addr, 1); + // XF8: AddressSanitizer: stack-use-after-scope + // XF8: [f8] + case 0xf8: + return __asan_set_shadow_f8(addr, 1); + } + assert(0); +} + +int main(int argc, char **argv) { + assert(argc > 1); + + long arg = strtol(argv[1], 0, 16); + f(arg); + a = 1; + printf("PASS\n"); + return 0; +} diff --git a/test/asan/TestCases/speculative_load.cc b/test/asan/TestCases/speculative_load.cc index 2409d7a5eee3..fdf70eb39767 100644 --- a/test/asan/TestCases/speculative_load.cc +++ b/test/asan/TestCases/speculative_load.cc @@ -27,6 +27,10 @@ struct S { __asan_poison_memory_region(_data._s._ch, 23); } + ~S() { + __asan_unpoison_memory_region(_data._s._ch, 23); + } + bool is_long() const { return _data._s._size & 1; } diff --git a/test/asan/TestCases/strdup_oob_test.cc b/test/asan/TestCases/strdup_oob_test.cc index 492555ad1019..60c5ef12a473 100644 --- a/test/asan/TestCases/strdup_oob_test.cc +++ b/test/asan/TestCases/strdup_oob_test.cc @@ -9,6 +9,10 @@ // Unwind problem on arm: "main" is missing from the allocation stack trace. // UNSUPPORTED: armv7l-unknown-linux-gnueabihf +// FIXME: We fail to intercept strdup with the dynamic WinASan RTL, so it's not +// in the stack trace. +// XFAIL: win32-dynamic-asan + #include char kString[] = "foo"; diff --git a/test/asan/TestCases/strncasecmp_strict.c b/test/asan/TestCases/strncasecmp_strict.c new file mode 100644 index 000000000000..aa658402b42b --- /dev/null +++ b/test/asan/TestCases/strncasecmp_strict.c @@ -0,0 +1,67 @@ +// Test strict_string_checks option in strncmp function +// RUN: %clang_asan %s -o %t + +// RUN: %env_asan_opts=strict_string_checks=false %run %t a 2>&1 +// RUN: %env_asan_opts=strict_string_checks=true %run %t a 2>&1 +// RUN: not %run %t b 2>&1 | FileCheck %s +// RUN: not %run %t c 2>&1 | FileCheck %s +// RUN: not %run %t d 2>&1 | FileCheck %s +// RUN: not %run %t e 2>&1 | FileCheck %s +// RUN: not %run %t f 2>&1 | FileCheck %s +// RUN: not %run %t g 2>&1 | FileCheck %s +// RUN: %env_asan_opts=strict_string_checks=false %run %t h 2>&1 +// RUN: %env_asan_opts=strict_string_checks=true not %run %t h 2>&1 | FileCheck %s +// RUN: %env_asan_opts=strict_string_checks=false %run %t i 2>&1 +// RUN: %env_asan_opts=strict_string_checks=true not %run %t i 2>&1 | FileCheck %s + +// XFAIL: win32 + +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + assert(argc >= 2); + const size_t size = 100; + char fill = 'o'; + char s1[size]; + char s2[size]; + memset(s1, fill, size); + memset(s2, fill, size); + + switch (argv[1][0]) { + case 'a': + s1[size - 1] = 'z'; + s2[size - 1] = 'x'; + for (int i = 0; i <= size; ++i) + assert((strncasecmp(s1, s2, i) == 0) == (i < size)); + s1[size - 1] = '\0'; + s2[size - 1] = '\0'; + assert(strncasecmp(s1, s2, 2*size) == 0); + break; + case 'b': + return strncasecmp(s1-1, s2, 1); + case 'c': + return strncasecmp(s1, s2-1, 1); + case 'd': + return strncasecmp(s1+size, s2, 1); + case 'e': + return strncasecmp(s1, s2+size, 1); + case 'f': + return strncasecmp(s1+1, s2, size); + case 'g': + return strncasecmp(s1, s2+1, size); + case 'h': + s1[size - 1] = '\0'; + assert(strncasecmp(s1, s2, 2*size) != 0); + break; + case 'i': + s2[size - 1] = '\0'; + assert(strncasecmp(s1, s2, 2*size) != 0); + break; + // CHECK: {{.*}}ERROR: AddressSanitizer: stack-buffer-{{ov|und}}erflow on address + } + return 0; +} diff --git a/test/asan/TestCases/strncmp_strict.c b/test/asan/TestCases/strncmp_strict.c new file mode 100644 index 000000000000..5b5429064ced --- /dev/null +++ b/test/asan/TestCases/strncmp_strict.c @@ -0,0 +1,65 @@ +// Test strict_string_checks option in strncmp function +// RUN: %clang_asan %s -o %t + +// RUN: %env_asan_opts=strict_string_checks=false %run %t a 2>&1 +// RUN: %env_asan_opts=strict_string_checks=true %run %t a 2>&1 +// RUN: not %run %t b 2>&1 | FileCheck %s +// RUN: not %run %t c 2>&1 | FileCheck %s +// RUN: not %run %t d 2>&1 | FileCheck %s +// RUN: not %run %t e 2>&1 | FileCheck %s +// RUN: not %run %t f 2>&1 | FileCheck %s +// RUN: not %run %t g 2>&1 | FileCheck %s +// RUN: %env_asan_opts=strict_string_checks=false %run %t h 2>&1 +// RUN: %env_asan_opts=strict_string_checks=true not %run %t h 2>&1 | FileCheck %s +// RUN: %env_asan_opts=strict_string_checks=false %run %t i 2>&1 +// RUN: %env_asan_opts=strict_string_checks=true not %run %t i 2>&1 | FileCheck %s + +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + assert(argc >= 2); + const size_t size = 100; + char fill = 'o'; + char s1[size]; + char s2[size]; + memset(s1, fill, size); + memset(s2, fill, size); + + switch (argv[1][0]) { + case 'a': + s1[size - 1] = 'z'; + s2[size - 1] = 'x'; + for (int i = 0; i <= size; ++i) + assert((strncmp(s1, s2, i) == 0) == (i < size)); + s1[size - 1] = '\0'; + s2[size - 1] = '\0'; + assert(strncmp(s1, s2, 2*size) == 0); + break; + case 'b': + return strncmp(s1-1, s2, 1); + case 'c': + return strncmp(s1, s2-1, 1); + case 'd': + return strncmp(s1+size, s2, 1); + case 'e': + return strncmp(s1, s2+size, 1); + case 'f': + return strncmp(s1+1, s2, size); + case 'g': + return strncmp(s1, s2+1, size); + case 'h': + s1[size - 1] = '\0'; + assert(strncmp(s1, s2, 2*size) != 0); + break; + case 'i': + s2[size - 1] = '\0'; + assert(strncmp(s1, s2, 2*size) != 0); + break; + // CHECK: {{.*}}ERROR: AddressSanitizer: stack-buffer-{{ov|und}}erflow on address + } + return 0; +} diff --git a/test/asan/TestCases/strncpy-overflow.cc b/test/asan/TestCases/strncpy-overflow.cc index 651ae22795f1..7da9a8ff8eac 100644 --- a/test/asan/TestCases/strncpy-overflow.cc +++ b/test/asan/TestCases/strncpy-overflow.cc @@ -4,8 +4,7 @@ // RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK // REQUIRES: compiler-rt-optimized -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime #include #include diff --git a/test/asan/TestCases/strstr-1.c b/test/asan/TestCases/strstr-1.c index d0fa25bc62ba..06a8a8a55d99 100644 --- a/test/asan/TestCases/strstr-1.c +++ b/test/asan/TestCases/strstr-1.c @@ -15,7 +15,7 @@ int main(int argc, char **argv) { char s1[4] = "acb"; __asan_poison_memory_region ((char *)&s1[2], 2); r = strstr(s1, s2); - // CHECK:'s1' <== Memory access at offset {{[0-9]+}} partially overflows this variable + // CHECK:'s1' <== Memory access at offset {{[0-9]+}} {{partially overflows this variable|is inside this variable}} assert(r == s1 + 1); return 0; } diff --git a/test/asan/TestCases/strstr_strict.c b/test/asan/TestCases/strstr_strict.c index 35ad93c645de..63e6b25a017c 100644 --- a/test/asan/TestCases/strstr_strict.c +++ b/test/asan/TestCases/strstr_strict.c @@ -17,7 +17,7 @@ int main(int argc, char **argv) { s2[size - 1]='\0'; char* r = strstr(s1, s2); // CHECK: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}} - // CHECK: READ of size 101 + // CHECK: READ of size {{101|100}} assert(r == s1); free(s1); free(s2); diff --git a/test/asan/TestCases/suppressions-library.cc b/test/asan/TestCases/suppressions-library.cc index ad6e09279b3d..e95d339168ed 100644 --- a/test/asan/TestCases/suppressions-library.cc +++ b/test/asan/TestCases/suppressions-library.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %dynamiclib %ld_flags_rpath_so +// RUN: %clangxx_asan -O0 -DSHARED_LIB %s %fPIC -shared -o %dynamiclib %ld_flags_rpath_so // RUN: %clangxx_asan -O0 %s -o %t %ld_flags_rpath_exe // Check that without suppressions, we catch the issue. diff --git a/test/asan/TestCases/use-after-delete.cc b/test/asan/TestCases/use-after-delete.cc index 8fdec8d83c80..1cc8c2f079ac 100644 --- a/test/asan/TestCases/use-after-delete.cc +++ b/test/asan/TestCases/use-after-delete.cc @@ -2,8 +2,7 @@ // RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK // RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK // RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime #include int main() { diff --git a/test/asan/TestCases/use-after-free-right.cc b/test/asan/TestCases/use-after-free-right.cc index f714b44f2f1f..d72370e72d81 100644 --- a/test/asan/TestCases/use-after-free-right.cc +++ b/test/asan/TestCases/use-after-free-right.cc @@ -2,8 +2,7 @@ // RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK // RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK // RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime // Test use-after-free report in the case when access is at the right border of // the allocation. diff --git a/test/asan/TestCases/use-after-free.cc b/test/asan/TestCases/use-after-free.cc index 7bc225b1ef86..c96d7f2e24e1 100644 --- a/test/asan/TestCases/use-after-free.cc +++ b/test/asan/TestCases/use-after-free.cc @@ -2,8 +2,7 @@ // RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK // RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK // RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK -// XFAIL: arm-linux-gnueabi -// XFAIL: armv7l-unknown-linux-gnueabihf +// REQUIRES: stable-runtime #include int main() { diff --git a/test/asan/TestCases/use-after-scope-capture.cc b/test/asan/TestCases/use-after-scope-capture.cc index 07aab672eecb..113ce3536662 100644 --- a/test/asan/TestCases/use-after-scope-capture.cc +++ b/test/asan/TestCases/use-after-scope-capture.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -std=c++11 -O1 -fsanitize-address-use-after-scope %s -o %t && \ +// RUN: %clangxx_asan %stdcxx11 -O1 -fsanitize-address-use-after-scope %s -o %t && \ // RUN: not %run %t 2>&1 | FileCheck %s #include diff --git a/test/asan/TestCases/use-after-scope-chars.cc b/test/asan/TestCases/use-after-scope-chars.cc deleted file mode 100644 index 51fc5fa38747..000000000000 --- a/test/asan/TestCases/use-after-scope-chars.cc +++ /dev/null @@ -1,15 +0,0 @@ -// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \ -// RUN: not %run %t 2>&1 | FileCheck %s -// XFAIL: * - -// FIXME: This works only for arraysize <= 8. - -char *p = 0; - -int main() { - { - char x[1024] = {}; - p = x; - } - return *p; // BOOM -} diff --git a/test/asan/TestCases/use-after-scope-goto.cc b/test/asan/TestCases/use-after-scope-goto.cc new file mode 100644 index 000000000000..351cbe995efb --- /dev/null +++ b/test/asan/TestCases/use-after-scope-goto.cc @@ -0,0 +1,73 @@ +// RUN: %clangxx_asan -O0 -fsanitize-address-use-after-scope %s -o %t && %run %t + +// Function jumps over variable initialization making lifetime analysis +// ambiguous. Asan should ignore such variable and program must not fail. + +#include + +int *ptr; + +void f1(int cond) { + if (cond) + goto label; + int tmp; + + label: + ptr = &tmp; + *ptr = 5; +} + +void f2(int cond) { + switch (cond) { + case 1: { + ++cond; + int tmp; + ptr = &tmp; + exit(0); + case 2: + ptr = &tmp; + *ptr = 5; + exit(0); + } + } +} + +void f3(int cond) { + { + int tmp; + goto l2; + l1: + ptr = &tmp; + *ptr = 5; + + exit(0); + } + l2: + goto l1; +} + +void use(int *x) { + static int c = 10; + if (--c == 0) + exit(0); + (*x)++; +} + +void f4() { + { + int x; + l2: + use(&x); + goto l1; + } + l1: + goto l2; +} + +int main() { + f1(1); + f2(1); + f3(1); + f4(); + return 0; +} diff --git a/test/asan/TestCases/use-after-scope-inlined.cc b/test/asan/TestCases/use-after-scope-inlined.cc index fc8c7f7bb87d..98a455cbc0c7 100644 --- a/test/asan/TestCases/use-after-scope-inlined.cc +++ b/test/asan/TestCases/use-after-scope-inlined.cc @@ -24,5 +24,5 @@ int main(int argc, char *argv[]) { // CHECK: Address 0x{{.*}} is located in stack of thread T0 at offset // CHECK: [[OFFSET:[^ ]*]] in frame // CHECK: main - // CHECK: {{\[}}[[OFFSET]], {{.*}}) 'x.i' + // CHECK: {{\[}}[[OFFSET]], {{.*}}) 'x.i:[[@LINE-15]]' } diff --git a/test/asan/TestCases/use-after-scope-loop-bug.cc b/test/asan/TestCases/use-after-scope-loop-bug.cc index 6ad9bf3260cc..d4b12eca9808 100644 --- a/test/asan/TestCases/use-after-scope-loop-bug.cc +++ b/test/asan/TestCases/use-after-scope-loop-bug.cc @@ -1,10 +1,7 @@ // RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \ // RUN: not %run %t 2>&1 | FileCheck %s -// -// FIXME: @llvm.lifetime.* are not emitted for x. -// XFAIL: * -int *p; +volatile int *p; int main() { // Variable goes in and out of scope. @@ -13,4 +10,8 @@ int main() { p = x + i; } return *p; // BOOM + // CHECK: ERROR: AddressSanitizer: stack-use-after-scope + // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-loop-bug.cc:[[@LINE-2]] + // CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame + // {{\[}}[[OFFSET]], {{[0-9]+}}) 'x' } diff --git a/test/asan/TestCases/use-after-scope-loop-removed.cc b/test/asan/TestCases/use-after-scope-loop-removed.cc index cd71a5046cd4..730bf3a3ebe3 100644 --- a/test/asan/TestCases/use-after-scope-loop-removed.cc +++ b/test/asan/TestCases/use-after-scope-loop-removed.cc @@ -1,9 +1,5 @@ // RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \ // RUN: not %run %t 2>&1 | FileCheck %s -// -// FIXME: Compiler removes for-loop but keeps x variable. For unknown reason -// @llvm.lifetime.* are not emitted for x. -// XFAIL: * #include @@ -14,6 +10,9 @@ int main() { int x; p = &x; } - return **p; // BOOM + return *p; // BOOM // CHECK: ERROR: AddressSanitizer: stack-use-after-scope + // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-loop-removed.cc:[[@LINE-2]] + // CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame + // {{\[}}[[OFFSET]], {{[0-9]+}}) 'x' } diff --git a/test/asan/TestCases/use-after-scope-temp.cc b/test/asan/TestCases/use-after-scope-temp.cc index 3736f914d072..4dcef59a2ff1 100644 --- a/test/asan/TestCases/use-after-scope-temp.cc +++ b/test/asan/TestCases/use-after-scope-temp.cc @@ -1,8 +1,6 @@ -// RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \ +// RUN: %clangxx_asan %stdcxx11 -O1 -fsanitize-address-use-after-scope %s -o %t && \ // RUN: not %run %t 2>&1 | FileCheck %s -// -// Lifetime for temporaries is not emitted yet. -// XFAIL: * + struct IntHolder { int val; @@ -15,9 +13,9 @@ void save(const IntHolder &holder) { } int main(int argc, char *argv[]) { - save({10}); + save({argc}); int x = saved->val; // BOOM -// CHECK: ERROR: AddressSanitizer: stack-use-after-scope -// CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-temp.cc:[[@LINE-2]] + // CHECK: ERROR: AddressSanitizer: stack-use-after-scope + // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-temp.cc:[[@LINE-2]] return x; } diff --git a/test/asan/TestCases/use-after-scope-temp2.cc b/test/asan/TestCases/use-after-scope-temp2.cc new file mode 100644 index 000000000000..1ecd3cbe23ff --- /dev/null +++ b/test/asan/TestCases/use-after-scope-temp2.cc @@ -0,0 +1,20 @@ +// RUN: %clangxx_asan %stdcxx11 -O1 -fsanitize-address-use-after-scope %s -o %t && \ +// RUN: not %run %t 2>&1 | FileCheck %s + + +struct IntHolder { + const IntHolder& Self() const { + return *this; + } + int val = 3; +}; + +const IntHolder *saved; + +int main(int argc, char *argv[]) { + saved = &IntHolder().Self(); + int x = saved->val; // BOOM + // CHECK: ERROR: AddressSanitizer: stack-use-after-scope + // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-temp2.cc:[[@LINE-2]] + return x; +} diff --git a/test/asan/TestCases/use-after-scope-types.cc b/test/asan/TestCases/use-after-scope-types.cc new file mode 100644 index 000000000000..ec6742bbb24f --- /dev/null +++ b/test/asan/TestCases/use-after-scope-types.cc @@ -0,0 +1,74 @@ +// RUN: %clangxx_asan %stdcxx11 -O0 -fsanitize-address-use-after-scope %s -o %t +// RUN: not %run %t 0 2>&1 | FileCheck %s +// RUN: not %run %t 1 2>&1 | FileCheck %s +// RUN: not %run %t 2 2>&1 | FileCheck %s +// RUN: not %run %t 3 2>&1 | FileCheck %s +// RUN: not %run %t 4 2>&1 | FileCheck %s +// RUN: not %run %t 5 2>&1 | FileCheck %s +// RUN: not %run %t 6 2>&1 | FileCheck %s +// RUN: not %run %t 7 2>&1 | FileCheck %s +// RUN: not %run %t 8 2>&1 | FileCheck %s +// RUN: not %run %t 9 2>&1 | FileCheck %s +// RUN: not %run %t 10 2>&1 | FileCheck %s + +#include +#include +#include + +template struct Ptr { + void Store(T *ptr) { t = ptr; } + + void Access() { *t = {}; } + + T *t; +}; + +template struct Ptr { + using Type = T[N]; + void Store(Type *ptr) { t = *ptr; } + + void Access() { *t = {}; } + + T *t; +}; + +template __attribute__((noinline)) void test() { + Ptr ptr; + { + T x; + ptr.Store(&x); + } + + ptr.Access(); + // CHECK: ERROR: AddressSanitizer: stack-use-after-scope + // CHECK: #{{[0-9]+}} 0x{{.*}} in {{(void )?test.*\((void)?\) .*}}use-after-scope-types.cc + // CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame + // {{\[}}[[OFFSET]], {{[0-9]+}}) 'x' +} + +int main(int argc, char **argv) { + using Tests = void (*)(); + Tests tests[] = { + &test, + &test, + &test, + &test, + &test, + &test, + &test>, + &test, + &test, + &test, + &test, + }; + + int n = atoi(argv[1]); + if (n == sizeof(tests) / sizeof(tests[0])) { + for (auto te : tests) + te(); + } else { + tests[n](); + } + + return 0; +} diff --git a/test/asan/TestCases/use-after-scope.cc b/test/asan/TestCases/use-after-scope.cc index 1aa6758229dd..d92dae6572ce 100644 --- a/test/asan/TestCases/use-after-scope.cc +++ b/test/asan/TestCases/use-after-scope.cc @@ -1,16 +1,17 @@ // RUN: %clangxx_asan -O1 -fsanitize-address-use-after-scope %s -o %t && \ // RUN: not %run %t 2>&1 | FileCheck %s -int *p = 0; +volatile int *p = 0; int main() { { int x = 0; p = &x; } - return *p; // BOOM + *p = 5; // BOOM // CHECK: ERROR: AddressSanitizer: stack-use-after-scope // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope.cc:[[@LINE-2]] // CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame // {{\[}}[[OFFSET]], {{[0-9]+}}) 'x' + return 0; } diff --git a/test/asan/TestCases/vla_chrome_testcase.cc b/test/asan/TestCases/vla_chrome_testcase.cc index 8ee040120c48..a8771800609d 100644 --- a/test/asan/TestCases/vla_chrome_testcase.cc +++ b/test/asan/TestCases/vla_chrome_testcase.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s // diff --git a/test/asan/TestCases/vla_condition_overflow.cc b/test/asan/TestCases/vla_condition_overflow.cc index 17f28d823252..cf42d794e9d5 100644 --- a/test/asan/TestCases/vla_condition_overflow.cc +++ b/test/asan/TestCases/vla_condition_overflow.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s // // REQUIRES: stable-runtime diff --git a/test/asan/TestCases/vla_loop_overfow.cc b/test/asan/TestCases/vla_loop_overfow.cc index 4f20c8d19d14..b6a5864c0f64 100644 --- a/test/asan/TestCases/vla_loop_overfow.cc +++ b/test/asan/TestCases/vla_loop_overfow.cc @@ -1,4 +1,4 @@ -// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t +// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-dynamic-allocas %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s // // REQUIRES: stable-runtime -- cgit v1.2.3