aboutsummaryrefslogtreecommitdiff
path: root/test/asan/TestCases/Posix
diff options
context:
space:
mode:
Diffstat (limited to 'test/asan/TestCases/Posix')
-rw-r--r--test/asan/TestCases/Posix/allow_user_segv.cc6
-rw-r--r--test/asan/TestCases/Posix/asan-symbolize-bad-path.cc4
-rw-r--r--test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc2
-rw-r--r--test/asan/TestCases/Posix/assign_large_valloc_to_global.cc7
-rw-r--r--test/asan/TestCases/Posix/closed-fds.cc33
-rw-r--r--test/asan/TestCases/Posix/coverage-caller-callee.cc75
-rw-r--r--test/asan/TestCases/Posix/coverage-direct-activation.cc6
-rw-r--r--test/asan/TestCases/Posix/coverage-direct-large.cc4
-rw-r--r--test/asan/TestCases/Posix/coverage-direct.cc12
-rw-r--r--test/asan/TestCases/Posix/coverage-fork-direct.cc2
-rw-r--r--test/asan/TestCases/Posix/coverage-fork.cc3
-rw-r--r--test/asan/TestCases/Posix/coverage-maybe-open-file.cc32
-rw-r--r--test/asan/TestCases/Posix/coverage-module-unloaded.cc5
-rw-r--r--test/asan/TestCases/Posix/coverage-sandboxing.cc13
-rw-r--r--test/asan/TestCases/Posix/coverage.cc13
-rw-r--r--test/asan/TestCases/Posix/current_allocated_bytes.cc44
-rw-r--r--test/asan/TestCases/Posix/deep_call_stack.cc25
-rw-r--r--test/asan/TestCases/Posix/deep_thread_stack.cc58
-rw-r--r--test/asan/TestCases/Posix/dlclose-test.cc106
-rw-r--r--test/asan/TestCases/Posix/free_hook_realloc.cc34
-rw-r--r--test/asan/TestCases/Posix/freopen.cc15
-rw-r--r--test/asan/TestCases/Posix/gc-test.cc54
-rw-r--r--test/asan/TestCases/Posix/halt_on_error-signals.c102
-rw-r--r--test/asan/TestCases/Posix/halt_on_error-torture.cc87
-rw-r--r--test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc55
-rw-r--r--test/asan/TestCases/Posix/init-order-pthread-create.cc54
-rw-r--r--test/asan/TestCases/Posix/ioctl.cc4
-rw-r--r--test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc2
-rw-r--r--test/asan/TestCases/Posix/log_path_fork_test.cc.disabled2
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_test.cc4
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc4
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc3
-rw-r--r--test/asan/TestCases/Posix/stack-overflow.cc114
-rw-r--r--test/asan/TestCases/Posix/stack-use-after-return.cc79
-rw-r--r--test/asan/TestCases/Posix/start-deactivated.cc10
-rw-r--r--test/asan/TestCases/Posix/tsd_dtor_leak.cc2
-rw-r--r--test/asan/TestCases/Posix/wait.cc12
-rw-r--r--test/asan/TestCases/Posix/wait3.cc36
38 files changed, 1056 insertions, 67 deletions
diff --git a/test/asan/TestCases/Posix/allow_user_segv.cc b/test/asan/TestCases/Posix/allow_user_segv.cc
index b299ae8cb21e..69c1df9a1d3f 100644
--- a/test/asan/TestCases/Posix/allow_user_segv.cc
+++ b/test/asan/TestCases/Posix/allow_user_segv.cc
@@ -1,8 +1,8 @@
// Regression test for
// https://code.google.com/p/address-sanitizer/issues/detail?id=180
-// RUN: %clangxx_asan -O0 %s -o %t && ASAN_OPTIONS=$ASAN_OPTIONS:allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -O2 %s -o %t && ASAN_OPTIONS=$ASAN_OPTIONS:allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -o %t && %env_asan_opts=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && %env_asan_opts=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
#include <signal.h>
#include <stdio.h>
@@ -55,5 +55,5 @@ int main() {
// CHECK: User sigaction installed
// CHECK-NEXT: User sigaction called
-// CHECK-NEXT: ASAN:SIGSEGV
+// CHECK-NEXT: ASAN:DEADLYSIGNAL
// CHECK: AddressSanitizer: SEGV on unknown address
diff --git a/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc b/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc
new file mode 100644
index 000000000000..22c03e8ddced
--- /dev/null
+++ b/test/asan/TestCases/Posix/asan-symbolize-bad-path.cc
@@ -0,0 +1,4 @@
+// Test that asan_symbolize does not hang when provided with an non-existing
+// path.
+// RUN: echo '#0 0xabcdabcd (%T/bad/path+0x1234)' | %asan_symbolize | FileCheck %s
+// CHECK: #0 0xabcdabcd
diff --git a/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
index 043130f9e549..dd59e4a60774 100644
--- a/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
+++ b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
@@ -6,7 +6,7 @@
// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
// RUN: %clangxx_asan -O0 %s %libdl -o %t
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:symbolize=0 not %run %t 2>&1 | %asan_symbolize | FileCheck %s
+// RUN: %env_asan_opts=symbolize=0 not %run %t 2>&1 | %asan_symbolize | FileCheck %s
// XFAIL: arm-linux-gnueabi
// XFAIL: armv7l-unknown-linux-gnueabihf
diff --git a/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc b/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc
index ad547ce0ce1b..8031d04aae48 100644
--- a/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc
+++ b/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc
@@ -2,8 +2,5 @@
// RUN: %clangxx_asan -O3 %s -o %t && %run %t
#include <stdlib.h>
#include <unistd.h>
-#if !defined(__APPLE__) && !defined(__FreeBSD__)
-# include <malloc.h>
-#endif // !__APPLE__ && !__FreeBSD__
-int *p = (int*)valloc(1 << 20);
-int main() { }
+int *p;
+int main() { posix_memalign((void **)&p, 4096, 1 << 20); }
diff --git a/test/asan/TestCases/Posix/closed-fds.cc b/test/asan/TestCases/Posix/closed-fds.cc
new file mode 100644
index 000000000000..3bbe3d8e68e1
--- /dev/null
+++ b/test/asan/TestCases/Posix/closed-fds.cc
@@ -0,0 +1,33 @@
+// Check that when the program closed its std(in|out|err), running the external
+// symbolizer still works.
+
+// RUN: rm -f %t.log.*
+// RUN: %clangxx_asan -O0 %s -o %t 2>&1 && %env_asan_opts=log_path=%t.log:verbosity=2 not %run %t 2>&1
+// RUN: FileCheck %s --check-prefix=CHECK-FILE < %t.log.*
+
+// FIXME: copy %t.log back from the device and re-enable on Android.
+// UNSUPPORTED: android
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ int result = fprintf(stderr, "Closing streams.\n");
+ assert(result > 0);
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ result = fprintf(stderr, "Can you hear me now?\n");
+ assert(result < 0);
+ char *x = (char *)malloc(10 * sizeof(char));
+ free(x);
+ x[argc] = 'X'; // BOOM
+ // CHECK-FILE: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+ // CHECK-FILE: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}}
+ // CHECK-FILE: {{WRITE of size 1 at 0x.* thread T0}}
+ // CHECK-FILE: {{ #0 0x.* in main .*closed-fds.cc:}}[[@LINE-4]]
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/coverage-caller-callee.cc b/test/asan/TestCases/Posix/coverage-caller-callee.cc
new file mode 100644
index 000000000000..fb8b9bf92af2
--- /dev/null
+++ b/test/asan/TestCases/Posix/coverage-caller-callee.cc
@@ -0,0 +1,75 @@
+// Test caller-callee coverage with large number of threads
+// and various numbers of callers and callees.
+
+// RUN: %clangxx_asan -fsanitize-coverage=edge,indirect-calls %s -o %t
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 10 1 2>&1 | FileCheck %s --check-prefix=CHECK-10-1
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 9 2 2>&1 | FileCheck %s --check-prefix=CHECK-9-2
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 7 3 2>&1 | FileCheck %s --check-prefix=CHECK-7-3
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 17 1 2>&1 | FileCheck %s --check-prefix=CHECK-17-1
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 15 2 2>&1 | FileCheck %s --check-prefix=CHECK-15-2
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 18 3 2>&1 | FileCheck %s --check-prefix=CHECK-18-3
+// RUN: rm -f caller-callee*.sancov
+//
+// REQUIRES: asan-64-bits
+// UNSUPPORTED: android
+//
+// CHECK-10-1: CovDump: 10 caller-callee pairs written
+// CHECK-9-2: CovDump: 18 caller-callee pairs written
+// CHECK-7-3: CovDump: 21 caller-callee pairs written
+// CHECK-17-1: CovDump: 14 caller-callee pairs written
+// CHECK-15-2: CovDump: 28 caller-callee pairs written
+// CHECK-18-3: CovDump: 42 caller-callee pairs written
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+int P = 0;
+struct Foo {virtual void f() {if (P) printf("Foo::f()\n");}};
+struct Foo1 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo2 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo3 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo4 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo5 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo6 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo7 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo8 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo9 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo10 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo11 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo12 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo13 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo14 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo15 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo16 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo17 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo18 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+struct Foo19 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
+
+Foo *foo[20] = {
+ new Foo, new Foo1, new Foo2, new Foo3, new Foo4, new Foo5, new Foo6,
+ new Foo7, new Foo8, new Foo9, new Foo10, new Foo11, new Foo12, new Foo13,
+ new Foo14, new Foo15, new Foo16, new Foo17, new Foo18, new Foo19,
+};
+
+int n_functions = 10;
+int n_callers = 2;
+
+void *Thread(void *arg) {
+ if (n_callers >= 1) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
+ if (n_callers >= 2) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
+ if (n_callers >= 3) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
+ return arg;
+}
+
+int main(int argc, char **argv) {
+ if (argc >= 2)
+ n_functions = atoi(argv[1]);
+ if (argc >= 3)
+ n_callers = atoi(argv[2]);
+ const int kNumThreads = 16;
+ pthread_t t[kNumThreads];
+ for (int i = 0; i < kNumThreads; i++)
+ pthread_create(&t[i], 0, Thread, 0);
+ for (int i = 0; i < kNumThreads; i++)
+ pthread_join(t[i], 0);
+}
diff --git a/test/asan/TestCases/Posix/coverage-direct-activation.cc b/test/asan/TestCases/Posix/coverage-direct-activation.cc
index af73f5d2952d..0af3296f22d4 100644
--- a/test/asan/TestCases/Posix/coverage-direct-activation.cc
+++ b/test/asan/TestCases/Posix/coverage-direct-activation.cc
@@ -7,11 +7,11 @@
// RUN: rm -rf %T/coverage-direct-activation
// RUN: mkdir -p %T/coverage-direct-activation/normal
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1,coverage_direct=0,coverage_dir=%T/coverage-direct-activation/normal:verbosity=1 %run %t %dynamiclib
+// RUN: %env_asan_opts=coverage=1,coverage_direct=0,coverage_dir=%T/coverage-direct-activation/normal:verbosity=1 %run %t %dynamiclib
// RUN: %sancov print %T/coverage-direct-activation/normal/*.sancov >%T/coverage-direct-activation/normal/out.txt
// RUN: mkdir -p %T/coverage-direct-activation/direct
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1,coverage_direct=1,verbosity=1 \
+// RUN: %env_asan_opts=start_deactivated=1,coverage_direct=1,verbosity=1 \
// RUN: ASAN_ACTIVATION_OPTIONS=coverage=1,coverage_dir=%T/coverage-direct-activation/direct %run %t %dynamiclib
// RUN: cd %T/coverage-direct-activation/direct
// RUN: %sancov rawunpack *.sancov.raw
@@ -23,7 +23,7 @@
// RUN: diff -u coverage-direct-activation/normal/out.txt coverage-direct-activation/direct/out.txt
// RUN: mkdir -p %T/coverage-direct-activation/direct2
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1,coverage=1,coverage_direct=1,verbosity=1 \
+// RUN: %env_asan_opts=start_deactivated=1,coverage=1,coverage_direct=1,verbosity=1 \
// RUN: ASAN_ACTIVATION_OPTIONS=coverage_dir=%T/coverage-direct-activation/direct2 %run %t %dynamiclib
// RUN: cd %T/coverage-direct-activation/direct2
// RUN: %sancov rawunpack *.sancov.raw
diff --git a/test/asan/TestCases/Posix/coverage-direct-large.cc b/test/asan/TestCases/Posix/coverage-direct-large.cc
index 2769172c39ab..367a5667a711 100644
--- a/test/asan/TestCases/Posix/coverage-direct-large.cc
+++ b/test/asan/TestCases/Posix/coverage-direct-large.cc
@@ -8,12 +8,12 @@
// RUN: rm -rf %T/coverage-direct-large
// RUN: mkdir -p %T/coverage-direct-large/normal && cd %T/coverage-direct-large/normal
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:coverage_direct=0:verbosity=1 %run %t %dynamiclib
+// RUN: %env_asan_opts=coverage=1:coverage_direct=0:verbosity=1 %run %t %dynamiclib
// RUN: %sancov print *.sancov >out.txt
// RUN: cd ../..
// RUN: mkdir -p %T/coverage-direct-large/direct && cd %T/coverage-direct-large/direct
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:coverage_direct=1:verbosity=1 %run %t %dynamiclib
+// RUN: %env_asan_opts=coverage=1:coverage_direct=1:verbosity=1 %run %t %dynamiclib
// RUN: %sancov rawunpack *.sancov.raw
// RUN: %sancov print *.sancov >out.txt
// RUN: cd ../..
diff --git a/test/asan/TestCases/Posix/coverage-direct.cc b/test/asan/TestCases/Posix/coverage-direct.cc
index 5371a859c24f..8caa9c553f2e 100644
--- a/test/asan/TestCases/Posix/coverage-direct.cc
+++ b/test/asan/TestCases/Posix/coverage-direct.cc
@@ -6,11 +6,11 @@
// RUN: rm -rf %T/coverage-direct
// RUN: mkdir -p %T/coverage-direct/normal
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:coverage_direct=0:coverage_dir=%T/coverage-direct/normal:verbosity=1 %run %t %dynamiclib
+// RUN: %env_asan_opts=coverage=1:coverage_direct=0:coverage_dir=%T/coverage-direct/normal:verbosity=1 %run %t %dynamiclib
// RUN: %sancov print %T/coverage-direct/normal/*.sancov >%T/coverage-direct/normal/out.txt
// RUN: mkdir -p %T/coverage-direct/direct
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:coverage_direct=1:coverage_dir=%T/coverage-direct/direct:verbosity=1 %run %t %dynamiclib
+// RUN: %env_asan_opts=coverage=1:coverage_direct=1:coverage_dir=%T/coverage-direct/direct:verbosity=1 %run %t %dynamiclib
// RUN: cd %T/coverage-direct/direct
// RUN: %sancov rawunpack *.sancov.raw
// RUN: %sancov print *.sancov >out.txt
@@ -25,11 +25,11 @@
// RUN: rm -rf %T/coverage-direct
// RUN: mkdir -p %T/coverage-direct/normal
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:coverage_direct=0:coverage_dir=%T/coverage-direct/normal:verbosity=1 %run %t %dynamiclib
+// RUN: %env_asan_opts=coverage=1:coverage_direct=0:coverage_dir=%T/coverage-direct/normal:verbosity=1 %run %t %dynamiclib
// RUN: %sancov print %T/coverage-direct/normal/*.sancov >%T/coverage-direct/normal/out.txt
// RUN: mkdir -p %T/coverage-direct/direct
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:coverage_direct=1:coverage_dir=%T/coverage-direct/direct:verbosity=1 %run %t %dynamiclib
+// RUN: %env_asan_opts=coverage=1:coverage_direct=1:coverage_dir=%T/coverage-direct/direct:verbosity=1 %run %t %dynamiclib
// RUN: cd %T/coverage-direct/direct
// RUN: %sancov rawunpack *.sancov.raw
// RUN: %sancov print *.sancov >out.txt
@@ -44,11 +44,11 @@
// RUN: rm -rf %T/coverage-direct
// RUN: mkdir -p %T/coverage-direct/normal
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:coverage_direct=0:coverage_dir=%T/coverage-direct/normal:verbosity=1 %run %t %dynamiclib
+// RUN: %env_asan_opts=coverage=1:coverage_direct=0:coverage_dir=%T/coverage-direct/normal:verbosity=1 %run %t %dynamiclib
// RUN: %sancov print %T/coverage-direct/normal/*.sancov >%T/coverage-direct/normal/out.txt
// RUN: mkdir -p %T/coverage-direct/direct
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:coverage_direct=1:coverage_dir=%T/coverage-direct/direct:verbosity=1 %run %t %dynamiclib
+// RUN: %env_asan_opts=coverage=1:coverage_direct=1:coverage_dir=%T/coverage-direct/direct:verbosity=1 %run %t %dynamiclib
// RUN: cd %T/coverage-direct/direct
// RUN: %sancov rawunpack *.sancov.raw
// RUN: %sancov print *.sancov >out.txt
diff --git a/test/asan/TestCases/Posix/coverage-fork-direct.cc b/test/asan/TestCases/Posix/coverage-fork-direct.cc
index 39363911fec3..c19671953809 100644
--- a/test/asan/TestCases/Posix/coverage-fork-direct.cc
+++ b/test/asan/TestCases/Posix/coverage-fork-direct.cc
@@ -1,7 +1,7 @@
// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t
// RUN: rm -rf %T/coverage-fork-direct
// RUN: mkdir -p %T/coverage-fork-direct && cd %T/coverage-fork-direct
-// RUN: (ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:coverage_direct=1:verbosity=1 %run %t; \
+// RUN: (%env_asan_opts=coverage=1:coverage_direct=1:verbosity=1 %run %t; \
// RUN: %sancov rawunpack *.sancov.raw; %sancov print *.sancov) 2>&1
//
// XFAIL: android
diff --git a/test/asan/TestCases/Posix/coverage-fork.cc b/test/asan/TestCases/Posix/coverage-fork.cc
index c1f0fc3a84b8..799d71638a26 100644
--- a/test/asan/TestCases/Posix/coverage-fork.cc
+++ b/test/asan/TestCases/Posix/coverage-fork.cc
@@ -1,8 +1,7 @@
// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t
-// RUN: export ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:coverage_direct=0:verbosity=1
// RUN: rm -rf %T/coverage-fork
// RUN: mkdir -p %T/coverage-fork && cd %T/coverage-fork
-// RUN: %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=coverage=1:coverage_direct=0:verbosity=1 %run %t 2>&1 | FileCheck %s
//
// XFAIL: android
diff --git a/test/asan/TestCases/Posix/coverage-maybe-open-file.cc b/test/asan/TestCases/Posix/coverage-maybe-open-file.cc
new file mode 100644
index 000000000000..cab3d5770aa5
--- /dev/null
+++ b/test/asan/TestCases/Posix/coverage-maybe-open-file.cc
@@ -0,0 +1,32 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t
+// RUN: rm -rf %T/coverage-maybe-open-file
+// RUN: mkdir -p %T/coverage-maybe-open-file && cd %T/coverage-maybe-open-file
+// RUN: %env_asan_opts=coverage=1 %run %t | FileCheck %s --check-prefix=CHECK-success
+// RUN: %env_asan_opts=coverage=0 %run %t | FileCheck %s --check-prefix=CHECK-fail
+// RUN: [ "$(cat test.sancov.packed)" == "test" ]
+// RUN: cd .. && rm -rf %T/coverage-maybe-open-file
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sanitizer/coverage_interface.h>
+
+// FIXME: the code below might not work on Windows.
+int main(int argc, char **argv) {
+ int fd = __sanitizer_maybe_open_cov_file("test");
+ if (fd > 0) {
+ printf("SUCCESS\n");
+ const char s[] = "test\n";
+ write(fd, s, strlen(s));
+ close(fd);
+ } else {
+ printf("FAIL\n");
+ }
+}
+
+// CHECK-success: SUCCESS
+// CHECK-fail: FAIL
diff --git a/test/asan/TestCases/Posix/coverage-module-unloaded.cc b/test/asan/TestCases/Posix/coverage-module-unloaded.cc
index fe08bdd792b1..d492af6662fa 100644
--- a/test/asan/TestCases/Posix/coverage-module-unloaded.cc
+++ b/test/asan/TestCases/Posix/coverage-module-unloaded.cc
@@ -3,10 +3,9 @@
// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED %s -shared -o %dynamiclib1 -fPIC
// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED %s -shared -o %dynamiclib2 -fPIC
// RUN: %clangxx_asan -fsanitize-coverage=func %s %libdl -o %t
-// RUN: export ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:verbosity=1
// RUN: mkdir -p %T/coverage-module-unloaded && cd %T/coverage-module-unloaded
-// RUN: %run %t %dynamiclib1 %dynamiclib2 2>&1 | FileCheck %s
-// RUN: %run %t %dynamiclib1 %dynamiclib2 foo 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t %dynamiclib1 %dynamiclib2 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t %dynamiclib1 %dynamiclib2 foo 2>&1 | FileCheck %s
// RUN: rm -r %T/coverage-module-unloaded
//
// https://code.google.com/p/address-sanitizer/issues/detail?id=263
diff --git a/test/asan/TestCases/Posix/coverage-sandboxing.cc b/test/asan/TestCases/Posix/coverage-sandboxing.cc
index dd2c1ec43be5..f6fc5266607c 100644
--- a/test/asan/TestCases/Posix/coverage-sandboxing.cc
+++ b/test/asan/TestCases/Posix/coverage-sandboxing.cc
@@ -1,16 +1,16 @@
// RUN: %clangxx_asan -fsanitize-coverage=bb -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so
// RUN: %clangxx_asan -fsanitize-coverage=func %s -o %t %ld_flags_rpath_exe
-// RUN: export ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:verbosity=1
+
// RUN: rm -rf %T/coverage_sandboxing_test
// RUN: mkdir %T/coverage_sandboxing_test && cd %T/coverage_sandboxing_test
// RUN: mkdir vanilla && cd vanilla
-// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-vanilla
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-vanilla
// RUN: mkdir ../sandbox1 && cd ../sandbox1
-// RUN: %run %t a 2>&1 | FileCheck %s --check-prefix=CHECK-sandbox
-// RUN: %sancov unpack coverage_sandboxing_test.sancov.packed
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t a 2>&1 | FileCheck %s --check-prefix=CHECK-sandbox
+// RUN: %sancov unpack coverage_sandboxing_test.sancov.packed
// RUN: mkdir ../sandbox2 && cd ../sandbox2
-// RUN: %run %t a b 2>&1 | FileCheck %s --check-prefix=CHECK-sandbox
-// RUN: %sancov unpack coverage_sandboxing_test.sancov.packed
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t a b 2>&1 | FileCheck %s --check-prefix=CHECK-sandbox
+// RUN: %sancov unpack coverage_sandboxing_test.sancov.packed
// RUN: cd ..
// RUN: %sancov print vanilla/`basename %dynamiclib`*.sancov > vanilla.txt
// RUN: %sancov print sandbox1/`basename %dynamiclib`*.sancov > sandbox1.txt
@@ -18,6 +18,7 @@
// RUN: diff vanilla.txt sandbox1.txt
// RUN: diff vanilla.txt sandbox2.txt
// RUN: rm -r %T/coverage_sandboxing_test
+
// https://code.google.com/p/address-sanitizer/issues/detail?id=263
// XFAIL: android
diff --git a/test/asan/TestCases/Posix/coverage.cc b/test/asan/TestCases/Posix/coverage.cc
index 99e348fdaf9d..7c1c4949f60c 100644
--- a/test/asan/TestCases/Posix/coverage.cc
+++ b/test/asan/TestCases/Posix/coverage.cc
@@ -1,20 +1,19 @@
// RUN: %clangxx_asan -fsanitize-coverage=func -DSHARED %s -shared -o %dynamiclib -fPIC %ld_flags_rpath_so
// RUN: %clangxx_asan -fsanitize-coverage=func %s %ld_flags_rpath_exe -o %t
-// RUN: export ASAN_OPTIONS=$ASAN_OPTIONS:coverage=1:verbosity=1
// RUN: rm -rf %T/coverage && mkdir -p %T/coverage && cd %T/coverage
-// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-main
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-main
// RUN: %sancov print `ls coverage.*sancov | grep -v '.so'` 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV1
-// RUN: %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-foo
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-foo
// RUN: %sancov print `ls coverage.*sancov | grep -v '.so'` 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
-// RUN: %run %t bar 2>&1 | FileCheck %s --check-prefix=CHECK-bar
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t bar 2>&1 | FileCheck %s --check-prefix=CHECK-bar
// RUN: %sancov print `ls *coverage.*sancov | grep -v '.so'` 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
-// RUN: %run %t foo bar 2>&1 | FileCheck %s --check-prefix=CHECK-foo-bar
+// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t foo bar 2>&1 | FileCheck %s --check-prefix=CHECK-foo-bar
// RUN: %sancov print `ls *coverage.*sancov | grep -v '.so'` 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
// RUN: %sancov print `ls *coverage.*sancov | grep '.so'` 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV1
// RUN: %sancov merge `ls *coverage.*sancov | grep -v '.so'` > merged-cov
// RUN: %sancov print merged-cov 2>&1 | FileCheck %s --check-prefix=CHECK-SANCOV2
-// RUN: not %run %t foo bar 4 2>&1 | FileCheck %s --check-prefix=CHECK-report
-// RUN: not %run %t foo bar 4 5 2>&1 | FileCheck %s --check-prefix=CHECK-segv
+// RUN: %env_asan_opts=coverage=1:verbosity=1 not %run %t foo bar 4 2>&1 | FileCheck %s --check-prefix=CHECK-report
+// RUN: %env_asan_opts=coverage=1:verbosity=1 not %run %t foo bar 4 5 2>&1 | FileCheck %s --check-prefix=CHECK-segv
// RUN: rm -r %T/coverage
//
// https://code.google.com/p/address-sanitizer/issues/detail?id=263
diff --git a/test/asan/TestCases/Posix/current_allocated_bytes.cc b/test/asan/TestCases/Posix/current_allocated_bytes.cc
new file mode 100644
index 000000000000..c49e433b1e8b
--- /dev/null
+++ b/test/asan/TestCases/Posix/current_allocated_bytes.cc
@@ -0,0 +1,44 @@
+// RUN: %clangxx_asan -O0 %s -pthread -o %t && %run %t
+// RUN: %clangxx_asan -O2 %s -pthread -o %t && %run %t
+// REQUIRES: stable-runtime
+
+#include <assert.h>
+#include <pthread.h>
+#include <sanitizer/allocator_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+const size_t kLargeAlloc = 1UL << 20;
+
+void* allocate(void *arg) {
+ volatile void *ptr = malloc(kLargeAlloc);
+ free((void*)ptr);
+ return 0;
+}
+
+void* check_stats(void *arg) {
+ assert(__sanitizer_get_current_allocated_bytes() > 0);
+ return 0;
+}
+
+int main() {
+ size_t used_mem = __sanitizer_get_current_allocated_bytes();
+ printf("Before: %zu\n", used_mem);
+ const int kNumIterations = 1000;
+ for (int iter = 0; iter < kNumIterations; iter++) {
+ pthread_t thr[4];
+ for (int j = 0; j < 4; j++) {
+ assert(0 ==
+ pthread_create(&thr[j], 0, (j < 2) ? allocate : check_stats, 0));
+ }
+ for (int j = 0; j < 4; j++)
+ assert(0 == pthread_join(thr[j], 0));
+ used_mem = __sanitizer_get_current_allocated_bytes();
+ if (used_mem > kLargeAlloc) {
+ printf("After iteration %d: %zu\n", iter, used_mem);
+ return 1;
+ }
+ }
+ printf("Success after %d iterations\n", kNumIterations);
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/deep_call_stack.cc b/test/asan/TestCases/Posix/deep_call_stack.cc
new file mode 100644
index 000000000000..18ba563dbd21
--- /dev/null
+++ b/test/asan/TestCases/Posix/deep_call_stack.cc
@@ -0,0 +1,25 @@
+// Check that UAR mode can handle very deep recusrion.
+// RUN: %clangxx_asan -O2 %s -o %t && \
+// RUN: (ulimit -s 4096; %env_asan_opts=detect_stack_use_after_return=1 %run %t) 2>&1 | FileCheck %s
+
+// Also check that use_sigaltstack+verbosity doesn't crash.
+// RUN: %env_asan_opts=verbosity=1:use_sigaltstack=1:detect_stack_use_after_return=1 %run %t | FileCheck %s
+#include <stdio.h>
+
+__attribute__((noinline))
+void RecursiveFunc(int depth, int *ptr) {
+ if ((depth % 1000) == 0)
+ printf("[%05d] ptr: %p\n", depth, ptr);
+ if (depth == 0)
+ return;
+ int local;
+ RecursiveFunc(depth - 1, &local);
+}
+
+int main(int argc, char **argv) {
+ RecursiveFunc(15000, 0);
+ return 0;
+}
+// CHECK: [15000] ptr:
+// CHECK: [07000] ptr:
+// CHECK: [00000] ptr:
diff --git a/test/asan/TestCases/Posix/deep_thread_stack.cc b/test/asan/TestCases/Posix/deep_thread_stack.cc
new file mode 100644
index 000000000000..535da79ff58d
--- /dev/null
+++ b/test/asan/TestCases/Posix/deep_thread_stack.cc
@@ -0,0 +1,58 @@
+// RUN: %clangxx_asan -O0 %s -pthread -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -pthread -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -pthread -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -pthread -o %t && not %run %t 2>&1 | FileCheck %s
+// REQUIRES: stable-runtime
+
+#include <pthread.h>
+
+int *x;
+
+void *AllocThread(void *arg) {
+ x = new int;
+ *x = 42;
+ return NULL;
+}
+
+void *FreeThread(void *arg) {
+ delete x;
+ return NULL;
+}
+
+void *AccessThread(void *arg) {
+ *x = 43; // BOOM
+ return NULL;
+}
+
+typedef void* (*callback_type)(void* arg);
+
+void *RunnerThread(void *function) {
+ pthread_t thread;
+ pthread_create(&thread, NULL, (callback_type)function, NULL);
+ pthread_join(thread, NULL);
+ return NULL;
+}
+
+void RunThread(callback_type function) {
+ pthread_t runner;
+ pthread_create(&runner, NULL, RunnerThread, (void*)function);
+ pthread_join(runner, NULL);
+}
+
+int main(int argc, char *argv[]) {
+ RunThread(AllocThread);
+ RunThread(FreeThread);
+ RunThread(AccessThread);
+ return (x != 0);
+}
+
+// CHECK: AddressSanitizer: heap-use-after-free
+// CHECK: WRITE of size 4 at 0x{{.*}} thread T[[ACCESS_THREAD:[0-9]+]]
+// CHECK: freed by thread T[[FREE_THREAD:[0-9]+]] here:
+// CHECK: previously allocated by thread T[[ALLOC_THREAD:[0-9]+]] here:
+// CHECK: Thread T[[ACCESS_THREAD]] created by T[[ACCESS_RUNNER:[0-9]+]] here:
+// CHECK: Thread T[[ACCESS_RUNNER]] created by T0 here:
+// CHECK: Thread T[[FREE_THREAD]] created by T[[FREE_RUNNER:[0-9]+]] here:
+// CHECK: Thread T[[FREE_RUNNER]] created by T0 here:
+// CHECK: Thread T[[ALLOC_THREAD]] created by T[[ALLOC_RUNNER:[0-9]+]] here:
+// CHECK: Thread T[[ALLOC_RUNNER]] created by T0 here:
diff --git a/test/asan/TestCases/Posix/dlclose-test.cc b/test/asan/TestCases/Posix/dlclose-test.cc
new file mode 100644
index 000000000000..369abd3127cc
--- /dev/null
+++ b/test/asan/TestCases/Posix/dlclose-test.cc
@@ -0,0 +1,106 @@
+// Regression test for
+// http://code.google.com/p/address-sanitizer/issues/detail?id=19
+// Bug description:
+// 1. application dlopens foo.so
+// 2. asan registers all globals from foo.so
+// 3. application dlcloses foo.so
+// 4. application mmaps some memory to the location where foo.so was before
+// 5. application starts using this mmaped memory, but asan still thinks there
+// are globals.
+// 6. BOOM
+
+// This sublte test assumes that after a foo.so is dlclose-d
+// we can mmap the region of memory that has been occupied by the library.
+// It works on i368/x86_64 Linux, but not necessary anywhere else.
+// REQUIRES: x86_64-supported-target,i386-supported-target
+
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O0 %s %libdl -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O1 %s %libdl -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O2 %s %libdl -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O3 %s %libdl -o %t && %run %t 2>&1 | FileCheck %s
+
+#if !defined(SHARED_LIB)
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <string>
+
+#if defined(__FreeBSD__)
+// The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
+// that, it was never implemented. So just define it to zero.
+#undef MAP_NORESERVE
+#define MAP_NORESERVE 0
+#endif
+
+using std::string;
+
+typedef int *(fun_t)();
+
+int main(int argc, char *argv[]) {
+ string path = string(argv[0]) + "-so.so";
+ size_t PageSize = sysconf(_SC_PAGESIZE);
+ printf("opening %s ... \n", path.c_str());
+ void *lib = dlopen(path.c_str(), RTLD_NOW);
+ if (!lib) {
+ printf("error in dlopen(): %s\n", dlerror());
+ return 1;
+ }
+ fun_t *get = (fun_t*)dlsym(lib, "get_address_of_static_var");
+ if (!get) {
+ printf("failed dlsym\n");
+ return 1;
+ }
+ int *addr = get();
+ assert(((size_t)addr % 32) == 0); // should be 32-byte aligned.
+ printf("addr: %p\n", addr);
+ addr[0] = 1; // make sure we can write there.
+
+ // Now dlclose the shared library.
+ printf("attempting to dlclose\n");
+ if (dlclose(lib)) {
+ printf("failed to dlclose\n");
+ return 1;
+ }
+ // Now, the page where 'addr' is unmapped. Map it.
+ size_t page_beg = ((size_t)addr) & ~(PageSize - 1);
+ void *res = mmap((void*)(page_beg), PageSize,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, -1, 0);
+ if (res == (char*)-1L) {
+ printf("failed to mmap\n");
+ return 1;
+ }
+ addr[1] = 2; // BOOM (if the bug is not fixed).
+ printf("PASS\n");
+ // CHECK: PASS
+ return 0;
+}
+#else // SHARED_LIB
+#include <stdio.h>
+
+static int pad1;
+static int static_var;
+static int pad2;
+
+extern "C"
+int *get_address_of_static_var() {
+ return &static_var;
+}
+
+__attribute__((constructor))
+void at_dlopen() {
+ printf("%s: I am being dlopened\n", __FILE__);
+}
+__attribute__((destructor))
+void at_dlclose() {
+ printf("%s: I am being dlclosed\n", __FILE__);
+}
+#endif // SHARED_LIB
diff --git a/test/asan/TestCases/Posix/free_hook_realloc.cc b/test/asan/TestCases/Posix/free_hook_realloc.cc
new file mode 100644
index 000000000000..cbc5d6fed56e
--- /dev/null
+++ b/test/asan/TestCases/Posix/free_hook_realloc.cc
@@ -0,0 +1,34 @@
+// Check that free hook doesn't conflict with Realloc.
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: %run %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sanitizer/allocator_interface.h>
+
+static void *glob_ptr;
+
+extern "C" {
+void __sanitizer_free_hook(const volatile void *ptr) {
+ if (ptr == glob_ptr) {
+ *(int*)ptr = 0;
+ write(1, "FreeHook\n", sizeof("FreeHook\n"));
+ }
+}
+}
+
+int main() {
+ int *x = (int*)malloc(100);
+ x[0] = 42;
+ glob_ptr = x;
+ int *y = (int*)realloc(x, 200);
+ // Verify that free hook was called and didn't spoil the memory.
+ if (y[0] != 42) {
+ _exit(1);
+ }
+ write(1, "Passed\n", sizeof("Passed\n"));
+ free(y);
+ // CHECK: FreeHook
+ // CHECK: Passed
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/freopen.cc b/test/asan/TestCases/Posix/freopen.cc
new file mode 100644
index 000000000000..c137abb8fcb8
--- /dev/null
+++ b/test/asan/TestCases/Posix/freopen.cc
@@ -0,0 +1,15 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t
+
+// This fails on i386 Linux due to a glibc versioned symbols mixup.
+// REQUIRES: asan-64-bits
+
+#include <assert.h>
+#include <stdio.h>
+
+int main() {
+ FILE *fp = fopen("/dev/null", "w");
+ assert(fp);
+ freopen(NULL, "a", fp);
+ fclose(fp);
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/gc-test.cc b/test/asan/TestCases/Posix/gc-test.cc
new file mode 100644
index 000000000000..56d8c398fc75
--- /dev/null
+++ b/test/asan/TestCases/Posix/gc-test.cc
@@ -0,0 +1,54 @@
+// RUN: %clangxx_asan %s -pthread -o %t
+// RUN: %env_asan_opts=detect_stack_use_after_return=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
+// RUN: %env_asan_opts=detect_stack_use_after_return=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
+// RUN: %clangxx_asan -O3 %s -pthread -o %t
+// RUN: %env_asan_opts=detect_stack_use_after_return=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1
+// RUN: %env_asan_opts=detect_stack_use_after_return=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0
+// REQUIRES: stable-runtime
+
+#include <assert.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <sanitizer/asan_interface.h>
+
+static const int kNumThreads = 2;
+static const int kLeftRedzoneSize = sizeof(void *) * 4;
+
+void *Thread(void *unused) {
+ void *fake_stack = __asan_get_current_fake_stack();
+ char var[15];
+ if (fake_stack) {
+ fprintf(stderr, "fake stack found: %p; var: %p\n", fake_stack, var);
+ // CHECK1: fake stack found
+ // CHECK1: fake stack found
+ void *beg, *end;
+ void *real_stack =
+ __asan_addr_is_in_fake_stack(fake_stack, &var[0], &beg, &end);
+ assert(real_stack);
+ assert((char*)beg <= (char*)&var[0]);
+ assert((char*)end > (char*)&var[0]);
+ for (int i = -kLeftRedzoneSize; i < 15; i++) {
+ void *beg1, *end1;
+ char *ptr = &var[0] + i;
+ void *real_stack1 =
+ __asan_addr_is_in_fake_stack(fake_stack, ptr, &beg1, &end1);
+ assert(real_stack == real_stack1);
+ assert(beg == beg1);
+ assert(end == end1);
+ }
+ } else {
+ fprintf(stderr, "no fake stack\n");
+ // CHECK0: no fake stack
+ // CHECK0: no fake stack
+ }
+ return NULL;
+}
+
+int main(int argc, char **argv) {
+ pthread_t t[kNumThreads];
+ for (int i = 0; i < kNumThreads; i++)
+ pthread_create(&t[i], 0, Thread, 0);
+ for (int i = 0; i < kNumThreads; i++)
+ pthread_join(t[i], 0);
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/halt_on_error-signals.c b/test/asan/TestCases/Posix/halt_on_error-signals.c
new file mode 100644
index 000000000000..60916f6570fc
--- /dev/null
+++ b/test/asan/TestCases/Posix/halt_on_error-signals.c
@@ -0,0 +1,102 @@
+// Test interaction of Asan recovery mode with asynch signals.
+//
+// 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
+// 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
+
+#define _SVID_SOURCE 1 // SA_NODEFER
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <time.h>
+#include <signal.h>
+
+#include <sanitizer/asan_interface.h>
+
+void random_delay(unsigned *seed) {
+ *seed = 1664525 * *seed + 1013904223;
+ struct timespec delay = { 0, (*seed % 1000) * 1000 };
+ nanosleep(&delay, 0);
+}
+
+volatile char bad[2] = {1, };
+
+void error() {
+ // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting
+ // CHECK-NO-COLLISION: AddressSanitizer: use-after-poison
+ volatile int idx = 0;
+ bad[idx] = 0;
+}
+
+#define CHECK_CALL(e, msg) do { \
+ if (0 != (e)) { \
+ fprintf(stderr, "Failed to " msg "\n"); \
+ exit(1); \
+ } \
+} while (0)
+
+size_t niter = 10;
+pthread_t sender_tid, receiver_tid;
+
+pthread_mutex_t keep_alive_mu = PTHREAD_MUTEX_INITIALIZER;
+
+void *sender(void *arg) {
+ unsigned seed = 0;
+ for (size_t i = 0; i < niter; ++i) {
+ random_delay(&seed);
+ CHECK_CALL(pthread_kill(receiver_tid, SIGUSR1), "send signal");
+ }
+ return 0;
+}
+
+void handler(int sig) {
+ // Expect error collisions here
+ error();
+}
+
+void *receiver(void *arg) {
+ unsigned seed = 1;
+ for (size_t i = 0; i < niter; ++i) {
+ random_delay(&seed);
+ // And here
+ error();
+ }
+ // Parent will release this when it's ok to terminate
+ CHECK_CALL(pthread_mutex_lock(&keep_alive_mu), "unlock mutex");
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ fprintf(stderr, "Syntax: %s niter\n", argv[0]);
+ exit(1);
+ }
+
+ niter = (size_t)strtoul(argv[1], 0, 0);
+
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = handler;
+ sa.sa_flags = SA_NODEFER; // Enable nested handlers to add more stress
+ CHECK_CALL(sigaction(SIGUSR1, &sa, 0), "set sighandler");
+
+ __asan_poison_memory_region(&bad, sizeof(bad));
+
+ CHECK_CALL(pthread_mutex_lock(&keep_alive_mu), "lock mutex");
+ CHECK_CALL(pthread_create(&receiver_tid, 0, receiver, 0), "start thread");
+ CHECK_CALL(pthread_create(&sender_tid, 0, sender, 0), "start thread");
+ CHECK_CALL(pthread_join(sender_tid, 0), "join thread");
+ // Now allow receiver to die
+ CHECK_CALL(pthread_mutex_unlock(&keep_alive_mu), "unlock mutex");
+ CHECK_CALL(pthread_join(receiver_tid, 0), "join thread");
+
+ // CHECK-NO-COLLISION: All threads terminated
+ printf("All threads terminated\n");
+
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/halt_on_error-torture.cc b/test/asan/TestCases/Posix/halt_on_error-torture.cc
new file mode 100644
index 000000000000..019f7d126a47
--- /dev/null
+++ b/test/asan/TestCases/Posix/halt_on_error-torture.cc
@@ -0,0 +1,87 @@
+// Stress test recovery mode with many threads.
+//
+// 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: 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
+// This one is racy although _very_ unlikely to fail:
+// RUN: FileCheck %s < 10.txt
+// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 1.txt || 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 %run %t 10 20 >10.txt 2>&1 || true
+// This one is racy although _very_ unlikely to fail:
+// RUN: FileCheck %s < 10.txt
+// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 1.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <time.h>
+
+#include <sanitizer/asan_interface.h>
+
+size_t nthreads = 10;
+size_t niter = 10;
+
+void random_delay(unsigned *seed) {
+ *seed = 1664525 * *seed + 1013904223;
+ struct timespec delay = { 0, (*seed % 1000) * 1000 };
+ nanosleep(&delay, 0);
+}
+
+void *run(void *arg) {
+ unsigned seed = (unsigned)(size_t)arg;
+
+ volatile char tmp[2];
+ __asan_poison_memory_region(&tmp, sizeof(tmp));
+
+ for (size_t i = 0; i < niter; ++i) {
+ random_delay(&seed);
+ // Expect error collisions here
+ // CHECK: ERROR: AddressSanitizer: use-after-poison
+ volatile int idx = 0;
+ tmp[idx] = 0;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ if (argc != 3) {
+ fprintf(stderr, "Syntax: %s nthreads niter\n", argv[0]);
+ exit(1);
+ }
+
+ nthreads = (size_t)strtoul(argv[1], 0, 0);
+ niter = (size_t)strtoul(argv[2], 0, 0);
+
+ pthread_t *tids = new pthread_t[nthreads];
+
+ for (size_t i = 0; i < nthreads; ++i) {
+ if (0 != pthread_create(&tids[i], 0, run, (void *)i)) {
+ fprintf(stderr, "Failed to create thread\n");
+ exit(1);
+ }
+ }
+
+ for (size_t i = 0; i < nthreads; ++i) {
+ if (0 != pthread_join(tids[i], 0)) {
+ fprintf(stderr, "Failed to join thread\n");
+ exit(1);
+ }
+ }
+
+ // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting
+ // CHECK-NO-COLLISION: All threads terminated
+ printf("All threads terminated\n");
+
+ delete [] tids;
+
+ return 0;
+}
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
new file mode 100644
index 000000000000..98b034812ef6
--- /dev/null
+++ b/test/asan/TestCases/Posix/halt_on_error_suppress_equal_pcs.cc
@@ -0,0 +1,55 @@
+// Test reports dedupication for recovery mode.
+//
+// RUN: %clang_asan -fsanitize-recover=address %s -o %t
+//
+// Check for reports dedupication.
+// 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: [ $(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: [ $(grep -c 'ERROR: AddressSanitizer: stack-buffer-overflow' %t2.log) -eq 30 ]
+
+#define ACCESS_ARRAY_FIVE_ELEMENTS(array, i) \
+ array[i] = i; \
+ array[i + 1] = i + 1; \
+ array[i + 2] = i + 2; \
+ array[i + 3] = i + 3; \
+ array[i + 4] = i + 4; \
+
+volatile int ten = 10;
+unsigned kNumIterations = 10;
+
+int main(int argc, char **argv) {
+ char a[10];
+ char b[10];
+
+ if (argc == 1) {
+ for (int i = 0; i < kNumIterations; ++i) {
+ // CHECK: READ of size 1
+ volatile int res = a[ten + i];
+ // CHECK: WRITE of size 1
+ a[i + ten] = res + 3;
+ // CHECK: READ of size 1
+ res = a[ten + i];
+ // CHECK-NOT: ERROR
+ }
+ } else {
+ for (int i = 0; i < kNumIterations; ++i) {
+ ACCESS_ARRAY_FIVE_ELEMENTS(a, ten);
+ ACCESS_ARRAY_FIVE_ELEMENTS(a, ten + 5);
+ ACCESS_ARRAY_FIVE_ELEMENTS(a, ten + 10);
+ ACCESS_ARRAY_FIVE_ELEMENTS(b, ten);
+ ACCESS_ARRAY_FIVE_ELEMENTS(b, ten + 5);
+ ACCESS_ARRAY_FIVE_ELEMENTS(b, ten + 10);
+ }
+ }
+ return 0;
+}
+
diff --git a/test/asan/TestCases/Posix/init-order-pthread-create.cc b/test/asan/TestCases/Posix/init-order-pthread-create.cc
new file mode 100644
index 000000000000..19c000fec435
--- /dev/null
+++ b/test/asan/TestCases/Posix/init-order-pthread-create.cc
@@ -0,0 +1,54 @@
+// Check that init-order checking is properly disabled if pthread_create is
+// called.
+
+// RUN: %clangxx_asan -c -DCONFIG1 %s -o %t1.o
+// RUN: %clangxx_asan -c %s -o %t2.o
+// RUN: %clangxx_asan -pthread %t1.o %t2.o -o %t
+// RUN: %env_asan_opts=strict_init_order=true %run %t
+
+#ifdef CONFIG1
+
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+
+void *bar(void *input, bool sleep_before_init) {
+ if (sleep_before_init)
+ usleep(500000);
+ return input;
+}
+
+void *glob = bar((void*)0x1234, false);
+extern void *glob2;
+
+void *poll(void *arg) {
+ void **glob = (void**)arg;
+ while (true) {
+ usleep(100000);
+ printf("glob is now: %p\n", *glob);
+ }
+}
+
+struct GlobalPollerStarter {
+ GlobalPollerStarter() {
+ pthread_t p;
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create(&p, 0, poll, &glob);
+ pthread_attr_destroy(&attr);
+ printf("glob poller is started");
+ }
+} global_poller;
+
+int main() {
+ printf("%p %p\n", glob, glob2);
+ return 0;
+}
+
+#else // CONFIG1
+
+void *bar(void *input, bool sleep_before_init);
+void *glob2 = bar((void*)0x2345, true);
+
+#endif
diff --git a/test/asan/TestCases/Posix/ioctl.cc b/test/asan/TestCases/Posix/ioctl.cc
index d25f6ecbee1f..6cf9fa8e3cd3 100644
--- a/test/asan/TestCases/Posix/ioctl.cc
+++ b/test/asan/TestCases/Posix/ioctl.cc
@@ -1,5 +1,5 @@
-// RUN: %clangxx_asan -O0 -g %s -o %t && ASAN_OPTIONS=$ASAN_OPTIONS:handle_ioctl=1 not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -O3 -g %s -o %t && ASAN_OPTIONS=$ASAN_OPTIONS:handle_ioctl=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 -g %s -o %t && %env_asan_opts=handle_ioctl=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 -g %s -o %t && %env_asan_opts=handle_ioctl=1 not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -O0 -g %s -o %t && %run %t
// RUN: %clangxx_asan -O3 -g %s -o %t && %run %t
diff --git a/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc b/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc
index b1c99430c75d..b39fa74a3149 100644
--- a/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc
+++ b/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc
@@ -2,7 +2,7 @@
// RUN: %clangxx_asan %s -o %t
// The memory is released only when the deallocated chunk leaves the quarantine,
// otherwise the mmap(p, ...) call overwrites the malloc header.
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:quarantine_size_mb=0 %run %t
+// RUN: %env_asan_opts=quarantine_size_mb=0 %run %t
#include <assert.h>
#include <string.h>
diff --git a/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled b/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled
index 9f09b78f41c7..029bdd1e3372 100644
--- a/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled
+++ b/test/asan/TestCases/Posix/log_path_fork_test.cc.disabled
@@ -1,7 +1,7 @@
// RUN: %clangxx_asan %s -o %t
// RUN: rm -f %t.log.*
// Set verbosity to 1 so that the log files are opened prior to fork().
-// RUN: env ASAN_OPTIONS="$ASAN_OPTIONS:log_path=%t.log verbosity=1" not %run %t 2> %t.out
+// RUN: %env_asan_opts=log_path='"%t.log"':verbosity=1 not %run %t 2> %t.out
// RUN: for f in %t.log.* ; do FileCheck %s < $f; done
// RUN: [ `ls %t.log.* | wc -l` == 2 ]
diff --git a/test/asan/TestCases/Posix/new_array_cookie_test.cc b/test/asan/TestCases/Posix/new_array_cookie_test.cc
index bc681857ae67..dd50bf7fe6a8 100644
--- a/test/asan/TestCases/Posix/new_array_cookie_test.cc
+++ b/test/asan/TestCases/Posix/new_array_cookie_test.cc
@@ -1,8 +1,8 @@
// REQUIRES: asan-64-bits
// RUN: %clangxx_asan -O3 %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:poison_array_cookie=1 not %run %t 2>&1 | FileCheck %s
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:poison_array_cookie=0 not %run %t 2>&1 | FileCheck %s --check-prefix=NO_COOKIE
+// RUN: %env_asan_opts=poison_array_cookie=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=poison_array_cookie=0 not %run %t 2>&1 | FileCheck %s --check-prefix=NO_COOKIE
#include <stdio.h>
#include <stdlib.h>
struct C {
diff --git a/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc b/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc
index 5998d06756d7..f36da2b5438d 100644
--- a/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc
+++ b/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc
@@ -1,7 +1,7 @@
// REQUIRES: asan-64-bits
// RUN: %clangxx_asan -O3 %s -o %t
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:poison_array_cookie=1 not %run %t 2>&1 | FileCheck %s --check-prefix=COOKIE
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:poison_array_cookie=0 not %run %t 2>&1 | FileCheck %s --check-prefix=NO_COOKIE
+// RUN: %env_asan_opts=poison_array_cookie=1 not %run %t 2>&1 | FileCheck %s --check-prefix=COOKIE
+// RUN: %env_asan_opts=poison_array_cookie=0 not %run %t 2>&1 | FileCheck %s --check-prefix=NO_COOKIE
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
diff --git a/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc b/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc
index 1cea6f68adb2..0683e391cf23 100644
--- a/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc
+++ b/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc
@@ -2,8 +2,7 @@
// inside the class.
// RUN: %clangxx_asan %s -o %t && %run %t
//
-// XFAIL: android
-// XFAIL: armv7l-unknown-linux-gnueabihf
+// XFAIL: arm
#include <new>
#include <stdlib.h>
#include <stdint.h>
diff --git a/test/asan/TestCases/Posix/stack-overflow.cc b/test/asan/TestCases/Posix/stack-overflow.cc
new file mode 100644
index 000000000000..8ef161862499
--- /dev/null
+++ b/test/asan/TestCases/Posix/stack-overflow.cc
@@ -0,0 +1,114 @@
+// Test ASan detection of stack-overflow condition.
+
+// RUN: %clangxx_asan -O0 %s -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -O0 %s -DTHREAD -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DTHREAD -DSMALL_FRAME -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -DTHREAD -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DTHREAD -DSAVE_ALL_THE_REGISTERS -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %s -DTHREAD -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DTHREAD -pthread -o %t && %env_asan_opts=use_sigaltstack=1 not %run %t 2>&1 | FileCheck %s
+// RUN: not %run %t 2>&1 | FileCheck %s
+// REQUIRES: stable-runtime
+
+#include <assert.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sanitizer/asan_interface.h>
+
+const int BS = 1024;
+volatile char x;
+volatile int y = 1;
+volatile int z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13;
+
+void recursive_func(char *p) {
+#if defined(SMALL_FRAME)
+ char *buf = 0;
+#elif defined(SAVE_ALL_THE_REGISTERS)
+ char *buf = 0;
+ int t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13;
+ t0 = z0;
+ t1 = z1;
+ t2 = z2;
+ t3 = z3;
+ t4 = z4;
+ t5 = z5;
+ t6 = z6;
+ t7 = z7;
+ t8 = z8;
+ t9 = z9;
+ t10 = z10;
+ t11 = z11;
+ t12 = z12;
+ t13 = z13;
+
+ z0 = t0;
+ z1 = t1;
+ z2 = t2;
+ z3 = t3;
+ z4 = t4;
+ z5 = t5;
+ z6 = t6;
+ z7 = t7;
+ z8 = t8;
+ z9 = t9;
+ z10 = t10;
+ z11 = t11;
+ z12 = t12;
+ z13 = t13;
+#else
+ char buf[BS];
+ // Check that the stack grows in the righ direction, unless we use fake stack.
+ if (p && !__asan_get_current_fake_stack())
+ assert(p - buf >= BS);
+ buf[rand() % BS] = 1;
+ buf[rand() % BS] = 2;
+ x = buf[rand() % BS];
+#endif
+ if (y)
+ recursive_func(buf);
+ x = 1; // prevent tail call optimization
+ // CHECK: {{stack-overflow on address 0x.* \(pc 0x.* bp 0x.* sp 0x.* T.*\)}}
+ // If stack overflow happens during function prologue, stack trace may be
+ // corrupted. Unwind tables are not always 100% exact there.
+ // For this reason, we don't do any further checks.
+}
+
+void *ThreadFn(void* unused) {
+ recursive_func(0);
+ return 0;
+}
+
+void LimitStackAndReexec(int argc, char **argv) {
+ struct rlimit rlim;
+ int res = getrlimit(RLIMIT_STACK, &rlim);
+ assert(res == 0);
+ if (rlim.rlim_cur == RLIM_INFINITY) {
+ rlim.rlim_cur = 256 * 1024;
+ res = setrlimit(RLIMIT_STACK, &rlim);
+ assert(res == 0);
+
+ execv(argv[0], argv);
+ assert(0 && "unreachable");
+ }
+}
+
+int main(int argc, char **argv) {
+ LimitStackAndReexec(argc, argv);
+#ifdef THREAD
+ pthread_t t;
+ pthread_create(&t, 0, ThreadFn, 0);
+ pthread_join(t, 0);
+#else
+ recursive_func(0);
+#endif
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/stack-use-after-return.cc b/test/asan/TestCases/Posix/stack-use-after-return.cc
new file mode 100644
index 000000000000..cf114be97d51
--- /dev/null
+++ b/test/asan/TestCases/Posix/stack-use-after-return.cc
@@ -0,0 +1,79 @@
+// RUN: %clangxx_asan -O0 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=detect_stack_use_after_return=0 %run %t
+// Regression test for a CHECK failure with small stack size and large frame.
+// RUN: %clangxx_asan -O3 %s -pthread -o %t -DkSize=10000 -DUseThread -DkStackSize=65536 && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s
+//
+// Test that we can find UAR in a thread other than main:
+// RUN: %clangxx_asan -DUseThread -O2 %s -pthread -o %t && %env_asan_opts=detect_stack_use_after_return=1 not %run %t 2>&1 | FileCheck --check-prefix=THREAD %s
+//
+// Test the max_uar_stack_size_log/min_uar_stack_size_log flag.
+//
+// RUN: %env_asan_opts=detect_stack_use_after_return=1:max_uar_stack_size_log=20:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-20 %s
+// RUN: %env_asan_opts=detect_stack_use_after_return=1:min_uar_stack_size_log=24:max_uar_stack_size_log=24:verbosity=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-24 %s
+
+#include <stdio.h>
+#include <pthread.h>
+
+#ifndef kSize
+# define kSize 1
+#endif
+
+#ifndef UseThread
+# define UseThread 0
+#endif
+
+#ifndef kStackSize
+# define kStackSize 0
+#endif
+
+__attribute__((noinline))
+char *Ident(char *x) {
+ fprintf(stderr, "1: %p\n", x);
+ return x;
+}
+
+__attribute__((noinline))
+char *Func1() {
+ char local[kSize];
+ return Ident(local);
+}
+
+__attribute__((noinline))
+void Func2(char *x) {
+ fprintf(stderr, "2: %p\n", x);
+ *x = 1;
+ // CHECK: WRITE of size 1 {{.*}} thread T0
+ // CHECK: #0{{.*}}Func2{{.*}}stack-use-after-return.cc:[[@LINE-2]]
+ // CHECK: is located in stack of thread T0 at offset
+ // CHECK: 'local' <== Memory access at offset {{16|32}} is inside this variable
+ // THREAD: WRITE of size 1 {{.*}} thread T{{[1-9]}}
+ // THREAD: #0{{.*}}Func2{{.*}}stack-use-after-return.cc:[[@LINE-6]]
+ // THREAD: is located in stack of thread T{{[1-9]}} at offset
+ // THREAD: 'local' <== Memory access at offset {{16|32}} is inside this variable
+ // CHECK-20: T0: FakeStack created:{{.*}} stack_size_log: 20
+ // CHECK-24: T0: FakeStack created:{{.*}} stack_size_log: 24
+}
+
+void *Thread(void *unused) {
+ Func2(Func1());
+ return NULL;
+}
+
+int main(int argc, char **argv) {
+#if UseThread
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ if (kStackSize > 0)
+ pthread_attr_setstacksize(&attr, kStackSize);
+ pthread_t t;
+ pthread_create(&t, &attr, Thread, 0);
+ pthread_attr_destroy(&attr);
+ pthread_join(t, 0);
+#else
+ Func2(Func1());
+#endif
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/start-deactivated.cc b/test/asan/TestCases/Posix/start-deactivated.cc
index 2ca8015fc742..b30141549014 100644
--- a/test/asan/TestCases/Posix/start-deactivated.cc
+++ b/test/asan/TestCases/Posix/start-deactivated.cc
@@ -5,17 +5,17 @@
// 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 %t.o %libdl -o %t
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1,allocator_may_return_null=0 \
+// 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 --check-prefix=CHECK
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1 \
+// RUN: %env_asan_opts=start_deactivated=1 \
// RUN: ASAN_ACTIVATION_OPTIONS=help=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-HELP
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1,verbosity=1 \
+// RUN: %env_asan_opts=start_deactivated=1,verbosity=1 \
// RUN: ASAN_ACTIVATION_OPTIONS=help=1,handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORTED
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1 \
+// RUN: %env_asan_opts=start_deactivated=1 \
// RUN: ASAN_ACTIVATION_OPTIONS=help=1,handle_segv=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORTED-V0
// Check that verbosity=1 in activation flags affects reporting of unrecognized activation flags.
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1 \
+// RUN: %env_asan_opts=start_deactivated=1 \
// RUN: ASAN_ACTIVATION_OPTIONS=help=1,handle_segv=0,verbosity=1 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-UNSUPPORTED
// XFAIL: arm-linux-gnueabi
diff --git a/test/asan/TestCases/Posix/tsd_dtor_leak.cc b/test/asan/TestCases/Posix/tsd_dtor_leak.cc
index 69d28194fb9e..9e71ff61cf02 100644
--- a/test/asan/TestCases/Posix/tsd_dtor_leak.cc
+++ b/test/asan/TestCases/Posix/tsd_dtor_leak.cc
@@ -1,7 +1,7 @@
// Regression test for a leak in tsd:
// https://code.google.com/p/address-sanitizer/issues/detail?id=233
// RUN: %clangxx_asan -O1 %s -pthread -o %t
-// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:quarantine_size_mb=0 %run %t
+// RUN: %env_asan_opts=quarantine_size_mb=0 %run %t
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/test/asan/TestCases/Posix/wait.cc b/test/asan/TestCases/Posix/wait.cc
index 99d0212acfab..ed6f326b57d6 100644
--- a/test/asan/TestCases/Posix/wait.cc
+++ b/test/asan/TestCases/Posix/wait.cc
@@ -4,12 +4,6 @@
// RUN: %clangxx_asan -DWAITPID -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_asan -DWAITPID -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -DWAIT3 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -DWAIT3 -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
-
-// RUN: %clangxx_asan -DWAIT3_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx_asan -DWAIT3_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
-
#include <assert.h>
#include <sys/wait.h>
@@ -25,12 +19,6 @@ int main(int argc, char **argv) {
res = wait(status);
#elif defined(WAITPID)
res = waitpid(pid, status, WNOHANG);
-#elif defined(WAIT3)
- res = wait3(status, WNOHANG, NULL);
-#elif defined(WAIT3_RUSAGE)
- struct rusage *ru = (struct rusage*)(x + argc * 3);
- int good_status;
- res = wait3(&good_status, WNOHANG, ru);
#endif
// CHECK: stack-buffer-overflow
// CHECK: {{WRITE of size .* at 0x.* thread T0}}
diff --git a/test/asan/TestCases/Posix/wait3.cc b/test/asan/TestCases/Posix/wait3.cc
new file mode 100644
index 000000000000..2da816fed1aa
--- /dev/null
+++ b/test/asan/TestCases/Posix/wait3.cc
@@ -0,0 +1,36 @@
+// RUN: %clangxx_asan -DWAIT3 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT3 -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT3_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT3_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// UNSUPPORTED: android
+
+#include <assert.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ pid_t pid = fork();
+ if (pid) { // parent
+ int x[3];
+ int *status = x + argc * 3;
+ int res;
+#if defined(WAIT3)
+ res = wait3(status, WNOHANG, NULL);
+#elif defined(WAIT3_RUSAGE)
+ struct rusage *ru = (struct rusage*)(x + argc * 3);
+ int good_status;
+ res = wait3(&good_status, WNOHANG, ru);
+#endif
+ // CHECK: stack-buffer-overflow
+ // CHECK: {{WRITE of size .* at 0x.* thread T0}}
+ // CHECK: {{in .*wait}}
+ // CHECK: {{in main .*wait3.cc:}}
+ // CHECK: is located in stack of thread T0 at offset
+ // CHECK: {{in main}}
+ return res == -1 ? 1 : 0;
+ }
+ // child
+ return 0;
+}