diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:27 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:27 +0000 |
| commit | 316d58822dada9440bd06ecfc758dcc2364d617c (patch) | |
| tree | fe72ec2e6ce9a360dda74d9d57f7acdb0e3c39d6 /test/asan/TestCases/Linux | |
| parent | 0230fcf22fe7d19f03d981c9c2c59a3db0b72ea5 (diff) | |
Notes
Diffstat (limited to 'test/asan/TestCases/Linux')
17 files changed, 291 insertions, 264 deletions
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 <stdlib.h> 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 <sanitizer/common_interface_defs.h> + +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +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 <stdio.h> -#include <unistd.h> - -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 <assert.h> +#include <unistd.h> +#include <sys/mman.h> +#include <stdint.h> + +#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 <stdlib.h> 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 <string.h> @@ -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 <stdlib.h> 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 <sanitizer/common_interface_defs.h> #include <stdio.h> +#include <stdlib.h> 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 <stdio.h> +#include <pthread.h> +#include <unistd.h> + +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 <dlfcn.h> +#include <stdlib.h> +#include <string> + +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 <string.h> 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 <stdlib.h> +#include <stdio.h> +#include <algorithm> +#include <stdint.h> +#include <assert.h> + +#include <sanitizer/asan_interface.h> + +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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include <sanitizer/asan_interface.h> - -enum ReadOrWrite { Read = 0, Write = 1 }; - -struct S32 { - char x[32]; -}; - -template<class T> -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<class T> -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<class T> -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<class T> -T *LeakStack() { - T t[100]; - static volatile T *x; - x = &t[0]; - return (T*)x; -} - -template<class T> -void StackUseAfterReturn(int Idx, ReadOrWrite w) { - static T sink; - T *t = LeakStack<T>(); - 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<char>(0, Read); break; - case 2: HeapBuferOverflow<int>(0, Read); break; - case 3: HeapBuferOverflow<short>(0, Write); break; - case 4: HeapBuferOverflow<int64_t>(2, Write); break; - case 5: HeapBuferOverflow<S32>(4, Write); break; - case 6: HeapUseAfterFree<char>(0, Read); break; - case 7: HeapUseAfterFree<int>(0, Write); break; - case 8: HeapUseAfterFree<int64_t>(0, Read); break; - case 9: HeapUseAfterFree<S32>(0, Write); break; - case 10: StackBufferOverflow<char>(0, Write); break; - case 11: StackBufferOverflow<int64_t>(0, Read); break; - case 12: StackBufferOverflow<int>(4, Write); break; - case 13: StackUseAfterReturn<char>(0, Read); break; - case 14: StackUseAfterReturn<S32>(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 <assert.h> #include <dlfcn.h> 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 <pthread.h> #include <setjmp.h> @@ -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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sanitizer/allocator_interface.h> + +// 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 |
