aboutsummaryrefslogtreecommitdiff
path: root/lib/asan/lit_tests/TestCases
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asan/lit_tests/TestCases')
-rw-r--r--lib/asan/lit_tests/TestCases/Darwin/interface_symbols_darwin.c41
-rw-r--r--lib/asan/lit_tests/TestCases/Darwin/lit.local.cfg9
-rw-r--r--lib/asan/lit_tests/TestCases/Darwin/malloc_set_zone_name-mprotect.cc51
-rw-r--r--lib/asan/lit_tests/TestCases/Darwin/malloc_zone-protected.cc20
-rw-r--r--lib/asan/lit_tests/TestCases/Darwin/reexec-insert-libraries-env.cc20
-rw-r--r--lib/asan/lit_tests/TestCases/Darwin/unset-insert-libraries-on-exec.cc20
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/blacklist-extra.cc5
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/echo-env.cc19
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/init-order-atexit-extra.cc16
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/init-order-pthread-create-extra.cc2
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist-extra.cc15
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist-extra2.cc4
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist.txt3
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/initialization-bug-extra.cc5
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/initialization-bug-extra2.cc6
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/initialization-constexpr-extra.cc3
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/initialization-nobug-extra.cc9
-rw-r--r--lib/asan/lit_tests/TestCases/Helpers/lit.local.cfg3
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/asan_prelink_test.cc28
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/clone_test.cc44
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/coverage.cc45
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/glob.cc29
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/glob_test_root/aa0
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/glob_test_root/ab0
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/glob_test_root/ba0
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/heap-overflow-large.cc23
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/heavy_uar_test.cc54
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/initialization-bug-any-order.cc36
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/interception_failure_test.cc22
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/interception_malloc_test.cc23
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/interception_readdir_r_test.cc59
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/interception_test.cc22
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c35
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/lit.local.cfg9
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/malloc-in-qsort.cc56
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/malloc_delete_mismatch.cc31
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/overflow-in-qsort.cc51
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/preinit_test.cc27
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/ptrace.cc52
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/rlimit_mmap_test.cc16
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/swapcontext_test.cc90
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/syscalls.cc22
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/time_null_regtest.cc20
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/tsd_dtor_leak.cc39
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/uar_signals.cc70
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/unpoison_tls.cc35
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/zero-base-shadow32.cc24
-rw-r--r--lib/asan/lit_tests/TestCases/Linux/zero-base-shadow64.cc24
-rw-r--r--lib/asan/lit_tests/TestCases/SharedLibs/darwin-dummy-shared-lib-so.cc13
-rw-r--r--lib/asan/lit_tests/TestCases/SharedLibs/dlclose-test-so.cc33
-rw-r--r--lib/asan/lit_tests/TestCases/SharedLibs/init-order-dlopen-so.cc12
-rw-r--r--lib/asan/lit_tests/TestCases/SharedLibs/lit.local.cfg4
-rw-r--r--lib/asan/lit_tests/TestCases/SharedLibs/shared-lib-test-so.cc26
-rw-r--r--lib/asan/lit_tests/TestCases/allocator_returns_null.cc81
-rw-r--r--lib/asan/lit_tests/TestCases/allow_user_segv.cc48
-rw-r--r--lib/asan/lit_tests/TestCases/asan-symbolize-sanity-test.cc39
-rw-r--r--lib/asan/lit_tests/TestCases/assign_large_valloc_to_global.cc8
-rw-r--r--lib/asan/lit_tests/TestCases/atexit_stats.cc13
-rw-r--r--lib/asan/lit_tests/TestCases/blacklist.cc38
-rw-r--r--lib/asan/lit_tests/TestCases/contiguous_container.cc47
-rw-r--r--lib/asan/lit_tests/TestCases/current_allocated_bytes.cc43
-rw-r--r--lib/asan/lit_tests/TestCases/deep_call_stack.cc25
-rw-r--r--lib/asan/lit_tests/TestCases/deep_stack_uaf.cc31
-rw-r--r--lib/asan/lit_tests/TestCases/deep_tail_call.cc20
-rw-r--r--lib/asan/lit_tests/TestCases/deep_thread_stack.cc57
-rw-r--r--lib/asan/lit_tests/TestCases/default_blacklist.cc3
-rw-r--r--lib/asan/lit_tests/TestCases/default_options.cc15
-rw-r--r--lib/asan/lit_tests/TestCases/dlclose-test.cc81
-rw-r--r--lib/asan/lit_tests/TestCases/double-free.cc25
-rw-r--r--lib/asan/lit_tests/TestCases/force_inline_opt0.cc14
-rw-r--r--lib/asan/lit_tests/TestCases/free_hook_realloc.cc32
-rw-r--r--lib/asan/lit_tests/TestCases/global-demangle.cc17
-rw-r--r--lib/asan/lit_tests/TestCases/global-overflow.cc21
-rw-r--r--lib/asan/lit_tests/TestCases/heap-overflow.cc24
-rw-r--r--lib/asan/lit_tests/TestCases/huge_negative_hea_oob.cc13
-rw-r--r--lib/asan/lit_tests/TestCases/init-order-atexit.cc31
-rw-r--r--lib/asan/lit_tests/TestCases/init-order-dlopen.cc57
-rw-r--r--lib/asan/lit_tests/TestCases/init-order-pthread-create.cc32
-rw-r--r--lib/asan/lit_tests/TestCases/initialization-blacklist.cc32
-rw-r--r--lib/asan/lit_tests/TestCases/initialization-bug.cc45
-rw-r--r--lib/asan/lit_tests/TestCases/initialization-constexpr.cc31
-rw-r--r--lib/asan/lit_tests/TestCases/initialization-nobug.cc48
-rw-r--r--lib/asan/lit_tests/TestCases/inline.cc19
-rw-r--r--lib/asan/lit_tests/TestCases/interface_test.cc8
-rw-r--r--lib/asan/lit_tests/TestCases/invalid-free.cc21
-rw-r--r--lib/asan/lit_tests/TestCases/ioctl.cc24
-rw-r--r--lib/asan/lit_tests/TestCases/large_func_test.cc51
-rw-r--r--lib/asan/lit_tests/TestCases/log-path_test.cc39
-rw-r--r--lib/asan/lit_tests/TestCases/log_path_fork_test.cc.disabled22
-rw-r--r--lib/asan/lit_tests/TestCases/lsan_annotations.cc16
-rw-r--r--lib/asan/lit_tests/TestCases/malloc_context_size.cc27
-rw-r--r--lib/asan/lit_tests/TestCases/malloc_fill.cc22
-rw-r--r--lib/asan/lit_tests/TestCases/malloc_hook.cc36
-rw-r--r--lib/asan/lit_tests/TestCases/memcmp_strict_test.cc15
-rw-r--r--lib/asan/lit_tests/TestCases/memcmp_test.cc17
-rw-r--r--lib/asan/lit_tests/TestCases/null_deref.cc19
-rw-r--r--lib/asan/lit_tests/TestCases/on_error_callback.cc16
-rw-r--r--lib/asan/lit_tests/TestCases/partial_right.cc13
-rw-r--r--lib/asan/lit_tests/TestCases/poison_partial.cc19
-rw-r--r--lib/asan/lit_tests/TestCases/print_summary.cc14
-rw-r--r--lib/asan/lit_tests/TestCases/readv.cc32
-rw-r--r--lib/asan/lit_tests/TestCases/sanity_check_pure_c.c19
-rw-r--r--lib/asan/lit_tests/TestCases/shared-lib-test.cc42
-rw-r--r--lib/asan/lit_tests/TestCases/sleep_before_dying.c10
-rw-r--r--lib/asan/lit_tests/TestCases/stack-buffer-overflow-with-position.cc45
-rw-r--r--lib/asan/lit_tests/TestCases/stack-frame-demangle.cc22
-rw-r--r--lib/asan/lit_tests/TestCases/stack-oob-frames.cc59
-rw-r--r--lib/asan/lit_tests/TestCases/stack-overflow.cc16
-rw-r--r--lib/asan/lit_tests/TestCases/stack-use-after-return.cc77
-rw-r--r--lib/asan/lit_tests/TestCases/strdup_oob_test.cc19
-rw-r--r--lib/asan/lit_tests/TestCases/strerror_r_test.cc13
-rw-r--r--lib/asan/lit_tests/TestCases/strip_path_prefix.c12
-rw-r--r--lib/asan/lit_tests/TestCases/strncpy-overflow.cc28
-rw-r--r--lib/asan/lit_tests/TestCases/symbolize_callback.cc17
-rw-r--r--lib/asan/lit_tests/TestCases/throw_call_test.cc45
-rw-r--r--lib/asan/lit_tests/TestCases/throw_invoke_test.cc50
-rw-r--r--lib/asan/lit_tests/TestCases/time_interceptor.cc16
-rw-r--r--lib/asan/lit_tests/TestCases/uar_and_exceptions.cc40
-rw-r--r--lib/asan/lit_tests/TestCases/unaligned_loads_and_stores.cc52
-rw-r--r--lib/asan/lit_tests/TestCases/use-after-free-right.cc34
-rw-r--r--lib/asan/lit_tests/TestCases/use-after-free.cc31
-rw-r--r--lib/asan/lit_tests/TestCases/use-after-poison.cc20
-rw-r--r--lib/asan/lit_tests/TestCases/use-after-scope-dtor-order.cc25
-rw-r--r--lib/asan/lit_tests/TestCases/use-after-scope-inlined.cc27
-rw-r--r--lib/asan/lit_tests/TestCases/use-after-scope-nobug.cc14
-rw-r--r--lib/asan/lit_tests/TestCases/use-after-scope-temp.cc29
-rw-r--r--lib/asan/lit_tests/TestCases/use-after-scope.cc16
-rw-r--r--lib/asan/lit_tests/TestCases/wait.cc63
128 files changed, 3567 insertions, 0 deletions
diff --git a/lib/asan/lit_tests/TestCases/Darwin/interface_symbols_darwin.c b/lib/asan/lit_tests/TestCases/Darwin/interface_symbols_darwin.c
new file mode 100644
index 000000000000..b453b64cafd2
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Darwin/interface_symbols_darwin.c
@@ -0,0 +1,41 @@
+// Check the presense of interface symbols in the ASan runtime dylib.
+// If you're changing this file, please also change
+// ../Linux/interface_symbols.c
+
+// RUN: %clang_asan -dead_strip -O2 %s -o %t.exe
+// RUN: rm -f %t.symbols %t.interface
+
+// RUN: nm -g `otool -L %t.exe | grep "asan_osx_dynamic.dylib" | \
+// RUN: tr -d '\011' | \
+// RUN: sed "s/.dylib.*/.dylib/"` \
+// RUN: | grep " T " | sed "s/.* T //" \
+// RUN: | grep "__asan_" | sed "s/___asan_/__asan_/" \
+// RUN: | grep -v "__asan_malloc_hook" \
+// RUN: | grep -v "__asan_free_hook" \
+// RUN: | grep -v "__asan_symbolize" \
+// RUN: | grep -v "__asan_default_options" \
+// RUN: | grep -v "__asan_on_error" > %t.symbols
+
+// RUN: cat %p/../../../asan_interface_internal.h \
+// RUN: | sed "s/\/\/.*//" | sed "s/typedef.*//" \
+// RUN: | grep -v "OPTIONAL" \
+// RUN: | grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" \
+// RUN: > %t.interface
+// RUN: echo __asan_report_load1 >> %t.interface
+// RUN: echo __asan_report_load2 >> %t.interface
+// RUN: echo __asan_report_load4 >> %t.interface
+// RUN: echo __asan_report_load8 >> %t.interface
+// RUN: echo __asan_report_load16 >> %t.interface
+// RUN: echo __asan_report_store1 >> %t.interface
+// RUN: echo __asan_report_store2 >> %t.interface
+// RUN: echo __asan_report_store4 >> %t.interface
+// RUN: echo __asan_report_store8 >> %t.interface
+// RUN: echo __asan_report_store16 >> %t.interface
+// RUN: echo __asan_report_load_n >> %t.interface
+// RUN: echo __asan_report_store_n >> %t.interface
+// RUN: for i in `jot - 0 10`; do echo __asan_stack_malloc_$i >> %t.interface; done
+// RUN: for i in `jot - 0 10`; do echo __asan_stack_free_$i >> %t.interface; done
+
+// RUN: cat %t.interface | sort -u | diff %t.symbols -
+
+int main() { return 0; }
diff --git a/lib/asan/lit_tests/TestCases/Darwin/lit.local.cfg b/lib/asan/lit_tests/TestCases/Darwin/lit.local.cfg
new file mode 100644
index 000000000000..a85dfcd24c08
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Darwin/lit.local.cfg
@@ -0,0 +1,9 @@
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.host_os not in ['Darwin']:
+ config.unsupported = True
diff --git a/lib/asan/lit_tests/TestCases/Darwin/malloc_set_zone_name-mprotect.cc b/lib/asan/lit_tests/TestCases/Darwin/malloc_set_zone_name-mprotect.cc
new file mode 100644
index 000000000000..807a8283e788
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Darwin/malloc_set_zone_name-mprotect.cc
@@ -0,0 +1,51 @@
+// Regression test for a bug in malloc_create_zone()
+// (https://code.google.com/p/address-sanitizer/issues/detail?id=203)
+// The old implementation of malloc_create_zone() didn't always return a
+// page-aligned address, so we can only test on a best-effort basis.
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: %t 2>&1
+
+#include <malloc/malloc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+const int kNumIter = 4096;
+const int kNumZones = 100;
+int main() {
+ char *mem[kNumIter * 2];
+ // Allocate memory chunks from different size classes up to 1 page.
+ // (For the case malloc() returns memory chunks in descending order)
+ for (int i = 0; i < kNumIter; i++) {
+ mem[i] = (char*)malloc(8 * i);
+ }
+ // Try to allocate a page-aligned malloc zone. Otherwise the mprotect() call
+ // in malloc_set_zone_name() will silently fail.
+ malloc_zone_t *zone = NULL;
+ bool aligned = false;
+ for (int i = 0; i < kNumZones; i++) {
+ zone = malloc_create_zone(0, 0);
+ if (((uintptr_t)zone & (~0xfff)) == (uintptr_t)zone) {
+ aligned = true;
+ break;
+ }
+ }
+ if (!aligned) {
+ printf("Warning: couldn't allocate a page-aligned zone.");
+ return 0;
+ }
+ // malloc_set_zone_name() calls mprotect(zone, 4096, PROT_READ | PROT_WRITE),
+ // modifies the zone contents and then calls mprotect(zone, 4096, PROT_READ).
+ malloc_set_zone_name(zone, "foobar");
+ // Allocate memory chunks from different size classes again.
+ for (int i = 0; i < kNumIter; i++) {
+ mem[i + kNumIter] = (char*)malloc(8 * i);
+ }
+ // Access the allocated memory chunks and free them.
+ for (int i = 0; i < kNumIter * 2; i++) {
+ memset(mem[i], 'a', 8 * (i % kNumIter));
+ free(mem[i]);
+ }
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Darwin/malloc_zone-protected.cc b/lib/asan/lit_tests/TestCases/Darwin/malloc_zone-protected.cc
new file mode 100644
index 000000000000..d5f6c7c12e67
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Darwin/malloc_zone-protected.cc
@@ -0,0 +1,20 @@
+// Make sure the zones created by malloc_create_zone() are write-protected.
+#include <malloc/malloc.h>
+#include <stdio.h>
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+
+
+void *pwn(malloc_zone_t *unused_zone, size_t unused_size) {
+ printf("PWNED\n");
+ return NULL;
+}
+
+int main() {
+ malloc_zone_t *zone = malloc_create_zone(0, 0);
+ zone->malloc = pwn;
+ void *v = malloc_zone_malloc(zone, 1);
+ // CHECK-NOT: PWNED
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Darwin/reexec-insert-libraries-env.cc b/lib/asan/lit_tests/TestCases/Darwin/reexec-insert-libraries-env.cc
new file mode 100644
index 000000000000..208fe43ac7e4
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Darwin/reexec-insert-libraries-env.cc
@@ -0,0 +1,20 @@
+// Make sure ASan doesn't hang in an exec loop if DYLD_INSERT_LIBRARIES is set.
+// This is a regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=159
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: %clangxx %p/../SharedLibs/darwin-dummy-shared-lib-so.cc \
+// RUN: -dynamiclib -o darwin-dummy-shared-lib-so.dylib
+
+// FIXME: the following command line may hang in the case of a regression.
+// RUN: DYLD_INSERT_LIBRARIES=darwin-dummy-shared-lib-so.dylib \
+// RUN: %t 2>&1 | FileCheck %s || exit 1
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+ const char kEnvName[] = "DYLD_INSERT_LIBRARIES";
+ printf("%s=%s\n", kEnvName, getenv(kEnvName));
+ // CHECK: {{DYLD_INSERT_LIBRARIES=.*darwin-dummy-shared-lib-so.dylib.*}}
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Darwin/unset-insert-libraries-on-exec.cc b/lib/asan/lit_tests/TestCases/Darwin/unset-insert-libraries-on-exec.cc
new file mode 100644
index 000000000000..fa0dd4f9df88
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Darwin/unset-insert-libraries-on-exec.cc
@@ -0,0 +1,20 @@
+// Make sure ASan removes the runtime library from DYLD_INSERT_LIBRARIES before
+// executing other programs.
+
+// RUN: %clangxx_asan %s -o %t
+// RUN: %clangxx %p/../Helpers/echo-env.cc -o %T/echo-env
+// RUN: %clangxx %p/../SharedLibs/darwin-dummy-shared-lib-so.cc \
+// RUN: -dynamiclib -o %t-darwin-dummy-shared-lib-so.dylib
+
+// Make sure DYLD_INSERT_LIBRARIES doesn't contain the runtime library before
+// execl().
+
+// RUN: %t %T/echo-env >/dev/null 2>&1
+// RUN: DYLD_INSERT_LIBRARIES=%t-darwin-dummy-shared-lib-so.dylib \
+// RUN: %t %T/echo-env 2>&1 | FileCheck %s || exit 1
+#include <unistd.h>
+int main(int argc, char *argv[]) {
+ execl(argv[1], argv[1], "DYLD_INSERT_LIBRARIES", NULL);
+ // CHECK: {{DYLD_INSERT_LIBRARIES = .*darwin-dummy-shared-lib-so.dylib.*}}
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Helpers/blacklist-extra.cc b/lib/asan/lit_tests/TestCases/Helpers/blacklist-extra.cc
new file mode 100644
index 000000000000..627115cdda2b
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/blacklist-extra.cc
@@ -0,0 +1,5 @@
+// This function is broken, but this file is blacklisted
+int externalBrokenFunction(int argc) {
+ char x[10] = {0};
+ return x[argc * 10]; // BOOM
+}
diff --git a/lib/asan/lit_tests/TestCases/Helpers/echo-env.cc b/lib/asan/lit_tests/TestCases/Helpers/echo-env.cc
new file mode 100644
index 000000000000..65e91c155c84
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/echo-env.cc
@@ -0,0 +1,19 @@
+// Helper binary for
+// lit_tests/TestCases/Darwin/unset-insert-libraries-on-exec.cc
+// Prints the environment variable with the given name.
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[]) {
+ if (argc != 2) {
+ printf("Usage: %s ENVNAME\n", argv[0]);
+ exit(1);
+ }
+ const char *value = getenv(argv[1]);
+ if (value) {
+ printf("%s = %s\n", argv[1], value);
+ } else {
+ printf("%s not set.\n", argv[1]);
+ }
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Helpers/init-order-atexit-extra.cc b/lib/asan/lit_tests/TestCases/Helpers/init-order-atexit-extra.cc
new file mode 100644
index 000000000000..e4189d19d099
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/init-order-atexit-extra.cc
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+class C {
+ public:
+ C() { value = 42; }
+ ~C() { }
+ int value;
+};
+
+C c;
+
+void AccessC() {
+ printf("C value: %d\n", c.value);
+}
+
+int main() { return 0; }
diff --git a/lib/asan/lit_tests/TestCases/Helpers/init-order-pthread-create-extra.cc b/lib/asan/lit_tests/TestCases/Helpers/init-order-pthread-create-extra.cc
new file mode 100644
index 000000000000..d4606f0afb52
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/init-order-pthread-create-extra.cc
@@ -0,0 +1,2 @@
+void *bar(void *input);
+void *glob2 = bar((void*)0x2345);
diff --git a/lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist-extra.cc b/lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist-extra.cc
new file mode 100644
index 000000000000..09aed2112d5e
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist-extra.cc
@@ -0,0 +1,15 @@
+int zero_init() { return 0; }
+int badGlobal = zero_init();
+int readBadGlobal() { return badGlobal; }
+
+namespace badNamespace {
+class BadClass {
+ public:
+ BadClass() { value = 0; }
+ int value;
+};
+// Global object with non-trivial constructor.
+BadClass bad_object;
+} // namespace badNamespace
+
+int accessBadObject() { return badNamespace::bad_object.value; }
diff --git a/lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist-extra2.cc b/lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist-extra2.cc
new file mode 100644
index 000000000000..69455a0a6fc9
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist-extra2.cc
@@ -0,0 +1,4 @@
+int zero_init();
+int badSrcGlobal = zero_init();
+int readBadSrcGlobal() { return badSrcGlobal; }
+
diff --git a/lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist.txt b/lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist.txt
new file mode 100644
index 000000000000..83294635622d
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/initialization-blacklist.txt
@@ -0,0 +1,3 @@
+global:*badGlobal*=init
+type:*badNamespace::BadClass*=init
+src:*initialization-blacklist-extra2.cc=init
diff --git a/lib/asan/lit_tests/TestCases/Helpers/initialization-bug-extra.cc b/lib/asan/lit_tests/TestCases/Helpers/initialization-bug-extra.cc
new file mode 100644
index 000000000000..3c4cb411defa
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/initialization-bug-extra.cc
@@ -0,0 +1,5 @@
+// This file simply declares a dynamically initialized var by the name of 'y'.
+int initY() {
+ return 5;
+}
+int y = initY();
diff --git a/lib/asan/lit_tests/TestCases/Helpers/initialization-bug-extra2.cc b/lib/asan/lit_tests/TestCases/Helpers/initialization-bug-extra2.cc
new file mode 100644
index 000000000000..a3d8f190e58b
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/initialization-bug-extra2.cc
@@ -0,0 +1,6 @@
+// 'z' is dynamically initialized global from different TU.
+extern int z;
+int __attribute__((noinline)) initY() {
+ return z + 1;
+}
+int y = initY();
diff --git a/lib/asan/lit_tests/TestCases/Helpers/initialization-constexpr-extra.cc b/lib/asan/lit_tests/TestCases/Helpers/initialization-constexpr-extra.cc
new file mode 100644
index 000000000000..b32466a981b3
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/initialization-constexpr-extra.cc
@@ -0,0 +1,3 @@
+// Constexpr:
+int getCoolestInteger();
+static int coolest_integer = getCoolestInteger();
diff --git a/lib/asan/lit_tests/TestCases/Helpers/initialization-nobug-extra.cc b/lib/asan/lit_tests/TestCases/Helpers/initialization-nobug-extra.cc
new file mode 100644
index 000000000000..886165affd76
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/initialization-nobug-extra.cc
@@ -0,0 +1,9 @@
+// Linker initialized:
+int getAB();
+static int ab = getAB();
+// Function local statics:
+int countCalls();
+static int one = countCalls();
+// Trivial constructor, non-trivial destructor:
+int getStructWithDtorValue();
+static int val = getStructWithDtorValue();
diff --git a/lib/asan/lit_tests/TestCases/Helpers/lit.local.cfg b/lib/asan/lit_tests/TestCases/Helpers/lit.local.cfg
new file mode 100644
index 000000000000..2fc4d99456b0
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Helpers/lit.local.cfg
@@ -0,0 +1,3 @@
+# Sources in this directory are helper files for tests which test functionality
+# involving multiple translation units.
+config.suffixes = []
diff --git a/lib/asan/lit_tests/TestCases/Linux/asan_prelink_test.cc b/lib/asan/lit_tests/TestCases/Linux/asan_prelink_test.cc
new file mode 100644
index 000000000000..0f158c1bb3dd
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/asan_prelink_test.cc
@@ -0,0 +1,28 @@
+// Test if asan works with prelink.
+// It does not actually use prelink, but relies on ld's flag -Ttext-segment
+// or gold's flag -Ttext (we try the first flag first, if that fails we
+// try the second flag).
+//
+// RUN: %clangxx_asan -c %s -o %t.o
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so -Wl,-Ttext-segment=0x3600000000 ||\
+// RUN: %clangxx_asan -DBUILD_SO=1 -fPIC -shared %s -o %t.so -Wl,-Ttext=0x3600000000
+// RUN: %clangxx_asan %t.o %t.so -Wl,-R. -o %t
+// RUN: ASAN_OPTIONS=verbosity=1 %t 2>&1 | FileCheck %s
+
+// REQUIRES: x86_64-supported-target, asan-64-bits
+#if BUILD_SO
+int G;
+int *getG() {
+ return &G;
+}
+#else
+#include <stdio.h>
+extern int *getG();
+int main(int argc, char **argv) {
+ long p = (long)getG();
+ printf("SO mapped at %lx\n", p & ~0xffffffffUL);
+ *getG() = 0;
+}
+#endif
+// CHECK: 0x003000000000, 0x004fffffffff{{.*}} MidMem
+// CHECK: SO mapped at 3600000000
diff --git a/lib/asan/lit_tests/TestCases/Linux/clone_test.cc b/lib/asan/lit_tests/TestCases/Linux/clone_test.cc
new file mode 100644
index 000000000000..0e12f35b400a
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/clone_test.cc
@@ -0,0 +1,44 @@
+// Regression test for:
+// http://code.google.com/p/address-sanitizer/issues/detail?id=37
+
+// RUN: %clangxx_asan -O0 %s -o %t && %t | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && %t | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && %t | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && %t | FileCheck %s
+
+#include <stdio.h>
+#include <sched.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+int Child(void *arg) {
+ char x[32] = {0}; // Stack gets poisoned.
+ printf("Child: %p\n", x);
+ _exit(1); // NoReturn, stack will remain unpoisoned unless we do something.
+}
+
+int main(int argc, char **argv) {
+ const int kStackSize = 1 << 20;
+ char child_stack[kStackSize + 1];
+ char *sp = child_stack + kStackSize; // Stack grows down.
+ printf("Parent: %p\n", sp);
+ pid_t clone_pid = clone(Child, sp, CLONE_FILES | CLONE_VM, NULL, 0, 0, 0);
+ int status;
+ pid_t wait_result = waitpid(clone_pid, &status, __WCLONE);
+ if (wait_result < 0) {
+ perror("waitpid");
+ return 0;
+ }
+ if (wait_result == clone_pid && WIFEXITED(status)) {
+ // Make sure the child stack was indeed unpoisoned.
+ for (int i = 0; i < kStackSize; i++)
+ child_stack[i] = i;
+ int ret = child_stack[argc - 1];
+ printf("PASSED\n");
+ // CHECK: PASSED
+ return ret;
+ }
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/coverage.cc b/lib/asan/lit_tests/TestCases/Linux/coverage.cc
new file mode 100644
index 000000000000..4373e9b13c68
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/coverage.cc
@@ -0,0 +1,45 @@
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSHARED %s -shared -o %t.so -fPIC
+// RUN: %clangxx_asan -mllvm -asan-coverage=1 %s -o %t -Wl,-R. %t.so
+// RUN: export ASAN_OPTIONS=coverage=1:verbosity=1
+// RUN: %t 2>&1 | FileCheck %s --check-prefix=CHECK-main
+// RUN: %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-foo
+// RUN: %t bar 2>&1 | FileCheck %s --check-prefix=CHECK-bar
+// RUN: %t foo bar 2>&1 | FileCheck %s --check-prefix=CHECK-foo-bar
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef SHARED
+void bar() { printf("bar\n"); }
+#else
+__attribute__((noinline))
+void foo() { printf("foo\n"); }
+extern void bar();
+
+int main(int argc, char **argv) {
+ fprintf(stderr, "PID: %d\n", getpid());
+ for (int i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "foo"))
+ foo();
+ if (!strcmp(argv[i], "bar"))
+ bar();
+ }
+}
+#endif
+
+// CHECK-main: PID: [[PID:[0-9]+]]
+// CHECK-main: [[PID]].sancov: 1 PCs written
+// CHECK-main-NOT: .so.[[PID]]
+//
+// CHECK-foo: PID: [[PID:[0-9]+]]
+// CHECK-foo: [[PID]].sancov: 2 PCs written
+// CHECK-foo-NOT: .so.[[PID]]
+//
+// CHECK-bar: PID: [[PID:[0-9]+]]
+// CHECK-bar: [[PID]].sancov: 1 PCs written
+// CHECK-bar: .so.[[PID]].sancov: 1 PCs written
+//
+// CHECK-foo-bar: PID: [[PID:[0-9]+]]
+// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
+// CHECK-foo-bar: so.[[PID]].sancov: 1 PCs written
diff --git a/lib/asan/lit_tests/TestCases/Linux/glob.cc b/lib/asan/lit_tests/TestCases/Linux/glob.cc
new file mode 100644
index 000000000000..123768b099ed
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/glob.cc
@@ -0,0 +1,29 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && %t %p 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <glob.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <string>
+
+
+int main(int argc, char *argv[]) {
+ std::string path = argv[1];
+ std::string pattern = path + "/glob_test_root/*a";
+ printf("pattern: %s\n", pattern.c_str());
+
+ glob_t globbuf;
+ int res = glob(pattern.c_str(), 0, 0, &globbuf);
+
+ printf("%d %s\n", errno, strerror(errno));
+ assert(res == 0);
+ assert(globbuf.gl_pathc == 2);
+ printf("%zu\n", strlen(globbuf.gl_pathv[0]));
+ printf("%zu\n", strlen(globbuf.gl_pathv[1]));
+ globfree(&globbuf);
+ printf("PASS\n");
+ // CHECK: PASS
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/glob_test_root/aa b/lib/asan/lit_tests/TestCases/Linux/glob_test_root/aa
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/glob_test_root/aa
diff --git a/lib/asan/lit_tests/TestCases/Linux/glob_test_root/ab b/lib/asan/lit_tests/TestCases/Linux/glob_test_root/ab
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/glob_test_root/ab
diff --git a/lib/asan/lit_tests/TestCases/Linux/glob_test_root/ba b/lib/asan/lit_tests/TestCases/Linux/glob_test_root/ba
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/glob_test_root/ba
diff --git a/lib/asan/lit_tests/TestCases/Linux/heap-overflow-large.cc b/lib/asan/lit_tests/TestCases/Linux/heap-overflow-large.cc
new file mode 100644
index 000000000000..67e9c3718d59
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/heap-overflow-large.cc
@@ -0,0 +1,23 @@
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=183
+
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: not %t 12 2>&1 | FileCheck %s
+// RUN: not %t 100 2>&1 | FileCheck %s
+// RUN: not %t 10000 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+#include <string.h>
+
+int main(int argc, char *argv[]) {
+ int *x = new int[5];
+ memset(x, 0, sizeof(x[0]) * 5);
+ int index = atoi(argv[1]);
+ int res = x[index];
+ // CHECK: AddressSanitizer: {{(heap-buffer-overflow|SEGV)}}
+ // CHECK: #0 0x{{.*}} in main {{.*}}heap-overflow-large.cc:[[@LINE-2]]
+ // CHECK: AddressSanitizer can not {{(provide additional info|describe address in more detail \(wild memory access suspected\))}}
+ // CHECK: SUMMARY: AddressSanitizer: {{(heap-buffer-overflow|SEGV)}}
+ delete[] x;
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/heavy_uar_test.cc b/lib/asan/lit_tests/TestCases/Linux/heavy_uar_test.cc
new file mode 100644
index 000000000000..27b179e83624
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/heavy_uar_test.cc
@@ -0,0 +1,54 @@
+// RUN: export ASAN_OPTIONS=detect_stack_use_after_return=1
+// RUN: %clangxx_asan -O0 %s -o %t && \
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && \
+// RUN: not %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+__attribute__((noinline))
+char *pretend_to_do_something(char *x) {
+ __asm__ __volatile__("" : : "r" (x) : "memory");
+ return x;
+}
+
+__attribute__((noinline))
+char *LeakStack() {
+ char x[1024];
+ memset(x, 0, sizeof(x));
+ return pretend_to_do_something(x);
+}
+
+template<size_t kFrameSize>
+__attribute__((noinline))
+void RecuriveFunctionWithStackFrame(int depth) {
+ if (depth <= 0) return;
+ char x[kFrameSize];
+ x[0] = depth;
+ pretend_to_do_something(x);
+ RecuriveFunctionWithStackFrame<kFrameSize>(depth - 1);
+}
+
+int main(int argc, char **argv) {
+ int n_iter = argc >= 2 ? atoi(argv[1]) : 1000;
+ int depth = argc >= 3 ? atoi(argv[2]) : 500;
+ for (int i = 0; i < n_iter; i++) {
+ RecuriveFunctionWithStackFrame<10>(depth);
+ RecuriveFunctionWithStackFrame<100>(depth);
+ RecuriveFunctionWithStackFrame<500>(depth);
+ RecuriveFunctionWithStackFrame<1024>(depth);
+ RecuriveFunctionWithStackFrame<2000>(depth);
+ RecuriveFunctionWithStackFrame<5000>(depth);
+ RecuriveFunctionWithStackFrame<10000>(depth);
+ }
+ char *stale_stack = LeakStack();
+ RecuriveFunctionWithStackFrame<1024>(10);
+ stale_stack[100]++;
+ // CHECK: ERROR: AddressSanitizer: stack-use-after-return on address
+ // CHECK: is located in stack of thread T0 at offset 132 in frame
+ // CHECK: in LeakStack(){{.*}}heavy_uar_test.cc:
+ // CHECK: [32, 1056) 'x'
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/initialization-bug-any-order.cc b/lib/asan/lit_tests/TestCases/Linux/initialization-bug-any-order.cc
new file mode 100644
index 000000000000..042a07e428d9
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/initialization-bug-any-order.cc
@@ -0,0 +1,36 @@
+// Test to make sure basic initialization order errors are caught.
+// Check that on Linux initialization order bugs are caught
+// independently on order in which we list source files (if we specify
+// strict init-order checking).
+
+// RUN: %clangxx_asan -O0 %s %p/../Helpers/initialization-bug-extra.cc -o %t
+// RUN: ASAN_OPTIONS=strict_init_order=true not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O0 %p/../Helpers/initialization-bug-extra.cc %s -o %t
+// RUN: ASAN_OPTIONS=strict_init_order=true not %t 2>&1 | FileCheck %s
+
+// Do not test with optimization -- the error may be optimized away.
+
+#include <cstdio>
+
+// 'y' is a dynamically initialized global residing in a different TU. This
+// dynamic initializer will read the value of 'y' before main starts. The
+// result is undefined behavior, which should be caught by initialization order
+// checking.
+extern int y;
+int __attribute__((noinline)) initX() {
+ return y + 1;
+ // CHECK: {{AddressSanitizer: initialization-order-fiasco}}
+ // CHECK: {{READ of size .* at 0x.* thread T0}}
+ // CHECK: {{#0 0x.* in .*initX.* .*initialization-bug-any-order.cc:}}[[@LINE-3]]
+ // CHECK: {{0x.* is located 0 bytes inside of global variable .*y.*}}
+}
+
+// This initializer begins our initialization order problems.
+static int x = initX();
+
+int main() {
+ // ASan should have caused an exit before main runs.
+ printf("PASS\n");
+ // CHECK-NOT: PASS
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/interception_failure_test.cc b/lib/asan/lit_tests/TestCases/Linux/interception_failure_test.cc
new file mode 100644
index 000000000000..9d161aa2dccb
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/interception_failure_test.cc
@@ -0,0 +1,22 @@
+// If user provides his own libc functions, ASan doesn't
+// intercept these functions.
+
+// RUN: %clangxx_asan -O0 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <stdio.h>
+
+extern "C" long strtol(const char *nptr, char **endptr, int base) {
+ fprintf(stderr, "my_strtol_interceptor\n");
+ return 0;
+}
+
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return (int)strtol(x, 0, 10);
+ // CHECK: my_strtol_interceptor
+ // CHECK-NOT: heap-use-after-free
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/interception_malloc_test.cc b/lib/asan/lit_tests/TestCases/Linux/interception_malloc_test.cc
new file mode 100644
index 000000000000..cdd7239ab7bc
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/interception_malloc_test.cc
@@ -0,0 +1,23 @@
+// ASan interceptor can be accessed with __interceptor_ prefix.
+
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+extern "C" void *__interceptor_malloc(size_t size);
+extern "C" void *malloc(size_t size) {
+ write(2, "malloc call\n", sizeof("malloc call\n") - 1);
+ return __interceptor_malloc(size);
+}
+
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return (int)strtol(x, 0, 10);
+ // CHECK: malloc call
+ // CHECK: heap-use-after-free
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/interception_readdir_r_test.cc b/lib/asan/lit_tests/TestCases/Linux/interception_readdir_r_test.cc
new file mode 100644
index 000000000000..198e1f3884dd
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/interception_readdir_r_test.cc
@@ -0,0 +1,59 @@
+// RUN: %clangxx_asan -O0 %s -DTEMP_DIR='"'"%T"'"' -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -DTEMP_DIR='"'"%T"'"' -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -DTEMP_DIR='"'"%T"'"' -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -DTEMP_DIR='"'"%T"'"' -o %t && %t 2>&1 | FileCheck %s
+//
+// RUN: %clangxx_asan -O0 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%T"'"' -o %t && %t 2>&1 | FileCheck %s
+
+#include <dirent.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+int main() {
+ // Ensure the readdir_r interceptor doesn't erroneously mark the entire dirent
+ // as written when the end of the directory pointer is reached.
+ fputs("test1: reading the " TEMP_DIR " directory...\n", stderr);
+ DIR *d = opendir(TEMP_DIR);
+ struct dirent *result = (struct dirent *)(0xfeedbeef);
+ // We assume the temp dir for this test doesn't have crazy long file names.
+ char entry_buffer[4096];
+ memset(entry_buffer, 0xab, sizeof(entry_buffer));
+ unsigned count = 0;
+ do {
+ // Stamp the entry struct to try to trick the interceptor.
+ ((struct dirent *)entry_buffer)->d_reclen = 9999;
+ if (readdir_r(d, (struct dirent *)entry_buffer, &result) != 0)
+ abort();
+ ++count;
+ } while (result != NULL);
+ fprintf(stderr, "read %d entries\n", count);
+ closedir(d);
+ // CHECK: test1: reading the {{.*}} directory...
+ // CHECK-NOT: stack-buffer-overflow
+ // CHECK: read {{.*}} entries
+
+ // Ensure the readdir64_r interceptor doesn't have the bug either.
+ fputs("test2: reading the " TEMP_DIR " directory...\n", stderr);
+ d = opendir(TEMP_DIR);
+ struct dirent64 *result64;
+ memset(entry_buffer, 0xab, sizeof(entry_buffer));
+ count = 0;
+ do {
+ // Stamp the entry struct to try to trick the interceptor.
+ ((struct dirent64 *)entry_buffer)->d_reclen = 9999;
+ if (readdir64_r(d, (struct dirent64 *)entry_buffer, &result64) != 0)
+ abort();
+ ++count;
+ } while (result64 != NULL);
+ fprintf(stderr, "read %d entries\n", count);
+ closedir(d);
+ // CHECK: test2: reading the {{.*}} directory...
+ // CHECK-NOT: stack-buffer-overflow
+ // CHECK: read {{.*}} entries
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/interception_test.cc b/lib/asan/lit_tests/TestCases/Linux/interception_test.cc
new file mode 100644
index 000000000000..2b3316d7dc8a
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/interception_test.cc
@@ -0,0 +1,22 @@
+// ASan interceptor can be accessed with __interceptor_ prefix.
+
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <stdio.h>
+
+extern "C" long __interceptor_strtol(const char *nptr, char **endptr, int base);
+extern "C" long strtol(const char *nptr, char **endptr, int base) {
+ fprintf(stderr, "my_strtol_interceptor\n");
+ return __interceptor_strtol(nptr, endptr, base);
+}
+
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return (int)strtol(x, 0, 10);
+ // CHECK: my_strtol_interceptor
+ // CHECK: heap-use-after-free
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c b/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c
new file mode 100644
index 000000000000..d6ceda7af8b6
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/interface_symbols_linux.c
@@ -0,0 +1,35 @@
+// Check the presense of interface symbols in compiled file.
+
+// RUN: %clang_asan -O2 %s -o %t.exe
+// RUN: nm -D %t.exe | grep " T " | sed "s/.* T //" \
+// RUN: | grep "__asan_" | sed "s/___asan_/__asan_/" \
+// RUN: | grep -v "__asan_malloc_hook" \
+// RUN: | grep -v "__asan_free_hook" \
+// RUN: | grep -v "__asan_symbolize" \
+// RUN: | grep -v "__asan_default_options" \
+// RUN: | grep -v "__asan_stack_" \
+// RUN: | grep -v "__asan_on_error" > %t.symbols
+// RUN: cat %p/../../../asan_interface_internal.h \
+// RUN: | sed "s/\/\/.*//" | sed "s/typedef.*//" \
+// RUN: | grep -v "OPTIONAL" \
+// RUN: | grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" \
+// RUN: > %t.interface
+// RUN: echo __asan_report_load1 >> %t.interface
+// RUN: echo __asan_report_load2 >> %t.interface
+// RUN: echo __asan_report_load4 >> %t.interface
+// RUN: echo __asan_report_load8 >> %t.interface
+// RUN: echo __asan_report_load16 >> %t.interface
+// RUN: echo __asan_report_store1 >> %t.interface
+// RUN: echo __asan_report_store2 >> %t.interface
+// RUN: echo __asan_report_store4 >> %t.interface
+// RUN: echo __asan_report_store8 >> %t.interface
+// RUN: echo __asan_report_store16 >> %t.interface
+// RUN: echo __asan_report_load_n >> %t.interface
+// RUN: echo __asan_report_store_n >> %t.interface
+// RUN: cat %t.interface | sort -u | diff %t.symbols -
+
+// FIXME: nm -D on powerpc somewhy shows ASan interface symbols residing
+// in "initialized data section".
+// REQUIRES: x86_64-supported-target,i386-supported-target
+
+int main() { return 0; }
diff --git a/lib/asan/lit_tests/TestCases/Linux/lit.local.cfg b/lib/asan/lit_tests/TestCases/Linux/lit.local.cfg
new file mode 100644
index 000000000000..57271b8078a4
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/lit.local.cfg
@@ -0,0 +1,9 @@
+def getRoot(config):
+ if not config.parent:
+ return config
+ return getRoot(config.parent)
+
+root = getRoot(config)
+
+if root.host_os not in ['Linux']:
+ config.unsupported = True
diff --git a/lib/asan/lit_tests/TestCases/Linux/malloc-in-qsort.cc b/lib/asan/lit_tests/TestCases/Linux/malloc-in-qsort.cc
new file mode 100644
index 000000000000..3251b35e143c
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/malloc-in-qsort.cc
@@ -0,0 +1,56 @@
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS=fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-FAST
+// RUN: ASAN_OPTIONS=fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-SLOW
+
+// Test how well we unwind in presence of qsort in the stack
+// (i.e. if we can unwind through a function compiled w/o frame pointers).
+// https://code.google.com/p/address-sanitizer/issues/detail?id=137
+
+// Fast unwinder is only avaliable on x86_64 and i386.
+// REQUIRES: x86_64-supported-target
+
+// REQUIRES: compiler-rt-optimized
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int *GlobalPtr;
+
+extern "C" {
+int QsortCallback(const void *a, const void *b) {
+ char *x = (char*)a;
+ char *y = (char*)b;
+ printf("Calling QsortCallback\n");
+ GlobalPtr = new int[10];
+ return (int)*x - (int)*y;
+}
+
+__attribute__((noinline))
+void MyQsort(char *a, size_t size) {
+ printf("Calling qsort\n");
+ qsort(a, size, sizeof(char), QsortCallback);
+ printf("Done\n"); // Avoid tail call.
+}
+} // extern "C"
+
+int main() {
+ char a[2] = {1, 2};
+ MyQsort(a, 2);
+ return GlobalPtr[10];
+}
+
+// Fast unwind: can not unwind through qsort.
+// FIXME: this test does not properly work with slow unwind yet.
+
+// CHECK-FAST: ERROR: AddressSanitizer: heap-buffer-overflow
+// CHECK-FAST: is located 0 bytes to the right
+// CHECK-FAST: #0{{.*}}operator new
+// CHECK-FAST-NEXT: #1{{.*}}QsortCallback
+// CHECK-FAST-NOT: MyQsort
+//
+// CHECK-SLOW: ERROR: AddressSanitizer: heap-buffer-overflow
+// CHECK-SLOW: is located 0 bytes to the right
+// CHECK-SLOW: #0{{.*}}operator new
+// CHECK-SLOW-NEXT: #1{{.*}}QsortCallback
+// CHECK-SLOW: #{{.*}}MyQsort
+// CHECK-SLOW-NEXT: #{{.*}}main
diff --git a/lib/asan/lit_tests/TestCases/Linux/malloc_delete_mismatch.cc b/lib/asan/lit_tests/TestCases/Linux/malloc_delete_mismatch.cc
new file mode 100644
index 000000000000..7010eb2de2e7
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/malloc_delete_mismatch.cc
@@ -0,0 +1,31 @@
+// Check that we detect malloc/delete mismatch only if the approptiate flag
+// is set.
+
+// RUN: %clangxx_asan -g %s -o %t 2>&1
+
+// Find error and provide malloc context.
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1 not %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=ALLOC-STACK
+
+// No error here.
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=0 %t
+
+// Also works if no malloc context is available.
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1:malloc_context_size=0:fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=alloc_dealloc_mismatch=1:malloc_context_size=0:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+
+static volatile char *x;
+
+int main() {
+ x = (char*)malloc(10);
+ x[0] = 0;
+ delete x;
+}
+// CHECK: ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete) on 0x
+// CHECK-NEXT: #0{{.*}}operator delete
+// CHECK: #{{.*}}main
+// CHECK: is located 0 bytes inside of 10-byte region
+// CHECK-NEXT: allocated by thread T0 here:
+// ALLOC-STACK-NEXT: #0{{.*}}malloc
+// ALLOC-STACK: #{{.*}}main
+// CHECK: HINT: {{.*}} you may set ASAN_OPTIONS=alloc_dealloc_mismatch=0
diff --git a/lib/asan/lit_tests/TestCases/Linux/overflow-in-qsort.cc b/lib/asan/lit_tests/TestCases/Linux/overflow-in-qsort.cc
new file mode 100644
index 000000000000..139977261ec9
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/overflow-in-qsort.cc
@@ -0,0 +1,51 @@
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS=fast_unwind_on_fatal=1 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-FAST
+// RUN: ASAN_OPTIONS=fast_unwind_on_fatal=0 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-SLOW
+
+// Test how well we unwind in presence of qsort in the stack
+// (i.e. if we can unwind through a function compiled w/o frame pointers).
+// https://code.google.com/p/address-sanitizer/issues/detail?id=137
+
+// Fast unwinder is only avaliable on x86_64 and i386.
+// REQUIRES: x86_64-supported-target
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int global_array[10];
+volatile int one = 1;
+
+extern "C" {
+int QsortCallback(const void *a, const void *b) {
+ char *x = (char*)a;
+ char *y = (char*)b;
+ printf("Calling QsortCallback\n");
+ global_array[one * 10] = 0; // BOOM
+ return (int)*x - (int)*y;
+}
+
+__attribute__((noinline))
+void MyQsort(char *a, size_t size) {
+ printf("Calling qsort\n");
+ qsort(a, size, sizeof(char), QsortCallback);
+ printf("Done\n"); // Avoid tail call.
+}
+} // extern "C"
+
+int main() {
+ char a[2] = {1, 2};
+ MyQsort(a, 2);
+}
+
+// Fast unwind: can not unwind through qsort.
+
+// CHECK-FAST: ERROR: AddressSanitizer: global-buffer-overflow
+// CHECK-FAST: #0{{.*}} in QsortCallback
+// CHECK-FAST-NOT: MyQsort
+// CHECK-FAST: is located 0 bytes to the right of global variable 'global_array
+
+// CHECK-SLOW: ERROR: AddressSanitizer: global-buffer-overflow
+// CHECK-SLOW: #0{{.*}} in QsortCallback
+// CHECK-SLOW: #{{.*}} in MyQsort
+// CHECK-SLOW: #{{.*}} in main
+// CHECK-SLOW: is located 0 bytes to the right of global variable 'global_array
diff --git a/lib/asan/lit_tests/TestCases/Linux/preinit_test.cc b/lib/asan/lit_tests/TestCases/Linux/preinit_test.cc
new file mode 100644
index 000000000000..28e509472c0c
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/preinit_test.cc
@@ -0,0 +1,27 @@
+// RUN: %clangxx -DFUNC=zzzz %s -shared -o %t.so -fPIC
+// RUN: %clangxx_asan -DFUNC=main %s -o %t -Wl,-R. %t.so
+// RUN: %t
+
+// This test ensures that we call __asan_init early enough.
+// We build a shared library w/o asan instrumentation
+// and the binary with asan instrumentation.
+// Both files include the same header (emulated by -DFUNC here)
+// with C++ template magic which runs global initializer at library load time.
+// The function get() is instrumented with asan, but called
+// before the usual constructors are run.
+// So, we must make sure that __asan_init is executed even earlier.
+//
+// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56393
+
+struct A {
+ int foo() const { return 0; }
+};
+A get () { return A(); }
+template <class> struct O {
+ static A const e;
+};
+template <class T> A const O <T>::e = get();
+int FUNC() {
+ return O<int>::e.foo();
+}
+
diff --git a/lib/asan/lit_tests/TestCases/Linux/ptrace.cc b/lib/asan/lit_tests/TestCases/Linux/ptrace.cc
new file mode 100644
index 000000000000..8831b81efa96
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/ptrace.cc
@@ -0,0 +1,52 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %t
+// RUN: %clangxx_asan -DPOSITIVE -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <stdio.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+int main(void) {
+ pid_t pid;
+ pid = fork();
+ if (pid == 0) { // child
+ ptrace(PTRACE_TRACEME, 0, NULL, NULL);
+ execl("/bin/true", "true", NULL);
+ } else {
+ wait(NULL);
+ user_regs_struct regs;
+ int res;
+ user_regs_struct * volatile pregs = &regs;
+#ifdef POSITIVE
+ ++pregs;
+#endif
+ res = ptrace(PTRACE_GETREGS, pid, NULL, pregs);
+ // CHECK: AddressSanitizer: stack-buffer-overflow
+ // CHECK: {{.*ptrace.cc:}}[[@LINE-2]]
+ assert(!res);
+#if __WORDSIZE == 64
+ printf("%zx\n", regs.rip);
+#else
+ printf("%lx\n", regs.eip);
+#endif
+
+ user_fpregs_struct fpregs;
+ res = ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs);
+ assert(!res);
+ printf("%lx\n", (unsigned long)fpregs.cwd);
+
+#if __WORDSIZE == 32
+ user_fpxregs_struct fpxregs;
+ res = ptrace(PTRACE_GETFPXREGS, pid, NULL, &fpxregs);
+ assert(!res);
+ printf("%lx\n", (unsigned long)fpxregs.mxcsr);
+#endif
+
+ ptrace(PTRACE_CONT, pid, NULL, NULL);
+ wait(NULL);
+ }
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/rlimit_mmap_test.cc b/lib/asan/lit_tests/TestCases/Linux/rlimit_mmap_test.cc
new file mode 100644
index 000000000000..0d1d4baa7671
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/rlimit_mmap_test.cc
@@ -0,0 +1,16 @@
+// Check that we properly report mmap failure.
+// RUN: %clangxx_asan %s -o %t && not %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+static volatile void *x;
+
+int main(int argc, char **argv) {
+ struct rlimit mmap_resource_limit = { 0, 0 };
+ assert(0 == setrlimit(RLIMIT_AS, &mmap_resource_limit));
+ x = malloc(10000000);
+// CHECK: ERROR: Failed to mmap
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/swapcontext_test.cc b/lib/asan/lit_tests/TestCases/Linux/swapcontext_test.cc
new file mode 100644
index 000000000000..6cbb69a35321
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/swapcontext_test.cc
@@ -0,0 +1,90 @@
+// Check that ASan plays well with easy cases of makecontext/swapcontext.
+
+// RUN: %clangxx_asan -O0 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && %t 2>&1 | FileCheck %s
+//
+// This test is too sublte to try on non-x86 arch for now.
+// REQUIRES: x86_64-supported-target,i386-supported-target
+
+#include <stdio.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+ucontext_t orig_context;
+ucontext_t child_context;
+
+const int kStackSize = 1 << 20;
+
+__attribute__((noinline))
+void Throw() {
+ throw 1;
+}
+
+__attribute__((noinline))
+void ThrowAndCatch() {
+ try {
+ Throw();
+ } catch(int a) {
+ printf("ThrowAndCatch: %d\n", a);
+ }
+}
+
+void Child(int mode) {
+ char x[32] = {0}; // Stack gets poisoned.
+ printf("Child: %p\n", x);
+ ThrowAndCatch(); // Simulate __asan_handle_no_return().
+ // (a) Do nothing, just return to parent function.
+ // (b) Jump into the original function. Stack remains poisoned unless we do
+ // something.
+ if (mode == 1) {
+ if (swapcontext(&child_context, &orig_context) < 0) {
+ perror("swapcontext");
+ _exit(0);
+ }
+ }
+}
+
+int Run(int arg, int mode, char *child_stack) {
+ printf("Child stack: %p\n", child_stack);
+ // Setup child context.
+ getcontext(&child_context);
+ child_context.uc_stack.ss_sp = child_stack;
+ child_context.uc_stack.ss_size = kStackSize / 2;
+ if (mode == 0) {
+ child_context.uc_link = &orig_context;
+ }
+ makecontext(&child_context, (void (*)())Child, 1, mode);
+ if (swapcontext(&orig_context, &child_context) < 0) {
+ perror("swapcontext");
+ return 0;
+ }
+ // Touch childs's stack to make sure it's unpoisoned.
+ for (int i = 0; i < kStackSize; i++) {
+ child_stack[i] = i;
+ }
+ return child_stack[arg];
+}
+
+int main(int argc, char **argv) {
+ char stack[kStackSize + 1];
+ // CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext
+ int ret = 0;
+ ret += Run(argc - 1, 0, stack);
+ printf("Test1 passed\n");
+ // CHECK: Test1 passed
+ ret += Run(argc - 1, 1, stack);
+ printf("Test2 passed\n");
+ // CHECK: Test2 passed
+ char *heap = new char[kStackSize + 1];
+ ret += Run(argc - 1, 0, heap);
+ printf("Test3 passed\n");
+ // CHECK: Test3 passed
+ ret += Run(argc - 1, 1, heap);
+ printf("Test4 passed\n");
+ // CHECK: Test4 passed
+
+ delete [] heap;
+ return ret;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/syscalls.cc b/lib/asan/lit_tests/TestCases/Linux/syscalls.cc
new file mode 100644
index 000000000000..4bcbe446113e
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/syscalls.cc
@@ -0,0 +1,22 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <errno.h>
+#include <glob.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sanitizer/linux_syscall_hooks.h>
+
+/* Test the presence of __sanitizer_syscall_ in the tool runtime, and general
+ sanity of their behaviour. */
+
+int main(int argc, char *argv[]) {
+ char buf[1000];
+ __sanitizer_syscall_pre_recvmsg(0, buf - 1, 0);
+ // CHECK: AddressSanitizer: stack-buffer-{{.*}}erflow
+ // CHECK: READ of size {{.*}} at {{.*}} thread T0
+ // CHECK: #0 {{.*}} in __sanitizer_syscall{{.*}}recvmsg
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/time_null_regtest.cc b/lib/asan/lit_tests/TestCases/Linux/time_null_regtest.cc
new file mode 100644
index 000000000000..566409be6a19
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/time_null_regtest.cc
@@ -0,0 +1,20 @@
+// RUN: %clangxx_asan -O0 %s -fsanitize-address-zero-base-shadow -pie -o %t && %t 2>&1 | FileCheck %s
+
+// Zero-base shadow only works on x86_64 and i386.
+// REQUIRES: x86_64-supported-target
+
+// A regression test for time(NULL), which caused ASan to crash in the
+// zero-based shadow mode on Linux.
+// FIXME: this test does not work on Darwin, because the code pages of the
+// executable interleave with the zero-based shadow.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+int main() {
+ time_t t = time(NULL);
+ fprintf(stderr, "Time: %s\n", ctime(&t)); // NOLINT
+ // CHECK: {{Time: .* .* .*}}
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/tsd_dtor_leak.cc b/lib/asan/lit_tests/TestCases/Linux/tsd_dtor_leak.cc
new file mode 100644
index 000000000000..a1d89ee437d4
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/tsd_dtor_leak.cc
@@ -0,0 +1,39 @@
+// Regression test for a leak in tsd:
+// https://code.google.com/p/address-sanitizer/issues/detail?id=233
+// RUN: %clangxx_asan -O1 %s -o %t
+// RUN: ASAN_OPTIONS=quarantine_size=1 %t
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+extern "C" size_t __asan_get_heap_size();
+static pthread_key_t tsd_key;
+
+void *Thread(void *) {
+ pthread_setspecific(tsd_key, malloc(10));
+ return 0;
+}
+
+static volatile void *v;
+
+void Dtor(void *tsd) {
+ v = malloc(10000);
+ free(tsd);
+ free((void*)v); // The bug was that this was leaking.
+}
+
+int main() {
+ assert(0 == pthread_key_create(&tsd_key, Dtor));
+ size_t old_heap_size = 0;
+ for (int i = 0; i < 10; i++) {
+ pthread_t t;
+ pthread_create(&t, 0, Thread, 0);
+ pthread_join(t, 0);
+ size_t new_heap_size = __asan_get_heap_size();
+ fprintf(stderr, "heap size: new: %zd old: %zd\n", new_heap_size, old_heap_size);
+ if (old_heap_size)
+ assert(old_heap_size == new_heap_size);
+ old_heap_size = new_heap_size;
+ }
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/uar_signals.cc b/lib/asan/lit_tests/TestCases/Linux/uar_signals.cc
new file mode 100644
index 000000000000..9663859dfefd
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/uar_signals.cc
@@ -0,0 +1,70 @@
+// This test shows that the current implementation of use-after-return is
+// not signal-safe.
+// RUN: %clangxx_asan -O1 %s -o %t -lpthread && %t
+// RUN: %clangxx_asan -O1 %s -o %t -lpthread && %t
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+int *g;
+int n_signals;
+
+typedef void (*Sigaction)(int, siginfo_t *, void *);
+
+void SignalHandler(int, siginfo_t*, void*) {
+ int local;
+ g = &local;
+ n_signals++;
+ // printf("s: %p\n", &local);
+}
+
+static void EnableSigprof(Sigaction SignalHandler) {
+ struct sigaction sa;
+ sa.sa_sigaction = SignalHandler;
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(SIGPROF, &sa, NULL) != 0) {
+ perror("sigaction");
+ abort();
+ }
+ struct itimerval timer;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = 1;
+ timer.it_value = timer.it_interval;
+ if (setitimer(ITIMER_PROF, &timer, 0) != 0) {
+ perror("setitimer");
+ abort();
+ }
+}
+
+void RecursiveFunction(int depth) {
+ if (depth == 0) return;
+ int local;
+ g = &local;
+ // printf("r: %p\n", &local);
+ // printf("[%2d] n_signals: %d\n", depth, n_signals);
+ RecursiveFunction(depth - 1);
+ RecursiveFunction(depth - 1);
+}
+
+void *Thread(void *) {
+ RecursiveFunction(18);
+ return NULL;
+}
+
+int main(int argc, char **argv) {
+ EnableSigprof(SignalHandler);
+
+ for (int i = 0; i < 4; i++) {
+ fprintf(stderr, ".");
+ const int kNumThread = sizeof(void*) == 8 ? 16 : 8;
+ pthread_t t[kNumThread];
+ for (int i = 0; i < kNumThread; i++)
+ pthread_create(&t[i], 0, Thread, 0);
+ for (int i = 0; i < kNumThread; i++)
+ pthread_join(t[i], 0);
+ }
+ fprintf(stderr, "\n");
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/unpoison_tls.cc b/lib/asan/lit_tests/TestCases/Linux/unpoison_tls.cc
new file mode 100644
index 000000000000..d67c4f954e43
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/unpoison_tls.cc
@@ -0,0 +1,35 @@
+// Test that TLS is unpoisoned on thread death.
+// REQUIRES: x86_64-supported-target,i386-supported-target
+
+// RUN: %clangxx_asan -O1 %s -o %t && %t 2>&1
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+
+#include <sanitizer/asan_interface.h>
+
+__thread int64_t tls_var[2];
+
+volatile int64_t *p_tls_var;
+
+void *first(void *arg) {
+ ASAN_POISON_MEMORY_REGION(&tls_var, sizeof(tls_var));
+ p_tls_var = tls_var;
+ return 0;
+}
+
+void *second(void *arg) {
+ assert(tls_var == p_tls_var);
+ *p_tls_var = 1;
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ pthread_t p;
+ assert(0 == pthread_create(&p, 0, first, 0));
+ assert(0 == pthread_join(p, 0));
+ assert(0 == pthread_create(&p, 0, second, 0));
+ assert(0 == pthread_join(p, 0));
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/zero-base-shadow32.cc b/lib/asan/lit_tests/TestCases/Linux/zero-base-shadow32.cc
new file mode 100644
index 000000000000..e6bcc5597471
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/zero-base-shadow32.cc
@@ -0,0 +1,24 @@
+// RUN: %clangxx_asan -O0 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+
+// Zero-base shadow only works on x86_64 and i386.
+// REQUIRES: i386-supported-target, asan-32-bits
+
+#include <string.h>
+int main(int argc, char **argv) {
+ char x[10];
+ memset(x, 0, 10);
+ int res = x[argc * 10]; // BOOOM
+ // CHECK: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.* in main .*zero-base-shadow32.cc:}}[[@LINE-2]]
+ // CHECK: {{Address 0x.* is .* frame}}
+ // CHECK: main
+
+ // Check that shadow for stack memory occupies lower part of address space.
+ // CHECK: =>0x1
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/Linux/zero-base-shadow64.cc b/lib/asan/lit_tests/TestCases/Linux/zero-base-shadow64.cc
new file mode 100644
index 000000000000..1db725c95752
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/Linux/zero-base-shadow64.cc
@@ -0,0 +1,24 @@
+// RUN: %clangxx_asan -O0 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+
+// Zero-base shadow only works on x86_64 and i386.
+// REQUIRES: x86_64-supported-target, asan-64-bits
+
+#include <string.h>
+int main(int argc, char **argv) {
+ char x[10];
+ memset(x, 0, 10);
+ int res = x[argc * 10]; // BOOOM
+ // CHECK: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.* in main .*zero-base-shadow64.cc:}}[[@LINE-2]]
+ // CHECK: {{Address 0x.* is .* frame}}
+ // CHECK: main
+
+ // Check that shadow for stack memory occupies lower part of address space.
+ // CHECK: =>0x0f
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/SharedLibs/darwin-dummy-shared-lib-so.cc b/lib/asan/lit_tests/TestCases/SharedLibs/darwin-dummy-shared-lib-so.cc
new file mode 100644
index 000000000000..5d939991476e
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/SharedLibs/darwin-dummy-shared-lib-so.cc
@@ -0,0 +1,13 @@
+//===----------- darwin-dummy-shared-lib-so.cc ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+//===----------------------------------------------------------------------===//
+void foo() {}
diff --git a/lib/asan/lit_tests/TestCases/SharedLibs/dlclose-test-so.cc b/lib/asan/lit_tests/TestCases/SharedLibs/dlclose-test-so.cc
new file mode 100644
index 000000000000..73e00507358a
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/SharedLibs/dlclose-test-so.cc
@@ -0,0 +1,33 @@
+//===----------- dlclose-test-so.cc -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Regression test for
+// http://code.google.com/p/address-sanitizer/issues/detail?id=19
+//===----------------------------------------------------------------------===//
+#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__);
+}
diff --git a/lib/asan/lit_tests/TestCases/SharedLibs/init-order-dlopen-so.cc b/lib/asan/lit_tests/TestCases/SharedLibs/init-order-dlopen-so.cc
new file mode 100644
index 000000000000..dc097a520d03
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/SharedLibs/init-order-dlopen-so.cc
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <unistd.h>
+
+extern "C" void inc_global();
+
+int slow_init() {
+ sleep(1);
+ inc_global();
+ return 42;
+}
+
+int slowly_init_glob = slow_init();
diff --git a/lib/asan/lit_tests/TestCases/SharedLibs/lit.local.cfg b/lib/asan/lit_tests/TestCases/SharedLibs/lit.local.cfg
new file mode 100644
index 000000000000..b3677c17a0f2
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/SharedLibs/lit.local.cfg
@@ -0,0 +1,4 @@
+# Sources in this directory are compiled as shared libraries and used by
+# tests in parent directory.
+
+config.suffixes = []
diff --git a/lib/asan/lit_tests/TestCases/SharedLibs/shared-lib-test-so.cc b/lib/asan/lit_tests/TestCases/SharedLibs/shared-lib-test-so.cc
new file mode 100644
index 000000000000..6ef565ce47b3
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/SharedLibs/shared-lib-test-so.cc
@@ -0,0 +1,26 @@
+//===----------- shared-lib-test-so.cc --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+//===----------------------------------------------------------------------===//
+#include <stdio.h>
+
+int pad[10];
+int GLOB[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+extern "C"
+void inc(int index) {
+ GLOB[index]++;
+}
+
+extern "C"
+void inc2(int *a, int index) {
+ a[index]++;
+}
diff --git a/lib/asan/lit_tests/TestCases/allocator_returns_null.cc b/lib/asan/lit_tests/TestCases/allocator_returns_null.cc
new file mode 100644
index 000000000000..595c9e252f86
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/allocator_returns_null.cc
@@ -0,0 +1,81 @@
+// Test the behavior of malloc/calloc/realloc when the allocation size is huge.
+// By default (allocator_may_return_null=0) the process should crash.
+// With allocator_may_return_null=1 the allocator should return 0.
+//
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH
+// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH
+// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mNULL
+// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-cCRASH
+// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %t calloc 2>&1 | FileCheck %s --check-prefix=CHECK-cNULL
+// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %t calloc-overflow 2>&1 | FileCheck %s --check-prefix=CHECK-coCRASH
+// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %t calloc-overflow 2>&1 | FileCheck %s --check-prefix=CHECK-coNULL
+// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %t realloc 2>&1 | FileCheck %s --check-prefix=CHECK-rCRASH
+// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %t realloc 2>&1 | FileCheck %s --check-prefix=CHECK-rNULL
+// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %t realloc-after-malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mrCRASH
+// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %t realloc-after-malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mrNULL
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <limits>
+int main(int argc, char **argv) {
+ volatile size_t size = std::numeric_limits<size_t>::max() - 10000;
+ assert(argc == 2);
+ char *x = 0;
+ if (!strcmp(argv[1], "malloc")) {
+ fprintf(stderr, "malloc:\n");
+ x = (char*)malloc(size);
+ }
+ if (!strcmp(argv[1], "calloc")) {
+ fprintf(stderr, "calloc:\n");
+ x = (char*)calloc(size / 4, 4);
+ }
+
+ if (!strcmp(argv[1], "calloc-overflow")) {
+ fprintf(stderr, "calloc-overflow:\n");
+ volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max();
+ size_t kArraySize = 4096;
+ volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
+ x = (char*)calloc(kArraySize, kArraySize2);
+ }
+
+ if (!strcmp(argv[1], "realloc")) {
+ fprintf(stderr, "realloc:\n");
+ x = (char*)realloc(0, size);
+ }
+ if (!strcmp(argv[1], "realloc-after-malloc")) {
+ fprintf(stderr, "realloc-after-malloc:\n");
+ char *t = (char*)malloc(100);
+ *t = 42;
+ x = (char*)realloc(t, size);
+ assert(*t == 42);
+ }
+ // The NULL pointer is printed differently on different systems, while (long)0
+ // is always the same.
+ fprintf(stderr, "x: %lx\n", (long)x);
+ return x != 0;
+}
+// CHECK-mCRASH: malloc:
+// CHECK-mCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-cCRASH: calloc:
+// CHECK-cCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-coCRASH: calloc-overflow:
+// CHECK-coCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-rCRASH: realloc:
+// CHECK-rCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-mrCRASH: realloc-after-malloc:
+// CHECK-mrCRASH: AddressSanitizer's allocator is terminating the process
+
+// CHECK-mNULL: malloc:
+// CHECK-mNULL: x: 0
+// CHECK-cNULL: calloc:
+// CHECK-cNULL: x: 0
+// CHECK-coNULL: calloc-overflow:
+// CHECK-coNULL: x: 0
+// CHECK-rNULL: realloc:
+// CHECK-rNULL: x: 0
+// CHECK-mrNULL: realloc-after-malloc:
+// CHECK-mrNULL: x: 0
diff --git a/lib/asan/lit_tests/TestCases/allow_user_segv.cc b/lib/asan/lit_tests/TestCases/allow_user_segv.cc
new file mode 100644
index 000000000000..55cf6044e7a0
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/allow_user_segv.cc
@@ -0,0 +1,48 @@
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=180
+
+// RUN: %clangxx_asan -O0 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true not %t 2>&1 | FileCheck %s
+
+#include <signal.h>
+#include <stdio.h>
+
+struct sigaction user_sigaction;
+struct sigaction original_sigaction;
+
+void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) {
+ fprintf(stderr, "User sigaction called\n");
+ if (original_sigaction.sa_flags | SA_SIGINFO)
+ original_sigaction.sa_sigaction(signum, siginfo, context);
+ else
+ original_sigaction.sa_handler(signum);
+}
+
+int DoSEGV() {
+ volatile int *x = 0;
+ return *x;
+}
+
+int main() {
+ user_sigaction.sa_sigaction = User_OnSIGSEGV;
+ user_sigaction.sa_flags = SA_SIGINFO;
+#if defined(__APPLE__) && !defined(__LP64__)
+ // On 32-bit Darwin KERN_PROTECTION_FAILURE (SIGBUS) is delivered.
+ int signum = SIGBUS;
+#else
+ // On 64-bit Darwin KERN_INVALID_ADDRESS (SIGSEGV) is delivered.
+ // On Linux SIGSEGV is delivered as well.
+ int signum = SIGSEGV;
+#endif
+ if (sigaction(signum, &user_sigaction, &original_sigaction)) {
+ perror("sigaction");
+ return 1;
+ }
+ fprintf(stderr, "User sigaction installed\n");
+ return DoSEGV();
+}
+
+// CHECK: User sigaction installed
+// CHECK-NEXT: User sigaction called
+// CHECK-NEXT: ASAN:SIGSEGV
+// CHECK: AddressSanitizer: SEGV on unknown address
diff --git a/lib/asan/lit_tests/TestCases/asan-symbolize-sanity-test.cc b/lib/asan/lit_tests/TestCases/asan-symbolize-sanity-test.cc
new file mode 100644
index 000000000000..0efe245bb6b5
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/asan-symbolize-sanity-test.cc
@@ -0,0 +1,39 @@
+// Check that asan_symbolize.py script works (for binaries, ASan RTL and
+// shared object files.
+
+// RUN: %clangxx_asan -O0 %p/SharedLibs/shared-lib-test-so.cc -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: ASAN_SYMBOLIZER_PATH= not %t 2>&1 | %asan_symbolize | FileCheck %s
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string>
+
+using std::string;
+
+typedef void (fun_t)(int*, int);
+
+int main(int argc, char *argv[]) {
+ string path = string(argv[0]) + "-so.so";
+ 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 *inc2 = (fun_t*)dlsym(lib, "inc2");
+ if (!inc2) return 1;
+ printf("ok\n");
+ int *array = (int*)malloc(40);
+ inc2(array, 1);
+ inc2(array, -1); // BOOM
+ // CHECK: ERROR: AddressSanitizer: heap-buffer-overflow
+ // CHECK: READ of size 4 at 0x{{.*}}
+ // CHECK: #0 {{.*}} in inc2 {{.*}}shared-lib-test-so.cc:25
+ // CHECK: #1 {{.*}} in main {{.*}}asan-symbolize-sanity-test.cc:[[@LINE-4]]
+ // CHECK: allocated by thread T{{.*}} here:
+ // CHECK: #{{.*}} in {{(wrap_|__interceptor_)?}}malloc
+ // CHECK: #{{.*}} in main {{.*}}asan-symbolize-sanity-test.cc:[[@LINE-9]]
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/assign_large_valloc_to_global.cc b/lib/asan/lit_tests/TestCases/assign_large_valloc_to_global.cc
new file mode 100644
index 000000000000..b0a501576945
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/assign_large_valloc_to_global.cc
@@ -0,0 +1,8 @@
+// Make sure we don't report a leak nor hang.
+// RUN: %clangxx_asan -O3 %s -o %t && %t
+#include <stdlib.h>
+#ifndef __APPLE__
+#include <malloc.h>
+#endif // __APPLE__
+int *p = (int*)valloc(1 << 20);
+int main() { }
diff --git a/lib/asan/lit_tests/TestCases/atexit_stats.cc b/lib/asan/lit_tests/TestCases/atexit_stats.cc
new file mode 100644
index 000000000000..e3b1269d25cc
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/atexit_stats.cc
@@ -0,0 +1,13 @@
+// Make sure we report atexit stats.
+// RUN: %clangxx_asan -O3 %s -o %t
+// RUN: ASAN_OPTIONS=atexit=1:print_stats=1 %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#if !defined(__APPLE__)
+#include <malloc.h>
+#endif
+int *p1 = (int*)malloc(900);
+int *p2 = (int*)malloc(90000);
+int *p3 = (int*)malloc(9000000);
+int main() { }
+
+// CHECK: AddressSanitizer exit stats:
diff --git a/lib/asan/lit_tests/TestCases/blacklist.cc b/lib/asan/lit_tests/TestCases/blacklist.cc
new file mode 100644
index 000000000000..46625ee7bdb5
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/blacklist.cc
@@ -0,0 +1,38 @@
+// Test the blacklist functionality of ASan
+
+// RUN: echo "fun:*brokenFunction*" > %tmp
+// RUN: echo "global:*badGlobal*" >> %tmp
+// RUN: echo "src:*blacklist-extra.cc" >> %tmp
+// RUN: %clangxx_asan -fsanitize-blacklist=%tmp -O0 %s -o %t \
+// RUN: %p/Helpers/blacklist-extra.cc && %t 2>&1
+// RUN: %clangxx_asan -fsanitize-blacklist=%tmp -O1 %s -o %t \
+// RUN: %p/Helpers/blacklist-extra.cc && %t 2>&1
+// RUN: %clangxx_asan -fsanitize-blacklist=%tmp -O2 %s -o %t \
+// RUN: %p/Helpers/blacklist-extra.cc && %t 2>&1
+// RUN: %clangxx_asan -fsanitize-blacklist=%tmp -O3 %s -o %t \
+// RUN: %p/Helpers/blacklist-extra.cc && %t 2>&1
+
+// badGlobal is accessed improperly, but we blacklisted it. Align
+// it to make sure memory past the end of badGlobal will be in
+// the same page.
+__attribute__((aligned(16))) int badGlobal;
+int readBadGlobal() {
+ return (&badGlobal)[1];
+}
+
+// A function which is broken, but excluded in the blacklist.
+int brokenFunction(int argc) {
+ char x[10] = {0};
+ return x[argc * 10]; // BOOM
+}
+
+// This function is defined in Helpers/blacklist-extra.cc, a source file which
+// is blacklisted by name
+int externalBrokenFunction(int x);
+
+int main(int argc, char **argv) {
+ brokenFunction(argc);
+ int x = readBadGlobal();
+ externalBrokenFunction(argc);
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/contiguous_container.cc b/lib/asan/lit_tests/TestCases/contiguous_container.cc
new file mode 100644
index 000000000000..aa97592c7bb9
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/contiguous_container.cc
@@ -0,0 +1,47 @@
+// RUN: %clangxx_asan -O %s -o %t && %t
+//
+// Test __sanitizer_annotate_contiguous_container.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+extern "C" {
+void __sanitizer_annotate_contiguous_container(void *beg, void *end,
+ void *old_mid, void *new_mid);
+bool __asan_address_is_poisoned(void *addr);
+} // extern "C"
+
+void TestContainer(size_t capacity) {
+ char *beg = new char[capacity];
+ char *end = beg + capacity;
+ char *mid = beg + capacity;
+ char *old_mid = 0;
+ unsigned seed = 0;
+
+ for (int i = 0; i < 10000; i++) {
+ size_t size = rand_r(&seed) % (capacity + 1);
+ assert(size <= capacity);
+ old_mid = mid;
+ mid = beg + size;
+ __sanitizer_annotate_contiguous_container(beg, end, old_mid, mid);
+
+ for (size_t idx = 0; idx < size; idx++)
+ assert(!__asan_address_is_poisoned(beg + idx));
+ for (size_t idx = size; idx < capacity; idx++)
+ assert(__asan_address_is_poisoned(beg + idx));
+ }
+
+ // Don't forget to unpoison the whole thing before destroing/reallocating.
+ __sanitizer_annotate_contiguous_container(beg, end, mid, end);
+ for (size_t idx = 0; idx < capacity; idx++)
+ assert(!__asan_address_is_poisoned(beg + idx));
+ delete[] beg;
+}
+
+int main(int argc, char **argv) {
+ int n = argc == 1 ? 128 : atoi(argv[1]);
+ for (int i = 0; i <= n; i++)
+ TestContainer(i);
+}
diff --git a/lib/asan/lit_tests/TestCases/current_allocated_bytes.cc b/lib/asan/lit_tests/TestCases/current_allocated_bytes.cc
new file mode 100644
index 000000000000..669cf150bdfb
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/current_allocated_bytes.cc
@@ -0,0 +1,43 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %t
+// RUN: %clangxx_asan -O2 %s -o %t && %t
+
+#include <assert.h>
+#include <pthread.h>
+#include <sanitizer/asan_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(__asan_get_current_allocated_bytes() > 0);
+ return 0;
+}
+
+int main() {
+ size_t used_mem = __asan_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 = __asan_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/lib/asan/lit_tests/TestCases/deep_call_stack.cc b/lib/asan/lit_tests/TestCases/deep_call_stack.cc
new file mode 100644
index 000000000000..e24704b9019e
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/deep_call_stack.cc
@@ -0,0 +1,25 @@
+// Check that UAR mode can handle very deep recusrion.
+// export ASAN_OPTIONS=detect_stack_use_after_return=1
+// RUN: %clangxx_asan -O2 %s -o %t && \
+// RUN: %t 2>&1 | FileCheck %s
+// Also check that use_sigaltstack+verbosity doesn't crash.
+// RUN: ASAN_OPTIONS=verbosity=1:use_sigaltstack=1 %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(40000, 0);
+ return 0;
+}
+// CHECK: [40000] ptr:
+// CHECK: [20000] ptr:
+// CHECK: [00000] ptr
diff --git a/lib/asan/lit_tests/TestCases/deep_stack_uaf.cc b/lib/asan/lit_tests/TestCases/deep_stack_uaf.cc
new file mode 100644
index 000000000000..920411c4ac52
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/deep_stack_uaf.cc
@@ -0,0 +1,31 @@
+// Check that we can store lots of stack frames if asked to.
+
+// RUN: %clangxx_asan -O0 %s -o %t 2>&1
+// RUN: ASAN_OPTIONS=malloc_context_size=120:redzone=512 not %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <stdio.h>
+
+template <int depth>
+struct DeepFree {
+ static void free(char *x) {
+ DeepFree<depth - 1>::free(x);
+ }
+};
+
+template<>
+struct DeepFree<0> {
+ static void free(char *x) {
+ ::free(x);
+ }
+};
+
+int main() {
+ char *x = (char*)malloc(10);
+ // deep_free(x);
+ DeepFree<200>::free(x);
+ return x[5];
+ // CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+ // CHECK: DeepFree<36>
+ // CHECK: DeepFree<98>
+ // CHECK: DeepFree<115>
+}
diff --git a/lib/asan/lit_tests/TestCases/deep_tail_call.cc b/lib/asan/lit_tests/TestCases/deep_tail_call.cc
new file mode 100644
index 000000000000..2e7aa8e0208f
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/deep_tail_call.cc
@@ -0,0 +1,20 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+// CHECK: AddressSanitizer: global-buffer-overflow
+int global[10];
+// CHECK: {{#0.*call4}}
+void __attribute__((noinline)) call4(int i) { global[i+10]++; }
+// CHECK: {{#1.*call3}}
+void __attribute__((noinline)) call3(int i) { call4(i); }
+// CHECK: {{#2.*call2}}
+void __attribute__((noinline)) call2(int i) { call3(i); }
+// CHECK: {{#3.*call1}}
+void __attribute__((noinline)) call1(int i) { call2(i); }
+// CHECK: {{#4.*main}}
+int main(int argc, char **argv) {
+ call1(argc);
+ return global[0];
+}
diff --git a/lib/asan/lit_tests/TestCases/deep_thread_stack.cc b/lib/asan/lit_tests/TestCases/deep_thread_stack.cc
new file mode 100644
index 000000000000..92e0d66c82eb
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/deep_thread_stack.cc
@@ -0,0 +1,57 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#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/lib/asan/lit_tests/TestCases/default_blacklist.cc b/lib/asan/lit_tests/TestCases/default_blacklist.cc
new file mode 100644
index 000000000000..25a1ae1752b0
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/default_blacklist.cc
@@ -0,0 +1,3 @@
+// Test that ASan uses the default blacklist from resource directory.
+// RUN: %clangxx_asan -### %s 2>&1 | FileCheck %s
+// CHECK: fsanitize-blacklist={{.*}}asan_blacklist.txt
diff --git a/lib/asan/lit_tests/TestCases/default_options.cc b/lib/asan/lit_tests/TestCases/default_options.cc
new file mode 100644
index 000000000000..84b80557b852
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/default_options.cc
@@ -0,0 +1,15 @@
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+
+const char *kAsanDefaultOptions="verbosity=1 foo=bar";
+
+extern "C"
+__attribute__((no_sanitize_address))
+const char *__asan_default_options() {
+ // CHECK: Using the defaults from __asan_default_options: {{.*}} foo=bar
+ return kAsanDefaultOptions;
+}
+
+int main() {
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/dlclose-test.cc b/lib/asan/lit_tests/TestCases/dlclose-test.cc
new file mode 100644
index 000000000000..03ed16016116
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/dlclose-test.cc
@@ -0,0 +1,81 @@
+// 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 %p/SharedLibs/dlclose-test-so.cc \
+// RUN: -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O0 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %p/SharedLibs/dlclose-test-so.cc \
+// RUN: -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %p/SharedLibs/dlclose-test-so.cc \
+// RUN: -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O2 %s -o %t && %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %p/SharedLibs/dlclose-test-so.cc \
+// RUN: -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O3 %s -o %t && %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <string>
+
+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, 0, 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;
+}
diff --git a/lib/asan/lit_tests/TestCases/double-free.cc b/lib/asan/lit_tests/TestCases/double-free.cc
new file mode 100644
index 000000000000..6bfd4fa2c7e5
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/double-free.cc
@@ -0,0 +1,25 @@
+// RUN: %clangxx_asan -O0 %s -o %t 2>&1
+// RUN: not %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=MALLOC-CTX
+
+// Also works if no malloc context is available.
+// RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+#include <string.h>
+int main(int argc, char **argv) {
+ char *x = (char*)malloc(10 * sizeof(char));
+ memset(x, 0, 10);
+ int res = x[argc];
+ free(x);
+ free(x + argc - 1); // BOOM
+ // CHECK: AddressSanitizer: attempting double-free{{.*}}in thread T0
+ // CHECK: #0 0x{{.*}} in {{.*}}free
+ // CHECK: #1 0x{{.*}} in main {{.*}}double-free.cc:[[@LINE-3]]
+ // CHECK: freed by thread T0 here:
+ // MALLOC-CTX: #0 0x{{.*}} in {{.*}}free
+ // MALLOC-CTX: #1 0x{{.*}} in main {{.*}}double-free.cc:[[@LINE-7]]
+ // CHECK: allocated by thread T0 here:
+ // MALLOC-CTX: double-free.cc:[[@LINE-12]]
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/force_inline_opt0.cc b/lib/asan/lit_tests/TestCases/force_inline_opt0.cc
new file mode 100644
index 000000000000..775a66dfe2fe
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/force_inline_opt0.cc
@@ -0,0 +1,14 @@
+// This test checks that we are no instrumenting a memory access twice
+// (before and after inlining)
+// RUN: %clangxx_asan -O1 %s -o %t && %t
+// RUN: %clangxx_asan -O0 %s -o %t && %t
+__attribute__((always_inline))
+void foo(int *x) {
+ *x = 0;
+}
+
+int main() {
+ int x;
+ foo(&x);
+ return x;
+}
diff --git a/lib/asan/lit_tests/TestCases/free_hook_realloc.cc b/lib/asan/lit_tests/TestCases/free_hook_realloc.cc
new file mode 100644
index 000000000000..7a71964b0032
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/free_hook_realloc.cc
@@ -0,0 +1,32 @@
+// Check that free hook doesn't conflict with Realloc.
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <unistd.h>
+
+static void *glob_ptr;
+
+extern "C" {
+void __asan_free_hook(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/lib/asan/lit_tests/TestCases/global-demangle.cc b/lib/asan/lit_tests/TestCases/global-demangle.cc
new file mode 100644
index 000000000000..d050b70f0fca
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/global-demangle.cc
@@ -0,0 +1,17 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+
+namespace XXX {
+class YYY {
+ public:
+ static char ZZZ[];
+};
+char YYY::ZZZ[] = "abc";
+}
+
+int main(int argc, char **argv) {
+ return (int)XXX::YYY::ZZZ[argc + 5]; // BOOM
+ // CHECK: {{READ of size 1 at 0x.*}}
+ // CHECK: {{0x.* is located 2 bytes to the right of global variable}}
+ // CHECK: 'XXX::YYY::ZZZ' {{.*}} of size 4
+ // CHECK: 'XXX::YYY::ZZZ' is ascii string 'abc'
+}
diff --git a/lib/asan/lit_tests/TestCases/global-overflow.cc b/lib/asan/lit_tests/TestCases/global-overflow.cc
new file mode 100644
index 000000000000..0f080f55f2f1
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/global-overflow.cc
@@ -0,0 +1,21 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <string.h>
+int main(int argc, char **argv) {
+ static char XXX[10];
+ static char YYY[10];
+ static char ZZZ[10];
+ memset(XXX, 0, 10);
+ memset(YYY, 0, 10);
+ memset(ZZZ, 0, 10);
+ int res = YYY[argc * 10]; // BOOOM
+ // CHECK: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.* in main .*global-overflow.cc:}}[[@LINE-2]]
+ // CHECK: {{0x.* is located 0 bytes to the right of global variable}}
+ // CHECK: {{.*YYY.* of size 10}}
+ res += XXX[argc] + ZZZ[argc];
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/heap-overflow.cc b/lib/asan/lit_tests/TestCases/heap-overflow.cc
new file mode 100644
index 000000000000..2c943a36014f
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/heap-overflow.cc
@@ -0,0 +1,24 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+
+#include <stdlib.h>
+#include <string.h>
+int main(int argc, char **argv) {
+ char *x = (char*)malloc(10 * sizeof(char));
+ memset(x, 0, 10);
+ int res = x[argc * 10]; // BOOOM
+ // CHECK: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.* in main .*heap-overflow.cc:}}[[@LINE-2]]
+ // CHECK: {{0x.* is located 0 bytes to the right of 10-byte region}}
+ // CHECK: {{allocated by thread T0 here:}}
+
+ // CHECK-Linux: {{ #0 0x.* in .*malloc}}
+ // CHECK-Linux: {{ #1 0x.* in main .*heap-overflow.cc:9}}
+
+ // CHECK-Darwin: {{ #0 0x.* in wrap_malloc.*}}
+ // CHECK-Darwin: {{ #1 0x.* in main .*heap-overflow.cc:9}}
+ free(x);
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/huge_negative_hea_oob.cc b/lib/asan/lit_tests/TestCases/huge_negative_hea_oob.cc
new file mode 100644
index 000000000000..58a44c5fb68e
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/huge_negative_hea_oob.cc
@@ -0,0 +1,13 @@
+// RUN: %clangxx_asan %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O %s -o %t && not %t 2>&1 | FileCheck %s
+// Check that we can find huge buffer overflows to the left.
+#include <stdlib.h>
+#include <string.h>
+int main(int argc, char **argv) {
+ char *x = (char*)malloc(1 << 20);
+ memset(x, 0, 10);
+ int res = x[-argc * 4000]; // BOOOM
+ // CHECK: is located 4000 bytes to the left of
+ free(x);
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/init-order-atexit.cc b/lib/asan/lit_tests/TestCases/init-order-atexit.cc
new file mode 100644
index 000000000000..e38cdd273d58
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/init-order-atexit.cc
@@ -0,0 +1,31 @@
+// Test for the following situation:
+// (1) global A is constructed.
+// (2) exit() is called during construction of global B.
+// (3) destructor of A reads uninitialized global C from another module.
+// We do *not* want to report init-order bug in this case.
+
+// RUN: %clangxx_asan -O0 %s %p/Helpers/init-order-atexit-extra.cc -o %t
+// RUN: ASAN_OPTIONS=strict_init_order=true not %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void AccessC();
+
+class A {
+ public:
+ A() { }
+ ~A() { AccessC(); printf("PASSED\n"); }
+ // CHECK-NOT: AddressSanitizer
+ // CHECK: PASSED
+};
+
+A a;
+
+class B {
+ public:
+ B() { exit(1); }
+ ~B() { }
+};
+
+B b;
diff --git a/lib/asan/lit_tests/TestCases/init-order-dlopen.cc b/lib/asan/lit_tests/TestCases/init-order-dlopen.cc
new file mode 100644
index 000000000000..d30d11999246
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/init-order-dlopen.cc
@@ -0,0 +1,57 @@
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=178
+
+// Assume we're on Darwin and try to pass -U to the linker. If this flag is
+// unsupported, don't use it.
+// RUN: %clangxx_asan -O0 %p/SharedLibs/init-order-dlopen-so.cc \
+// RUN: -fPIC -shared -o %t-so.so -Wl,-U,_inc_global || \
+// RUN: %clangxx_asan -O0 %p/SharedLibs/init-order-dlopen-so.cc \
+// RUN: -fPIC -shared -o %t-so.so
+// If the linker doesn't support --export-dynamic (which is ELF-specific),
+// try to link without that option.
+// FIXME: find a better solution.
+// RUN: %clangxx_asan -O0 %s -o %t -Wl,--export-dynamic || \
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: ASAN_OPTIONS=strict_init_order=true %t 2>&1 | FileCheck %s
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <string>
+
+using std::string;
+
+int foo() {
+ return 42;
+}
+int global = foo();
+
+__attribute__((visibility("default")))
+extern "C"
+void inc_global() {
+ global++;
+}
+
+void *global_poller(void *arg) {
+ while (true) {
+ if (global != 42)
+ break;
+ usleep(100);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ pthread_t p;
+ pthread_create(&p, 0, global_poller, 0);
+ string path = string(argv[0]) + "-so.so";
+ if (0 == dlopen(path.c_str(), RTLD_NOW)) {
+ fprintf(stderr, "dlerror: %s\n", dlerror());
+ return 1;
+ }
+ pthread_join(p, 0);
+ printf("PASSED\n");
+ // CHECK: PASSED
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/init-order-pthread-create.cc b/lib/asan/lit_tests/TestCases/init-order-pthread-create.cc
new file mode 100644
index 000000000000..52031216d5bb
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/init-order-pthread-create.cc
@@ -0,0 +1,32 @@
+// Check that init-order checking is properly disabled if pthread_create is
+// called.
+
+// RUN: %clangxx_asan %s %p/Helpers/init-order-pthread-create-extra.cc -o %t
+// RUN: ASAN_OPTIONS=strict_init_order=true %t
+
+#include <stdio.h>
+#include <pthread.h>
+
+void *run(void *arg) {
+ return arg;
+}
+
+void *foo(void *input) {
+ pthread_t t;
+ pthread_create(&t, 0, run, input);
+ void *res;
+ pthread_join(t, &res);
+ return res;
+}
+
+void *bar(void *input) {
+ return input;
+}
+
+void *glob = foo((void*)0x1234);
+extern void *glob2;
+
+int main() {
+ printf("%p %p\n", glob, glob2);
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/initialization-blacklist.cc b/lib/asan/lit_tests/TestCases/initialization-blacklist.cc
new file mode 100644
index 000000000000..f40fcc082f9a
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/initialization-blacklist.cc
@@ -0,0 +1,32 @@
+// Test for blacklist functionality of initialization-order checker.
+
+// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-blacklist-extra.cc\
+// RUN: %p/Helpers/initialization-blacklist-extra2.cc \
+// RUN: -fsanitize-blacklist=%p/Helpers/initialization-blacklist.txt \
+// RUN: -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+// RUN: %clangxx_asan -O1 %s %p/Helpers/initialization-blacklist-extra.cc\
+// RUN: %p/Helpers/initialization-blacklist-extra2.cc \
+// RUN: -fsanitize-blacklist=%p/Helpers/initialization-blacklist.txt \
+// RUN: -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+// RUN: %clangxx_asan -O2 %s %p/Helpers/initialization-blacklist-extra.cc\
+// RUN: %p/Helpers/initialization-blacklist-extra2.cc \
+// RUN: -fsanitize-blacklist=%p/Helpers/initialization-blacklist.txt \
+// RUN: -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+
+// Function is defined in another TU.
+int readBadGlobal();
+int x = readBadGlobal(); // init-order bug.
+
+// Function is defined in another TU.
+int accessBadObject();
+int y = accessBadObject(); // init-order bug.
+
+int readBadSrcGlobal();
+int z = readBadSrcGlobal(); // init-order bug.
+
+int main(int argc, char **argv) {
+ return argc + x + y + z - 1;
+}
diff --git a/lib/asan/lit_tests/TestCases/initialization-bug.cc b/lib/asan/lit_tests/TestCases/initialization-bug.cc
new file mode 100644
index 000000000000..fb289b1c7ebe
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/initialization-bug.cc
@@ -0,0 +1,45 @@
+// Test to make sure basic initialization order errors are caught.
+
+// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true not %t 2>&1 | FileCheck %s
+
+// Do not test with optimization -- the error may be optimized away.
+
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=186
+// XFAIL: darwin
+
+#include <cstdio>
+
+// The structure of the test is:
+// "x", "y", "z" are dynamically initialized globals.
+// Value of "x" depends on "y", value of "y" depends on "z".
+// "x" and "z" are defined in this TU, "y" is defined in another one.
+// Thus we shoud stably report initialization order fiasco independently of
+// the translation unit order.
+
+int initZ() {
+ return 5;
+}
+int z = initZ();
+
+// 'y' is a dynamically initialized global residing in a different TU. This
+// dynamic initializer will read the value of 'y' before main starts. The
+// result is undefined behavior, which should be caught by initialization order
+// checking.
+extern int y;
+int __attribute__((noinline)) initX() {
+ return y + 1;
+ // CHECK: {{AddressSanitizer: initialization-order-fiasco}}
+ // CHECK: {{READ of size .* at 0x.* thread T0}}
+ // CHECK: {{0x.* is located 0 bytes inside of global variable .*(y|z).*}}
+}
+
+// This initializer begins our initialization order problems.
+static int x = initX();
+
+int main() {
+ // ASan should have caused an exit before main runs.
+ printf("PASS\n");
+ // CHECK-NOT: PASS
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/initialization-constexpr.cc b/lib/asan/lit_tests/TestCases/initialization-constexpr.cc
new file mode 100644
index 000000000000..65c95edd5081
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/initialization-constexpr.cc
@@ -0,0 +1,31 @@
+// Constexpr:
+// We need to check that a global variable initialized with a constexpr
+// constructor can be accessed during dynamic initialization (as a constexpr
+// constructor implies that it was initialized during constant initialization,
+// not dynamic initialization).
+
+// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-constexpr-extra.cc\
+// RUN: --std=c++11 -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+// RUN: %clangxx_asan -O1 %s %p/Helpers/initialization-constexpr-extra.cc\
+// RUN: --std=c++11 -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+// RUN: %clangxx_asan -O2 %s %p/Helpers/initialization-constexpr-extra.cc\
+// RUN: --std=c++11 -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+// RUN: %clangxx_asan -O3 %s %p/Helpers/initialization-constexpr-extra.cc\
+// RUN: --std=c++11 -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+
+class Integer {
+ private:
+ int value;
+
+ public:
+ constexpr Integer(int x = 0) : value(x) {}
+ int getValue() {return value;}
+};
+Integer coolestInteger(42);
+int getCoolestInteger() { return coolestInteger.getValue(); }
+
+int main() { return 0; }
diff --git a/lib/asan/lit_tests/TestCases/initialization-nobug.cc b/lib/asan/lit_tests/TestCases/initialization-nobug.cc
new file mode 100644
index 000000000000..ed37d137f8cb
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/initialization-nobug.cc
@@ -0,0 +1,48 @@
+// A collection of various initializers which shouldn't trip up initialization
+// order checking. If successful, this will just return 0.
+
+// RUN: %clangxx_asan -O0 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+// RUN: %clangxx_asan -O1 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+// RUN: %clangxx_asan -O2 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+// RUN: %clangxx_asan -O3 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t
+// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1
+
+// Simple access:
+// Make sure that accessing a global in the same TU is safe
+
+bool condition = true;
+int initializeSameTU() {
+ return condition ? 0x2a : 052;
+}
+int sameTU = initializeSameTU();
+
+// Linker initialized:
+// Check that access to linker initialized globals originating from a different
+// TU's initializer is safe.
+
+int A = (1 << 1) + (1 << 3) + (1 << 5), B;
+int getAB() {
+ return A * B;
+}
+
+// Function local statics:
+// Check that access to function local statics originating from a different
+// TU's initializer is safe.
+
+int countCalls() {
+ static int calls;
+ return ++calls;
+}
+
+// Trivial constructor, non-trivial destructor.
+struct StructWithDtor {
+ ~StructWithDtor() { }
+ int value;
+};
+StructWithDtor struct_with_dtor;
+int getStructWithDtorValue() { return struct_with_dtor.value; }
+
+int main() { return 0; }
diff --git a/lib/asan/lit_tests/TestCases/inline.cc b/lib/asan/lit_tests/TestCases/inline.cc
new file mode 100644
index 000000000000..792aff59f4ba
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/inline.cc
@@ -0,0 +1,19 @@
+// RUN: %clangxx_asan -O3 %s -o %t && %t
+
+// Test that no_sanitize_address attribute applies even when the function would
+// be normally inlined.
+
+#include <stdlib.h>
+
+__attribute__((no_sanitize_address))
+int f(int *p) {
+ return *p; // BOOOM?? Nope!
+}
+
+int main(int argc, char **argv) {
+ int * volatile x = (int*)malloc(2*sizeof(int) + 2);
+ int res = f(x + 2);
+ if (res)
+ exit(0);
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/interface_test.cc b/lib/asan/lit_tests/TestCases/interface_test.cc
new file mode 100644
index 000000000000..297b5526e9d9
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/interface_test.cc
@@ -0,0 +1,8 @@
+// Check that user may include ASan interface header.
+// RUN: %clang_asan %s -o %t && %t
+// RUN: %clang %s -o %t && %t
+#include <sanitizer/asan_interface.h>
+
+int main() {
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/invalid-free.cc b/lib/asan/lit_tests/TestCases/invalid-free.cc
new file mode 100644
index 000000000000..f940b501279a
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/invalid-free.cc
@@ -0,0 +1,21 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=MALLOC-CTX
+
+// Also works if no malloc context is available.
+// RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+#include <string.h>
+int main(int argc, char **argv) {
+ char *x = (char*)malloc(10 * sizeof(char));
+ memset(x, 0, 10);
+ int res = x[argc];
+ free(x + 5); // BOOM
+ // CHECK: AddressSanitizer: attempting free on address{{.*}}in thread T0
+ // CHECK: invalid-free.cc:[[@LINE-2]]
+ // CHECK: is located 5 bytes inside of 10-byte region
+ // CHECK: allocated by thread T0 here:
+ // MALLOC-CTX: invalid-free.cc:[[@LINE-8]]
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/ioctl.cc b/lib/asan/lit_tests/TestCases/ioctl.cc
new file mode 100644
index 000000000000..08ca688d3872
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/ioctl.cc
@@ -0,0 +1,24 @@
+// RUN: %clangxx_asan -O0 -g %s -o %t && ASAN_OPTIONS=handle_ioctl=1 not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 -g %s -o %t && ASAN_OPTIONS=handle_ioctl=1 not %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -O0 -g %s -o %t && %t
+// RUN: %clangxx_asan -O3 -g %s -o %t && %t
+
+#include <assert.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ int nonblock;
+ int res = ioctl(fd, FIONBIO, &nonblock + 1);
+ // CHECK: AddressSanitizer: stack-buffer-overflow
+ // CHECK: READ of size 4 at
+ // CHECK: {{#.* in main .*ioctl.cc:}}[[@LINE-3]]
+ assert(res == 0);
+ close(fd);
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/large_func_test.cc b/lib/asan/lit_tests/TestCases/large_func_test.cc
new file mode 100644
index 000000000000..0534bcd31142
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/large_func_test.cc
@@ -0,0 +1,51 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+
+#include <stdlib.h>
+__attribute__((noinline))
+static void LargeFunction(int *x, int zero) {
+ x[0]++;
+ x[1]++;
+ x[2]++;
+ x[3]++;
+ x[4]++;
+ x[5]++;
+ x[6]++;
+ x[7]++;
+ x[8]++;
+ x[9]++;
+
+ // CHECK: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}}
+ // CHECK: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}}
+ // CHECK: {{READ of size 4 at 0x.* thread T0}}
+ x[zero + 103]++; // we should report this exact line
+ // atos incorrectly extracts the symbol name for the static functions on
+ // Darwin.
+ // CHECK-Linux: {{#0 0x.* in LargeFunction.*large_func_test.cc:}}[[@LINE-3]]
+ // CHECK-Darwin: {{#0 0x.* in .*LargeFunction.*large_func_test.cc}}:[[@LINE-4]]
+
+ x[10]++;
+ x[11]++;
+ x[12]++;
+ x[13]++;
+ x[14]++;
+ x[15]++;
+ x[16]++;
+ x[17]++;
+ x[18]++;
+ x[19]++;
+}
+
+int main(int argc, char **argv) {
+ int *x = new int[100];
+ LargeFunction(x, argc - 1);
+ // CHECK: {{ #1 0x.* in main .*large_func_test.cc:}}[[@LINE-1]]
+ // CHECK: {{0x.* is located 12 bytes to the right of 400-byte region}}
+ // CHECK: {{allocated by thread T0 here:}}
+ // CHECK-Linux: {{ #0 0x.* in operator new.*}}
+ // CHECK-Darwin: {{ #0 0x.* in .*_Zna.*}}
+ // CHECK: {{ #1 0x.* in main .*large_func_test.cc:}}[[@LINE-7]]
+ delete x;
+}
diff --git a/lib/asan/lit_tests/TestCases/log-path_test.cc b/lib/asan/lit_tests/TestCases/log-path_test.cc
new file mode 100644
index 000000000000..1072670fbff4
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/log-path_test.cc
@@ -0,0 +1,39 @@
+// RUN: %clangxx_asan %s -o %t
+
+// Regular run.
+// RUN: not %t 2> %t.out
+// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %t.out
+
+// Good log_path.
+// RUN: rm -f %t.log.*
+// RUN: ASAN_OPTIONS=log_path=%t.log not %t 2> %t.out
+// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %t.log.*
+
+// Invalid log_path.
+// RUN: ASAN_OPTIONS=log_path=/INVALID not %t 2> %t.out
+// RUN: FileCheck %s --check-prefix=CHECK-INVALID < %t.out
+
+// Too long log_path.
+// RUN: ASAN_OPTIONS=log_path=`for((i=0;i<10000;i++)); do echo -n $i; done` \
+// RUN: not %t 2> %t.out
+// RUN: FileCheck %s --check-prefix=CHECK-LONG < %t.out
+
+// Run w/o errors should not produce any log.
+// RUN: rm -f %t.log.*
+// RUN: ASAN_OPTIONS=log_path=%t.log %t ARG ARG ARG
+// RUN: not cat %t.log.*
+
+
+#include <stdlib.h>
+#include <string.h>
+int main(int argc, char **argv) {
+ if (argc > 2) return 0;
+ char *x = (char*)malloc(10);
+ memset(x, 0, 10);
+ int res = x[argc * 10]; // BOOOM
+ free(x);
+ return res;
+}
+// CHECK-ERROR: ERROR: AddressSanitizer
+// CHECK-INVALID: ERROR: Can't open file: /INVALID
+// CHECK-LONG: ERROR: Path is too long: 01234
diff --git a/lib/asan/lit_tests/TestCases/log_path_fork_test.cc.disabled b/lib/asan/lit_tests/TestCases/log_path_fork_test.cc.disabled
new file mode 100644
index 000000000000..c6c1b49e994d
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/log_path_fork_test.cc.disabled
@@ -0,0 +1,22 @@
+// 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: ASAN_OPTIONS="log_path=%t.log verbosity=1" not %t 2> %t.out
+// RUN: for f in %t.log.* ; do FileCheck %s < $f; done
+// RUN: [ `ls %t.log.* | wc -l` == 2 ]
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ void *x = malloc(10);
+ free(x);
+ if (fork() == -1) return 1;
+ // There are two processes at this point, thus there should be two distinct
+ // error logs.
+ free(x);
+ return 0;
+}
+
+// CHECK: ERROR: AddressSanitizer
diff --git a/lib/asan/lit_tests/TestCases/lsan_annotations.cc b/lib/asan/lit_tests/TestCases/lsan_annotations.cc
new file mode 100644
index 000000000000..c55ab8692eb5
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/lsan_annotations.cc
@@ -0,0 +1,16 @@
+// Check that LSan annotations work fine.
+// RUN: %clangxx_asan -O0 %s -o %t && %t
+// RUN: %clangxx_asan -O3 %s -o %t && %t
+
+#include <sanitizer/lsan_interface.h>
+#include <stdlib.h>
+
+int main() {
+ int *x = new int;
+ __lsan_ignore_object(x);
+ {
+ __lsan::ScopedDisabler disabler;
+ double *y = new double;
+ }
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/malloc_context_size.cc b/lib/asan/lit_tests/TestCases/malloc_context_size.cc
new file mode 100644
index 000000000000..266ce66f59e2
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/malloc_context_size.cc
@@ -0,0 +1,27 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os
+// RUN: ASAN_OPTIONS=malloc_context_size=0:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os
+// RUN: ASAN_OPTIONS=malloc_context_size=1:fast_unwind_on_malloc=0 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os
+// RUN: ASAN_OPTIONS=malloc_context_size=1:fast_unwind_on_malloc=1 not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os
+
+int main() {
+ char *x = new char[20];
+ delete[] x;
+ return x[0];
+ // We need to keep duplicate lines with different 'CHECK-%os' prefixes,
+ // otherwise FileCheck barks on missing 'CHECK-%os' before 'CHECK-%os-NEXT'.
+
+ // CHECK-Linux: freed by thread T{{.*}} here:
+ // CHECK-Linux-NEXT: #0 0x{{.*}} in operator delete[]
+ // CHECK-Darwin: freed by thread T{{.*}} here:
+ // CHECK-Darwin-NEXT: #0 0x{{.*}} in wrap__ZdaPv
+ // CHECK-NOT: #1 0x{{.*}}
+
+ // CHECK-Linux: previously allocated by thread T{{.*}} here:
+ // CHECK-Linux-NEXT: #0 0x{{.*}} in operator new[]
+ // CHECK-Darwin: previously allocated by thread T{{.*}} here:
+ // CHECK-Darwin-NEXT: #0 0x{{.*}} in wrap__Znam
+ // CHECK-NOT: #1 0x{{.*}}
+
+ // CHECK: SUMMARY: AddressSanitizer: heap-use-after-free
+}
diff --git a/lib/asan/lit_tests/TestCases/malloc_fill.cc b/lib/asan/lit_tests/TestCases/malloc_fill.cc
new file mode 100644
index 000000000000..57f50d1438b7
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/malloc_fill.cc
@@ -0,0 +1,22 @@
+// Check that we fill malloc-ed memory correctly.
+// RUN: %clangxx_asan %s -o %t
+// RUN: %t | FileCheck %s
+// RUN: ASAN_OPTIONS=max_malloc_fill_size=10:malloc_fill_byte=8 %t | FileCheck %s --check-prefix=CHECK-10-8
+// RUN: ASAN_OPTIONS=max_malloc_fill_size=20:malloc_fill_byte=171 %t | FileCheck %s --check-prefix=CHECK-20-ab
+
+#include <stdio.h>
+int main(int argc, char **argv) {
+ // With asan allocator this makes sure we get memory from mmap.
+ static const int kSize = 1 << 25;
+ unsigned char *x = new unsigned char[kSize];
+ printf("-");
+ for (int i = 0; i <= 32; i++) {
+ printf("%02x", x[i]);
+ }
+ printf("-\n");
+ delete [] x;
+}
+
+// CHECK: -bebebebebebebebebebebebebebebebebebebebebebebebebebebebebebebebebe-
+// CHECK-10-8: -080808080808080808080000000000000000000000000000000000000000000000-
+// CHECK-20-ab: -abababababababababababababababababababab00000000000000000000000000-
diff --git a/lib/asan/lit_tests/TestCases/malloc_hook.cc b/lib/asan/lit_tests/TestCases/malloc_hook.cc
new file mode 100644
index 000000000000..83be1020ea43
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/malloc_hook.cc
@@ -0,0 +1,36 @@
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: %t 2>&1 | FileCheck %s
+#include <stdlib.h>
+#include <unistd.h>
+
+extern "C" {
+bool __asan_get_ownership(const void *p);
+
+void *global_ptr;
+
+// Note: avoid calling functions that allocate memory in malloc/free
+// to avoid infinite recursion.
+void __asan_malloc_hook(void *ptr, size_t sz) {
+ if (__asan_get_ownership(ptr)) {
+ write(1, "MallocHook\n", sizeof("MallocHook\n"));
+ global_ptr = ptr;
+ }
+}
+void __asan_free_hook(void *ptr) {
+ if (__asan_get_ownership(ptr) && ptr == global_ptr)
+ write(1, "FreeHook\n", sizeof("FreeHook\n"));
+}
+} // extern "C"
+
+int main() {
+ volatile int *x = new int;
+ // CHECK: MallocHook
+ // Check that malloc hook was called with correct argument.
+ if (global_ptr != (void*)x) {
+ _exit(1);
+ }
+ *x = 0;
+ delete x;
+ // CHECK: FreeHook
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/memcmp_strict_test.cc b/lib/asan/lit_tests/TestCases/memcmp_strict_test.cc
new file mode 100644
index 000000000000..e06a8c7e9e2f
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/memcmp_strict_test.cc
@@ -0,0 +1,15 @@
+// RUN: %clangxx_asan -O0 %s -o %t && ASAN_OPTIONS=strict_memcmp=0 %t
+// RUN: %clangxx_asan -O0 %s -o %t && ASAN_OPTIONS=strict_memcmp=1 not %t 2>&1 | FileCheck %s
+// Default to strict_memcmp=1.
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <string.h>
+int main() {
+ char kFoo[] = "foo";
+ char kFubar[] = "fubar";
+ int res = memcmp(kFoo, kFubar, strlen(kFubar));
+ printf("res: %d\n", res);
+ // CHECK: AddressSanitizer: stack-buffer-overflow
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/memcmp_test.cc b/lib/asan/lit_tests/TestCases/memcmp_test.cc
new file mode 100644
index 000000000000..758311ddc476
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/memcmp_test.cc
@@ -0,0 +1,17 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+// REQUIRES: compiler-rt-optimized
+
+#include <string.h>
+int main(int argc, char **argv) {
+ char a1[] = {argc, 2, 3, 4};
+ char a2[] = {1, 2*argc, 3, 4};
+ int res = memcmp(a1, a2, 4 + argc); // BOOM
+ // CHECK: AddressSanitizer: stack-buffer-overflow
+ // CHECK: {{#0.*memcmp}}
+ // CHECK: {{#1.*main}}
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/null_deref.cc b/lib/asan/lit_tests/TestCases/null_deref.cc
new file mode 100644
index 000000000000..476418324cc5
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/null_deref.cc
@@ -0,0 +1,19 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+
+__attribute__((noinline))
+static void NullDeref(int *ptr) {
+ // CHECK: ERROR: AddressSanitizer: SEGV on unknown address
+ // CHECK: {{0x0*00028 .*pc 0x.*}}
+ ptr[10]++; // BOOM
+ // atos on Mac cannot extract the symbol name correctly.
+ // CHECK-Linux: {{ #0 0x.* in NullDeref.*null_deref.cc:}}[[@LINE-2]]
+ // CHECK-Darwin: {{ #0 0x.* in .*NullDeref.*null_deref.cc:}}[[@LINE-3]]
+}
+int main() {
+ NullDeref((int*)0);
+ // CHECK: {{ #1 0x.* in main.*null_deref.cc:}}[[@LINE-1]]
+ // CHECK: {{AddressSanitizer can not provide additional info.}}
+}
diff --git a/lib/asan/lit_tests/TestCases/on_error_callback.cc b/lib/asan/lit_tests/TestCases/on_error_callback.cc
new file mode 100644
index 000000000000..d0cec2eb2703
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/on_error_callback.cc
@@ -0,0 +1,16 @@
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C"
+void __asan_on_error() {
+ fprintf(stderr, "__asan_on_error called");
+}
+
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+ // CHECK: __asan_on_error called
+}
diff --git a/lib/asan/lit_tests/TestCases/partial_right.cc b/lib/asan/lit_tests/TestCases/partial_right.cc
new file mode 100644
index 000000000000..a000a913d6be
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/partial_right.cc
@@ -0,0 +1,13 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+int main(int argc, char **argv) {
+ volatile int *x = (int*)malloc(2*sizeof(int) + 2);
+ int res = x[2]; // BOOOM
+ // CHECK: {{READ of size 4 at 0x.* thread T0}}
+ // CHECK: [[ADDR:0x[01-9a-fa-f]+]] is located 0 bytes to the right of {{.*}}-byte region [{{.*}},{{.*}}[[ADDR]])
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/poison_partial.cc b/lib/asan/lit_tests/TestCases/poison_partial.cc
new file mode 100644
index 000000000000..f7c48bf597b6
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/poison_partial.cc
@@ -0,0 +1,19 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: not %t heap 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=poison_partial=0 %t
+// RUN: ASAN_OPTIONS=poison_partial=0 %t heap
+#include <string.h>
+char g[21];
+char *x;
+
+int main(int argc, char **argv) {
+ if (argc >= 2)
+ x = new char[21];
+ else
+ x = &g[0];
+ memset(x, 0, 21);
+ int *y = (int*)x;
+ return y[5];
+}
+// CHECK: 0 bytes to the right
diff --git a/lib/asan/lit_tests/TestCases/print_summary.cc b/lib/asan/lit_tests/TestCases/print_summary.cc
new file mode 100644
index 000000000000..949c9b54f8a3
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/print_summary.cc
@@ -0,0 +1,14 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s --check-prefix=YES
+// RUN: ASAN_OPTIONS=print_summary=false not %t 2>&1 | FileCheck %s --check-prefix=NO
+
+int main() {
+ char *x = new char[20];
+ delete[] x;
+ return x[0];
+ // YES: ERROR: AddressSanitizer: heap-use-after-free
+ // YES: SUMMARY: AddressSanitizer: heap-use-after-free
+ // NO: ERROR: AddressSanitizer: heap-use-after-free
+ // NO-NOT: SUMMARY: AddressSanitizer: heap-use-after-free
+}
+
diff --git a/lib/asan/lit_tests/TestCases/readv.cc b/lib/asan/lit_tests/TestCases/readv.cc
new file mode 100644
index 000000000000..ba17505f37ac
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/readv.cc
@@ -0,0 +1,32 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %t
+// RUN: %clangxx_asan -O0 %s -DPOSITIVE -o %t && not %t 2>&1 | FileCheck %s
+
+// Test the readv() interceptor.
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/uio.h>
+#include <time.h>
+
+int main() {
+ char buf[2011];
+ struct iovec iov[2];
+#ifdef POSITIVE
+ char * volatile buf_ = buf;
+ iov[0].iov_base = buf_ - 1;
+#else
+ iov[0].iov_base = buf + 1;
+#endif
+ iov[0].iov_len = 5;
+ iov[1].iov_base = buf + 10;
+ iov[1].iov_len = 2000;
+ int fd = open("/etc/hosts", O_RDONLY);
+ assert(fd > 0);
+ readv(fd, iov, 2);
+ // CHECK: WRITE of size 5 at
+ close(fd);
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/sanity_check_pure_c.c b/lib/asan/lit_tests/TestCases/sanity_check_pure_c.c
new file mode 100644
index 000000000000..df150675bd97
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/sanity_check_pure_c.c
@@ -0,0 +1,19 @@
+// Sanity checking a test in pure C.
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+
+// Sanity checking a test in pure C with -pie.
+// RUN: %clang_asan -O2 %s -pie -o %t
+// RUN: not %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+ // CHECK: heap-use-after-free
+ // CHECK: free
+ // CHECK: main{{.*}}sanity_check_pure_c.c:[[@LINE-4]]
+ // CHECK: malloc
+ // CHECK: main{{.*}}sanity_check_pure_c.c:[[@LINE-7]]
+}
diff --git a/lib/asan/lit_tests/TestCases/shared-lib-test.cc b/lib/asan/lit_tests/TestCases/shared-lib-test.cc
new file mode 100644
index 000000000000..126903a55866
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/shared-lib-test.cc
@@ -0,0 +1,42 @@
+// RUN: %clangxx_asan -O0 %p/SharedLibs/shared-lib-test-so.cc \
+// RUN: -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %p/SharedLibs/shared-lib-test-so.cc \
+// RUN: -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %p/SharedLibs/shared-lib-test-so.cc \
+// RUN: -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %p/SharedLibs/shared-lib-test-so.cc \
+// RUN: -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+
+using std::string;
+
+typedef void (fun_t)(int x);
+
+int main(int argc, char *argv[]) {
+ string path = string(argv[0]) + "-so.so";
+ 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 *inc = (fun_t*)dlsym(lib, "inc");
+ if (!inc) return 1;
+ printf("ok\n");
+ inc(1);
+ inc(-1); // BOOM
+ // CHECK: {{.*ERROR: AddressSanitizer: global-buffer-overflow}}
+ // CHECK: {{READ of size 4 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.*}}
+ // CHECK: {{ #1 0x.* in main .*shared-lib-test.cc:}}[[@LINE-4]]
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/sleep_before_dying.c b/lib/asan/lit_tests/TestCases/sleep_before_dying.c
new file mode 100644
index 000000000000..8dee9f2778ce
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/sleep_before_dying.c
@@ -0,0 +1,10 @@
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS="sleep_before_dying=1" not %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+ // CHECK: Sleeping for 1 second
+}
diff --git a/lib/asan/lit_tests/TestCases/stack-buffer-overflow-with-position.cc b/lib/asan/lit_tests/TestCases/stack-buffer-overflow-with-position.cc
new file mode 100644
index 000000000000..91820db0142a
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/stack-buffer-overflow-with-position.cc
@@ -0,0 +1,45 @@
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: not %t -2 2>&1 | FileCheck --check-prefix=CHECK-m2 %s
+// RUN: not %t -1 2>&1 | FileCheck --check-prefix=CHECK-m1 %s
+// RUN: %t 0
+// RUN: %t 8
+// RUN: not %t 9 2>&1 | FileCheck --check-prefix=CHECK-9 %s
+// RUN: not %t 10 2>&1 | FileCheck --check-prefix=CHECK-10 %s
+// RUN: not %t 62 2>&1 | FileCheck --check-prefix=CHECK-62 %s
+// RUN: not %t 63 2>&1 | FileCheck --check-prefix=CHECK-63 %s
+// RUN: not %t 63 2>&1 | FileCheck --check-prefix=CHECK-63 %s
+// RUN: not %t 73 2>&1 | FileCheck --check-prefix=CHECK-73 %s
+// RUN: not %t 74 2>&1 | FileCheck --check-prefix=CHECK-74 %s
+// RUN: not %t 126 2>&1 | FileCheck --check-prefix=CHECK-126 %s
+// RUN: not %t 127 2>&1 | FileCheck --check-prefix=CHECK-127 %s
+// RUN: not %t 137 2>&1 | FileCheck --check-prefix=CHECK-137 %s
+// RUN: not %t 138 2>&1 | FileCheck --check-prefix=CHECK-138 %s
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+int main(int argc, char **argv) {
+ assert(argc >= 2);
+ int idx = atoi(argv[1]);
+ char AAA[10], BBB[10], CCC[10];
+ memset(AAA, 0, sizeof(AAA));
+ memset(BBB, 0, sizeof(BBB));
+ memset(CCC, 0, sizeof(CCC));
+ int res = 0;
+ char *p = AAA + idx;
+ printf("AAA: %p\ny: %p\nz: %p\np: %p\n", AAA, BBB, CCC, p);
+ // make sure BBB and CCC are not removed;
+ return *(short*)(p) + BBB[argc % 2] + CCC[argc % 2];
+}
+// CHECK-m2: 'AAA' <== Memory access at offset 30 underflows this variable
+// CHECK-m1: 'AAA' <== Memory access at offset 31 partially underflows this variable
+// CHECK-9: 'AAA' <== Memory access at offset 41 partially overflows this variable
+// CHECK-10: 'AAA' <== Memory access at offset 42 overflows this variable
+// CHECK-62: 'BBB' <== Memory access at offset 94 underflows this variable
+// CHECK-63: 'BBB' <== Memory access at offset 95 partially underflows this variable
+// CHECK-73: 'BBB' <== Memory access at offset 105 partially overflows this variable
+// CHECK-74: 'BBB' <== Memory access at offset 106 overflows this variable
+// CHECK-126: 'CCC' <== Memory access at offset 158 underflows this variable
+// CHECK-127: 'CCC' <== Memory access at offset 159 partially underflows this variable
+// CHECK-137: 'CCC' <== Memory access at offset 169 partially overflows this variable
+// CHECK-138: 'CCC' <== Memory access at offset 170 overflows this variable
diff --git a/lib/asan/lit_tests/TestCases/stack-frame-demangle.cc b/lib/asan/lit_tests/TestCases/stack-frame-demangle.cc
new file mode 100644
index 000000000000..2b83ecc2923b
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/stack-frame-demangle.cc
@@ -0,0 +1,22 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <string.h>
+
+namespace XXX {
+struct YYY {
+ static int ZZZ(int x) {
+ char array[10];
+ memset(array, 0, 10);
+ return array[x]; // BOOOM
+ // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow
+ // CHECK: READ of size 1 at
+ // CHECK: is located in stack of thread T0 at offset
+ // CHECK: XXX::YYY::ZZZ
+ }
+};
+} // namespace XXX
+
+int main(int argc, char **argv) {
+ int res = XXX::YYY::ZZZ(argc + 10);
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/stack-oob-frames.cc b/lib/asan/lit_tests/TestCases/stack-oob-frames.cc
new file mode 100644
index 000000000000..909e700b3d00
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/stack-oob-frames.cc
@@ -0,0 +1,59 @@
+// RUN: %clangxx_asan -O1 %s -o %t
+// RUN: not %t 0 2>&1 | FileCheck %s --check-prefix=CHECK0
+// RUN: not %t 1 2>&1 | FileCheck %s --check-prefix=CHECK1
+// RUN: not %t 2 2>&1 | FileCheck %s --check-prefix=CHECK2
+// RUN: not %t 3 2>&1 | FileCheck %s --check-prefix=CHECK3
+
+#define NOINLINE __attribute__((noinline))
+inline void break_optimization(void *arg) {
+ __asm__ __volatile__("" : : "r" (arg) : "memory");
+}
+
+NOINLINE static void Frame0(int frame, char *a, char *b, char *c) {
+ char s[4] = {0};
+ char *d = s;
+ break_optimization(&d);
+ switch (frame) {
+ case 3: a[5]++; break;
+ case 2: b[5]++; break;
+ case 1: c[5]++; break;
+ case 0: d[5]++; break;
+ }
+}
+NOINLINE static void Frame1(int frame, char *a, char *b) {
+ char c[4] = {0}; Frame0(frame, a, b, c);
+ break_optimization(0);
+}
+NOINLINE static void Frame2(int frame, char *a) {
+ char b[4] = {0}; Frame1(frame, a, b);
+ break_optimization(0);
+}
+NOINLINE static void Frame3(int frame) {
+ char a[4] = {0}; Frame2(frame, a);
+ break_optimization(0);
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) return 1;
+ Frame3(argv[1][0] - '0');
+}
+
+// CHECK0: AddressSanitizer: stack-buffer-overflow
+// CHECK0: #0{{.*}}Frame0
+// CHECK0: #1{{.*}}Frame1
+// CHECK0: #2{{.*}}Frame2
+// CHECK0: #3{{.*}}Frame3
+// CHECK0: is located in stack of thread T0 at offset
+// CHECK0-NEXT: #0{{.*}}Frame0
+//
+// CHECK1: AddressSanitizer: stack-buffer-overflow
+// CHECK1: is located in stack of thread T0 at offset
+// CHECK1-NEXT: #0{{.*}}Frame1
+//
+// CHECK2: AddressSanitizer: stack-buffer-overflow
+// CHECK2: is located in stack of thread T0 at offset
+// CHECK2-NEXT: #0{{.*}}Frame2
+//
+// CHECK3: AddressSanitizer: stack-buffer-overflow
+// CHECK3: is located in stack of thread T0 at offset
+// CHECK3-NEXT: #0{{.*}}Frame3
diff --git a/lib/asan/lit_tests/TestCases/stack-overflow.cc b/lib/asan/lit_tests/TestCases/stack-overflow.cc
new file mode 100644
index 000000000000..adf1c0784f70
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/stack-overflow.cc
@@ -0,0 +1,16 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <string.h>
+int main(int argc, char **argv) {
+ char x[10];
+ memset(x, 0, 10);
+ int res = x[argc * 10]; // BOOOM
+ // CHECK: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.* in main .*stack-overflow.cc:}}[[@LINE-2]]
+ // CHECK: {{Address 0x.* is located in stack of thread T0 at offset}}
+ // CHECK-NEXT: in{{.*}}main{{.*}}stack-overflow.cc
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/stack-use-after-return.cc b/lib/asan/lit_tests/TestCases/stack-use-after-return.cc
new file mode 100644
index 000000000000..5ed42a8c0c97
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/stack-use-after-return.cc
@@ -0,0 +1,77 @@
+// RUN: export ASAN_OPTIONS=detect_stack_use_after_return=1
+// RUN: %clangxx_asan -O0 %s -o %t && \
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && \
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && \
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && \
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=detect_stack_use_after_return=0 %t
+// Regression test for a CHECK failure with small stack size and large frame.
+// RUN: %clangxx_asan -O3 %s -o %t -DkSize=10000 && \
+// RUN: (ulimit -s 65; not %t) 2>&1 | FileCheck %s
+//
+// Test that we can find UAR in a thread other than main:
+// RUN: %clangxx_asan -DUseThread -O2 %s -o %t && \
+// RUN: not %t 2>&1 | FileCheck --check-prefix=THREAD %s
+//
+// Test the uar_stack_size_log flag.
+//
+// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:uar_stack_size_log=20:verbosity=1 not %t 2>&1 | FileCheck --check-prefix=CHECK-20 %s
+// RUN: ASAN_OPTIONS=$ASAN_OPTIONS:uar_stack_size_log=24:verbosity=1 not %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
+
+__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 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 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_t t;
+ pthread_create(&t, 0, Thread, 0);
+ pthread_join(t, 0);
+#else
+ Func2(Func1());
+#endif
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/strdup_oob_test.cc b/lib/asan/lit_tests/TestCases/strdup_oob_test.cc
new file mode 100644
index 000000000000..e92afd3caaf9
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/strdup_oob_test.cc
@@ -0,0 +1,19 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <string.h>
+
+char kString[] = "foo";
+
+int main(int argc, char **argv) {
+ char *copy = strdup(kString);
+ int x = copy[4 + argc]; // BOOM
+ // CHECK: AddressSanitizer: heap-buffer-overflow
+ // CHECK: #0 {{.*}}main {{.*}}strdup_oob_test.cc:[[@LINE-2]]
+ // CHECK: allocated by thread T{{.*}} here:
+ // CHECK: #0 {{.*}}strdup
+ // CHECK: strdup_oob_test.cc:[[@LINE-6]]
+ return x;
+}
diff --git a/lib/asan/lit_tests/TestCases/strerror_r_test.cc b/lib/asan/lit_tests/TestCases/strerror_r_test.cc
new file mode 100644
index 000000000000..0df009b83f9c
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/strerror_r_test.cc
@@ -0,0 +1,13 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %t
+
+// Regression test for PR17138.
+
+#include <assert.h>
+#include <string.h>
+
+int main() {
+ char buf[1024];
+ char *res = (char *)strerror_r(300, buf, sizeof(buf));
+ assert(res != 0);
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/strip_path_prefix.c b/lib/asan/lit_tests/TestCases/strip_path_prefix.c
new file mode 100644
index 000000000000..c4d6ba49d5e3
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/strip_path_prefix.c
@@ -0,0 +1,12 @@
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS="strip_path_prefix='/'" not %t 2>&1 | FileCheck %s
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+ // Check that paths in error report don't start with slash.
+ // CHECK: heap-use-after-free
+ // CHECK-NOT: #0 0x{{.*}} ({{[/].*}})
+}
diff --git a/lib/asan/lit_tests/TestCases/strncpy-overflow.cc b/lib/asan/lit_tests/TestCases/strncpy-overflow.cc
new file mode 100644
index 000000000000..f91e191fde23
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/strncpy-overflow.cc
@@ -0,0 +1,28 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+
+// REQUIRES: compiler-rt-optimized
+
+#include <string.h>
+#include <stdlib.h>
+int main(int argc, char **argv) {
+ char *hello = (char*)malloc(6);
+ strcpy(hello, "hello");
+ char *short_buffer = (char*)malloc(9);
+ strncpy(short_buffer, hello, 10); // BOOM
+ // CHECK: {{WRITE of size 10 at 0x.* thread T0}}
+ // CHECK-Linux: {{ #0 0x.* in .*strncpy}}
+ // CHECK-Darwin: {{ #0 0x.* in wrap_strncpy}}
+ // CHECK: {{ #1 0x.* in main .*strncpy-overflow.cc:}}[[@LINE-4]]
+ // CHECK: {{0x.* is located 0 bytes to the right of 9-byte region}}
+ // CHECK: {{allocated by thread T0 here:}}
+
+ // CHECK-Linux: {{ #0 0x.* in .*malloc}}
+ // CHECK-Linux: {{ #1 0x.* in main .*strncpy-overflow.cc:}}[[@LINE-10]]
+
+ // CHECK-Darwin: {{ #0 0x.* in wrap_malloc.*}}
+ // CHECK-Darwin: {{ #1 0x.* in main .*strncpy-overflow.cc:}}[[@LINE-13]]
+ return short_buffer[8];
+}
diff --git a/lib/asan/lit_tests/TestCases/symbolize_callback.cc b/lib/asan/lit_tests/TestCases/symbolize_callback.cc
new file mode 100644
index 000000000000..058b3150fbba
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/symbolize_callback.cc
@@ -0,0 +1,17 @@
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C"
+bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) {
+ snprintf(out_buffer, out_size, "MySymbolizer");
+ return true;
+}
+
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+ // CHECK: MySymbolizer
+}
diff --git a/lib/asan/lit_tests/TestCases/throw_call_test.cc b/lib/asan/lit_tests/TestCases/throw_call_test.cc
new file mode 100644
index 000000000000..974bc51d97c5
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/throw_call_test.cc
@@ -0,0 +1,45 @@
+// RUN: %clangxx_asan %s -o %t && %t
+// http://code.google.com/p/address-sanitizer/issues/detail?id=147 (not fixed).
+// BROKEN: %clangxx_asan %s -o %t -static-libstdc++ && %t
+#include <stdio.h>
+static volatile int zero = 0;
+inline void pretend_to_do_something(void *x) {
+ __asm__ __volatile__("" : : "r" (x) : "memory");
+}
+
+__attribute__((noinline, no_sanitize_address))
+void ReallyThrow() {
+ fprintf(stderr, "ReallyThrow\n");
+ if (zero == 0)
+ throw 42;
+}
+
+__attribute__((noinline))
+void Throw() {
+ int a, b, c, d, e;
+ pretend_to_do_something(&a);
+ pretend_to_do_something(&b);
+ pretend_to_do_something(&c);
+ pretend_to_do_something(&d);
+ pretend_to_do_something(&e);
+ fprintf(stderr, "Throw stack = %p\n", &a);
+ ReallyThrow();
+}
+
+__attribute__((noinline))
+void CheckStack() {
+ int ar[100];
+ pretend_to_do_something(ar);
+ for (int i = 0; i < 100; i++)
+ ar[i] = i;
+ fprintf(stderr, "CheckStack stack = %p, %p\n", ar, ar + 100);
+}
+
+int main(int argc, char** argv) {
+ try {
+ Throw();
+ } catch(int a) {
+ fprintf(stderr, "a = %d\n", a);
+ }
+ CheckStack();
+}
diff --git a/lib/asan/lit_tests/TestCases/throw_invoke_test.cc b/lib/asan/lit_tests/TestCases/throw_invoke_test.cc
new file mode 100644
index 000000000000..077a940e8d19
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/throw_invoke_test.cc
@@ -0,0 +1,50 @@
+// RUN: %clangxx_asan %s -o %t && %t
+// RUN: %clangxx_asan %s -o %t -static-libstdc++ && %t
+#include <stdio.h>
+static volatile int zero = 0;
+inline void pretend_to_do_something(void *x) {
+ __asm__ __volatile__("" : : "r" (x) : "memory");
+}
+
+__attribute__((noinline))
+void ReallyThrow() {
+ fprintf(stderr, "ReallyThrow\n");
+ try {
+ if (zero == 0)
+ throw 42;
+ else if (zero == 1)
+ throw 1.;
+ } catch(double x) {
+ }
+}
+
+__attribute__((noinline))
+void Throw() {
+ int a, b, c, d, e;
+ pretend_to_do_something(&a);
+ pretend_to_do_something(&b);
+ pretend_to_do_something(&c);
+ pretend_to_do_something(&d);
+ pretend_to_do_something(&e);
+ fprintf(stderr, "Throw stack = %p\n", &a);
+ ReallyThrow();
+}
+
+__attribute__((noinline))
+void CheckStack() {
+ int ar[100];
+ pretend_to_do_something(ar);
+ for (int i = 0; i < 100; i++)
+ ar[i] = i;
+ fprintf(stderr, "CheckStack stack = %p, %p\n", ar, ar + 100);
+}
+
+int main(int argc, char** argv) {
+ try {
+ Throw();
+ } catch(int a) {
+ fprintf(stderr, "a = %d\n", a);
+ }
+ CheckStack();
+}
+
diff --git a/lib/asan/lit_tests/TestCases/time_interceptor.cc b/lib/asan/lit_tests/TestCases/time_interceptor.cc
new file mode 100644
index 000000000000..3be00d60c01d
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/time_interceptor.cc
@@ -0,0 +1,16 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+
+// Test the time() interceptor.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+int main() {
+ time_t *tm = (time_t*)malloc(sizeof(time_t));
+ free(tm);
+ time_t t = time(tm);
+ printf("Time: %s\n", ctime(&t)); // NOLINT
+ // CHECK: use-after-free
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/uar_and_exceptions.cc b/lib/asan/lit_tests/TestCases/uar_and_exceptions.cc
new file mode 100644
index 000000000000..c967531c2c02
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/uar_and_exceptions.cc
@@ -0,0 +1,40 @@
+// Test that use-after-return works with exceptions.
+// export ASAN_OPTIONS=detect_stack_use_after_return=1
+// RUN: %clangxx_asan -O0 %s -o %t && %t
+
+#include <stdio.h>
+
+volatile char *g;
+
+#ifndef FRAME_SIZE
+# define FRAME_SIZE 100
+#endif
+
+#ifndef NUM_ITER
+# define NUM_ITER 4000
+#endif
+
+#ifndef DO_THROW
+# define DO_THROW 1
+#endif
+
+void Func(int depth) {
+ char frame[FRAME_SIZE];
+ g = &frame[0];
+ if (depth)
+ Func(depth - 1);
+ else if (DO_THROW)
+ throw 1;
+}
+
+int main(int argc, char **argv) {
+ for (int i = 0; i < NUM_ITER; i++) {
+ try {
+ Func(argc * 100);
+ } catch(...) {
+ }
+ if ((i % (NUM_ITER / 10)) == 0)
+ fprintf(stderr, "done [%d]\n", i);
+ }
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/unaligned_loads_and_stores.cc b/lib/asan/lit_tests/TestCases/unaligned_loads_and_stores.cc
new file mode 100644
index 000000000000..d50566c44e9a
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/unaligned_loads_and_stores.cc
@@ -0,0 +1,52 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %t A 2>&1 | FileCheck --check-prefix=CHECK-A %s
+// RUN: not %t B 2>&1 | FileCheck --check-prefix=CHECK-B %s
+// RUN: not %t C 2>&1 | FileCheck --check-prefix=CHECK-C %s
+// RUN: not %t D 2>&1 | FileCheck --check-prefix=CHECK-D %s
+// RUN: not %t E 2>&1 | FileCheck --check-prefix=CHECK-E %s
+
+// RUN: not %t K 2>&1 | FileCheck --check-prefix=CHECK-K %s
+// RUN: not %t L 2>&1 | FileCheck --check-prefix=CHECK-L %s
+// RUN: not %t M 2>&1 | FileCheck --check-prefix=CHECK-M %s
+// RUN: not %t N 2>&1 | FileCheck --check-prefix=CHECK-N %s
+// RUN: not %t O 2>&1 | FileCheck --check-prefix=CHECK-O %s
+
+#include <sanitizer/asan_interface.h>
+
+#include <stdlib.h>
+#include <string.h>
+int main(int argc, char **argv) {
+ if (argc != 2) return 1;
+ char *x = new char[16];
+ memset(x, 0xab, 16);
+ int res = 1;
+ switch (argv[1][0]) {
+ case 'A': res = __sanitizer_unaligned_load16(x + 15); break;
+// CHECK-A ERROR: AddressSanitizer: heap-buffer-overflow on address
+// CHECK-A: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-2]]
+// CHECK-A: is located 0 bytes to the right of 16-byte region
+ case 'B': res = __sanitizer_unaligned_load32(x + 14); break;
+// CHECK-B: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]]
+ case 'C': res = __sanitizer_unaligned_load32(x + 13); break;
+// CHECK-C: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]]
+ case 'D': res = __sanitizer_unaligned_load64(x + 15); break;
+// CHECK-D: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]]
+ case 'E': res = __sanitizer_unaligned_load64(x + 9); break;
+// CHECK-E: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]]
+
+ case 'K': __sanitizer_unaligned_store16(x + 15, 0); break;
+// CHECK-K ERROR: AddressSanitizer: heap-buffer-overflow on address
+// CHECK-K: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-2]]
+// CHECK-K: is located 0 bytes to the right of 16-byte region
+ case 'L': __sanitizer_unaligned_store32(x + 15, 0); break;
+// CHECK-L: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]]
+ case 'M': __sanitizer_unaligned_store32(x + 13, 0); break;
+// CHECK-M: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]]
+ case 'N': __sanitizer_unaligned_store64(x + 10, 0); break;
+// CHECK-N: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]]
+ case 'O': __sanitizer_unaligned_store64(x + 14, 0); break;
+// CHECK-O: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]]
+ }
+ delete x;
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/use-after-free-right.cc b/lib/asan/lit_tests/TestCases/use-after-free-right.cc
new file mode 100644
index 000000000000..88d91f53d24e
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/use-after-free-right.cc
@@ -0,0 +1,34 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+
+// Test use-after-free report in the case when access is at the right border of
+// the allocation.
+
+#include <stdlib.h>
+int main() {
+ volatile char *x = (char*)malloc(sizeof(char));
+ free((void*)x);
+ *x = 42;
+ // CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+ // CHECK: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}}
+ // CHECK: {{WRITE of size 1 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.* in main .*use-after-free-right.cc:13}}
+ // CHECK: {{0x.* is located 0 bytes inside of 1-byte region .0x.*,0x.*}}
+ // CHECK: {{freed by thread T0 here:}}
+
+ // CHECK-Linux: {{ #0 0x.* in .*free}}
+ // CHECK-Linux: {{ #1 0x.* in main .*use-after-free-right.cc:12}}
+
+ // CHECK-Darwin: {{ #0 0x.* in wrap_free}}
+ // CHECK-Darwin: {{ #1 0x.* in main .*use-after-free-right.cc:12}}
+
+ // CHECK: {{previously allocated by thread T0 here:}}
+
+ // CHECK-Linux: {{ #0 0x.* in .*malloc}}
+ // CHECK-Linux: {{ #1 0x.* in main .*use-after-free-right.cc:11}}
+
+ // CHECK-Darwin: {{ #0 0x.* in wrap_malloc.*}}
+ // CHECK-Darwin: {{ #1 0x.* in main .*use-after-free-right.cc:11}}
+}
diff --git a/lib/asan/lit_tests/TestCases/use-after-free.cc b/lib/asan/lit_tests/TestCases/use-after-free.cc
new file mode 100644
index 000000000000..84ba479c1393
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/use-after-free.cc
@@ -0,0 +1,31 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O1 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O2 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+// RUN: %clangxx_asan -O3 %s -o %t && not %t 2>&1 | FileCheck %s --check-prefix=CHECK-%os --check-prefix=CHECK
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+ // CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
+ // CHECK: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}}
+ // CHECK: {{READ of size 1 at 0x.* thread T0}}
+ // CHECK: {{ #0 0x.* in main .*use-after-free.cc:10}}
+ // CHECK: {{0x.* is located 5 bytes inside of 10-byte region .0x.*,0x.*}}
+ // CHECK: {{freed by thread T0 here:}}
+
+ // CHECK-Linux: {{ #0 0x.* in .*free}}
+ // CHECK-Linux: {{ #1 0x.* in main .*use-after-free.cc:9}}
+
+ // CHECK-Darwin: {{ #0 0x.* in wrap_free}}
+ // CHECK-Darwin: {{ #1 0x.* in main .*use-after-free.cc:9}}
+
+ // CHECK: {{previously allocated by thread T0 here:}}
+
+ // CHECK-Linux: {{ #0 0x.* in .*malloc}}
+ // CHECK-Linux: {{ #1 0x.* in main .*use-after-free.cc:8}}
+
+ // CHECK-Darwin: {{ #0 0x.* in wrap_malloc.*}}
+ // CHECK-Darwin: {{ #1 0x.* in main .*use-after-free.cc:8}}
+}
diff --git a/lib/asan/lit_tests/TestCases/use-after-poison.cc b/lib/asan/lit_tests/TestCases/use-after-poison.cc
new file mode 100644
index 000000000000..e3bc6ecee7f2
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/use-after-poison.cc
@@ -0,0 +1,20 @@
+// Check that __asan_poison_memory_region works.
+// RUN: %clangxx_asan -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+//
+// Check that we can disable it
+// RUN: ASAN_OPTIONS=allow_user_poisoning=0 %t
+
+#include <stdlib.h>
+
+extern "C" void __asan_poison_memory_region(void *, size_t);
+
+int main(int argc, char **argv) {
+ char *x = new char[16];
+ x[10] = 0;
+ __asan_poison_memory_region(x, 16);
+ int res = x[argc * 10]; // BOOOM
+ // CHECK: ERROR: AddressSanitizer: use-after-poison
+ // CHECK: main{{.*}}use-after-poison.cc:[[@LINE-2]]
+ delete [] x;
+ return res;
+}
diff --git a/lib/asan/lit_tests/TestCases/use-after-scope-dtor-order.cc b/lib/asan/lit_tests/TestCases/use-after-scope-dtor-order.cc
new file mode 100644
index 000000000000..32fa6ad8a464
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/use-after-scope-dtor-order.cc
@@ -0,0 +1,25 @@
+// RUN: %clangxx_asan -O0 -fsanitize=use-after-scope %s -o %t && \
+// RUN: not %t 2>&1 | FileCheck %s
+#include <stdio.h>
+
+struct IntHolder {
+ explicit IntHolder(int *val = 0) : val_(val) { }
+ ~IntHolder() {
+ printf("Value: %d\n", *val_); // BOOM
+ // CHECK: ERROR: AddressSanitizer: stack-use-after-scope
+ // CHECK: #0 0x{{.*}} in IntHolder::~IntHolder{{.*}}use-after-scope-dtor-order.cc:[[@LINE-2]]
+ }
+ void set(int *val) { val_ = val; }
+ int *get() { return val_; }
+
+ int *val_;
+};
+
+int main(int argc, char *argv[]) {
+ // It is incorrect to use "x" int IntHolder destructor, because "x" is
+ // "destroyed" earlier as it's declared later.
+ IntHolder holder;
+ int x = argc;
+ holder.set(&x);
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/use-after-scope-inlined.cc b/lib/asan/lit_tests/TestCases/use-after-scope-inlined.cc
new file mode 100644
index 000000000000..0bad048e3b8f
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/use-after-scope-inlined.cc
@@ -0,0 +1,27 @@
+// Test with "-O2" only to make sure inlining (leading to use-after-scope)
+// happens. "always_inline" is not enough, as Clang doesn't emit
+// llvm.lifetime intrinsics at -O0.
+//
+// RUN: %clangxx_asan -O2 -fsanitize=use-after-scope %s -o %t && not %t 2>&1 | FileCheck %s
+
+int *arr;
+
+__attribute__((always_inline))
+void inlined(int arg) {
+ int x[5];
+ for (int i = 0; i < arg; i++) x[i] = i;
+ arr = x;
+}
+
+int main(int argc, char *argv[]) {
+ inlined(argc);
+ return arr[argc - 1]; // BOOM
+ // CHECK: ERROR: AddressSanitizer: stack-use-after-scope
+ // CHECK: READ of size 4 at 0x{{.*}} thread T0
+ // CHECK: #0 0x{{.*}} in main
+ // CHECK: {{.*}}use-after-scope-inlined.cc:[[@LINE-4]]
+ // CHECK: Address 0x{{.*}} is located in stack of thread T0 at offset
+ // CHECK: [[OFFSET:[^ ]*]] in frame
+ // CHECK: main
+ // CHECK: {{\[}}[[OFFSET]], {{.*}}) 'x.i'
+}
diff --git a/lib/asan/lit_tests/TestCases/use-after-scope-nobug.cc b/lib/asan/lit_tests/TestCases/use-after-scope-nobug.cc
new file mode 100644
index 000000000000..c23acf76eaee
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/use-after-scope-nobug.cc
@@ -0,0 +1,14 @@
+// RUN: %clangxx_asan -O0 -fsanitize=use-after-scope %s -o %t && %t
+
+#include <stdio.h>
+
+int main() {
+ int *p = 0;
+ // Variable goes in and out of scope.
+ for (int i = 0; i < 3; i++) {
+ int x = 0;
+ p = &x;
+ }
+ printf("PASSED\n");
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/use-after-scope-temp.cc b/lib/asan/lit_tests/TestCases/use-after-scope-temp.cc
new file mode 100644
index 000000000000..13d714f9def7
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/use-after-scope-temp.cc
@@ -0,0 +1,29 @@
+// RUN: %clangxx_asan -O0 -fsanitize=use-after-scope %s -o %t && \
+// RUN: %t 2>&1 | FileCheck %s
+//
+// Lifetime for temporaries is not emitted yet.
+// XFAIL: *
+
+#include <stdio.h>
+
+struct IntHolder {
+ explicit IntHolder(int val) : val(val) {
+ printf("IntHolder: %d\n", val);
+ }
+ int val;
+};
+
+const IntHolder *saved;
+
+void save(const IntHolder &holder) {
+ saved = &holder;
+}
+
+int main(int argc, char *argv[]) {
+ save(IntHolder(10));
+ int x = saved->val; // BOOM
+ // CHECK: ERROR: AddressSanitizer: stack-use-after-scope
+ // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope-temp.cc:[[@LINE-2]]
+ printf("saved value: %d\n", x);
+ return 0;
+}
diff --git a/lib/asan/lit_tests/TestCases/use-after-scope.cc b/lib/asan/lit_tests/TestCases/use-after-scope.cc
new file mode 100644
index 000000000000..c46c9594c314
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/use-after-scope.cc
@@ -0,0 +1,16 @@
+// RUN: %clangxx_asan -O0 -fsanitize=use-after-scope %s -o %t && \
+// RUN: not %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS="detect_stack_use_after_return=1" not %t 2>&1 | FileCheck %s
+
+int main() {
+ int *p = 0;
+ {
+ int x = 0;
+ p = &x;
+ }
+ return *p; // BOOM
+ // CHECK: ERROR: AddressSanitizer: stack-use-after-scope
+ // CHECK: #0 0x{{.*}} in main {{.*}}use-after-scope.cc:[[@LINE-2]]
+ // CHECK: Address 0x{{.*}} is located in stack of thread T{{.*}} at offset [[OFFSET:[^ ]+]] in frame
+ // {{\[}}[[OFFSET]], {{[0-9]+}}) 'x'
+}
diff --git a/lib/asan/lit_tests/TestCases/wait.cc b/lib/asan/lit_tests/TestCases/wait.cc
new file mode 100644
index 000000000000..b5580dc88675
--- /dev/null
+++ b/lib/asan/lit_tests/TestCases/wait.cc
@@ -0,0 +1,63 @@
+// RUN: %clangxx_asan -DWAIT -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAITPID -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAITPID -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAITID -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAITID -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT3 -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT3 -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT4 -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT4 -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT3_RUSAGE -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT3_RUSAGE -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT4_RUSAGE -O0 %s -o %t && not %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT4_RUSAGE -O3 %s -o %t && not %t 2>&1 | FileCheck %s
+
+
+#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(WAIT)
+ res = wait(status);
+#elif defined(WAITPID)
+ res = waitpid(pid, status, WNOHANG);
+#elif defined(WAITID)
+ siginfo_t *si = (siginfo_t*)(x + argc * 3);
+ res = waitid(P_ALL, 0, si, WEXITED | WNOHANG);
+#elif defined(WAIT3)
+ res = wait3(status, WNOHANG, NULL);
+#elif defined(WAIT4)
+ res = wait4(pid, status, WNOHANG, NULL);
+#elif defined(WAIT3_RUSAGE) || defined(WAIT4_RUSAGE)
+ struct rusage *ru = (struct rusage*)(x + argc * 3);
+ int good_status;
+# if defined(WAIT3_RUSAGE)
+ res = wait3(&good_status, WNOHANG, ru);
+# elif defined(WAIT4_RUSAGE)
+ res = wait4(pid, &good_status, WNOHANG, ru);
+# endif
+#endif
+ // CHECK: stack-buffer-overflow
+ // CHECK: {{WRITE of size .* at 0x.* thread T0}}
+ // CHECK: {{in .*wait}}
+ // CHECK: {{in main .*wait.cc:}}
+ // CHECK: is located in stack of thread T0 at offset
+ // CHECK: {{in main}}
+ return res != -1;
+ }
+ // child
+ return 0;
+}