aboutsummaryrefslogtreecommitdiff
path: root/test/asan/TestCases/Linux
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:27 +0000
commit316d58822dada9440bd06ecfc758dcc2364d617c (patch)
treefe72ec2e6ce9a360dda74d9d57f7acdb0e3c39d6 /test/asan/TestCases/Linux
parent0230fcf22fe7d19f03d981c9c2c59a3db0b72ea5 (diff)
Notes
Diffstat (limited to 'test/asan/TestCases/Linux')
-rw-r--r--test/asan/TestCases/Linux/abort_on_error.cc2
-rw-r--r--test/asan/TestCases/Linux/auto_memory_profile_test.cc32
-rw-r--r--test/asan/TestCases/Linux/coverage_html_report.cc24
-rw-r--r--test/asan/TestCases/Linux/cuda_test.cc37
-rw-r--r--test/asan/TestCases/Linux/local_alias.cc5
-rw-r--r--test/asan/TestCases/Linux/malloc_delete_mismatch.cc3
-rw-r--r--test/asan/TestCases/Linux/memmem_test.cc13
-rw-r--r--test/asan/TestCases/Linux/new_delete_mismatch.cc4
-rw-r--r--test/asan/TestCases/Linux/odr-violation.cc5
-rw-r--r--test/asan/TestCases/Linux/print_memory_profile_test.cc24
-rw-r--r--test/asan/TestCases/Linux/pthread_create_from_constructor.cc49
-rw-r--r--test/asan/TestCases/Linux/quarantine_size_mb.cc2
-rw-r--r--test/asan/TestCases/Linux/release_to_os_test.cc46
-rw-r--r--test/asan/TestCases/Linux/scariness_score_test.cc192
-rw-r--r--test/asan/TestCases/Linux/stack-trace-dlclose.cc3
-rw-r--r--test/asan/TestCases/Linux/swapcontext_annotation.cc74
-rw-r--r--test/asan/TestCases/Linux/thread_local_quarantine_size_kb.cc40
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