summaryrefslogtreecommitdiffstats
path: root/lib/asan/output_tests
diff options
context:
space:
mode:
authorandrew <andrew@FreeBSD.org>2012-07-30 10:58:13 +0000
committerandrew <andrew@FreeBSD.org>2012-07-30 10:58:13 +0000
commitcfeab007a554034f0b3ab4a677cf9dd2696c12f9 (patch)
tree40cc44a3d02ed86de24f2117a55680e4f0eb01a0 /lib/asan/output_tests
parent07af089f1449ec5506ca7ede5b593e11a0f48603 (diff)
downloadFreeBSD-src-cfeab007a554034f0b3ab4a677cf9dd2696c12f9.zip
FreeBSD-src-cfeab007a554034f0b3ab4a677cf9dd2696c12f9.tar.gz
Import compiler-rt r160957.
Diffstat (limited to 'lib/asan/output_tests')
-rw-r--r--lib/asan/output_tests/clone_test.cc34
-rw-r--r--lib/asan/output_tests/deep_tail_call.cc15
-rw-r--r--lib/asan/output_tests/default_options.cc12
-rw-r--r--lib/asan/output_tests/dlclose-test-so.cc33
-rw-r--r--lib/asan/output_tests/dlclose-test.cc74
-rw-r--r--lib/asan/output_tests/global-overflow.cc16
-rw-r--r--lib/asan/output_tests/heap-overflow.cc22
-rw-r--r--lib/asan/output_tests/interception_failure_test-linux.cc17
-rw-r--r--lib/asan/output_tests/interception_malloc_test-linux.cc19
-rw-r--r--lib/asan/output_tests/interception_test-linux.cc18
-rw-r--r--lib/asan/output_tests/large_func_test.cc48
-rw-r--r--lib/asan/output_tests/memcmp_test.cc10
-rw-r--r--lib/asan/output_tests/null_deref.cc17
-rw-r--r--lib/asan/output_tests/shared-lib-test-so.cc21
-rw-r--r--lib/asan/output_tests/shared-lib-test.cc42
-rw-r--r--lib/asan/output_tests/stack-overflow.cc11
-rw-r--r--lib/asan/output_tests/stack-use-after-return.cc.disabled27
-rw-r--r--lib/asan/output_tests/strncpy-overflow.cc24
-rwxr-xr-xlib/asan/output_tests/test_output.sh79
-rw-r--r--lib/asan/output_tests/use-after-free.c9
-rw-r--r--lib/asan/output_tests/use-after-free.cc31
21 files changed, 579 insertions, 0 deletions
diff --git a/lib/asan/output_tests/clone_test.cc b/lib/asan/output_tests/clone_test.cc
new file mode 100644
index 0000000..b18d255
--- /dev/null
+++ b/lib/asan/output_tests/clone_test.cc
@@ -0,0 +1,34 @@
+#ifdef __linux__
+#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);
+ waitpid(clone_pid, NULL, 0);
+ for (int i = 0; i < kStackSize; i++)
+ child_stack[i] = i;
+ int ret = child_stack[argc - 1];
+ printf("PASSED\n");
+ return ret;
+}
+#else // not __linux__
+#include <stdio.h>
+int main() {
+ printf("PASSED\n");
+ // Check-Common: PASSED
+}
+#endif
diff --git a/lib/asan/output_tests/deep_tail_call.cc b/lib/asan/output_tests/deep_tail_call.cc
new file mode 100644
index 0000000..cb69e89
--- /dev/null
+++ b/lib/asan/output_tests/deep_tail_call.cc
@@ -0,0 +1,15 @@
+// Check-Common: AddressSanitizer global-buffer-overflow
+int global[10];
+// Check-Common: {{#0.*call4}}
+void __attribute__((noinline)) call4(int i) { global[i+10]++; }
+// Check-Common: {{#1.*call3}}
+void __attribute__((noinline)) call3(int i) { call4(i); }
+// Check-Common: {{#2.*call2}}
+void __attribute__((noinline)) call2(int i) { call3(i); }
+// Check-Common: {{#3.*call1}}
+void __attribute__((noinline)) call1(int i) { call2(i); }
+// Check-Common: {{#4.*main}}
+int main(int argc, char **argv) {
+ call1(argc);
+ return global[0];
+}
diff --git a/lib/asan/output_tests/default_options.cc b/lib/asan/output_tests/default_options.cc
new file mode 100644
index 0000000..d6c7029
--- /dev/null
+++ b/lib/asan/output_tests/default_options.cc
@@ -0,0 +1,12 @@
+const char *kAsanDefaultOptions="verbosity=1 foo=bar";
+
+extern "C"
+__attribute__((no_address_safety_analysis))
+const char *__asan_default_options() {
+ return kAsanDefaultOptions;
+}
+
+int main() {
+ // Check-Common: foo=bar
+ return 0;
+}
diff --git a/lib/asan/output_tests/dlclose-test-so.cc b/lib/asan/output_tests/dlclose-test-so.cc
new file mode 100644
index 0000000..73e0050
--- /dev/null
+++ b/lib/asan/output_tests/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/output_tests/dlclose-test.cc b/lib/asan/output_tests/dlclose-test.cc
new file mode 100644
index 0000000..16126eb
--- /dev/null
+++ b/lib/asan/output_tests/dlclose-test.cc
@@ -0,0 +1,74 @@
+//===----------- dlclose-test.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
+// 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
+//===----------------------------------------------------------------------===//
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <string>
+
+using std::string;
+
+static const int kPageSize = 4096;
+
+typedef int *(fun_t)();
+
+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 *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) & ~(kPageSize - 1);
+ void *res = mmap((void*)(page_beg), kPageSize,
+ 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-Common: PASS
+ return 0;
+}
diff --git a/lib/asan/output_tests/global-overflow.cc b/lib/asan/output_tests/global-overflow.cc
new file mode 100644
index 0000000..a63eb73
--- /dev/null
+++ b/lib/asan/output_tests/global-overflow.cc
@@ -0,0 +1,16 @@
+#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-Common: {{READ of size 1 at 0x.* thread T0}}
+ // Check-Common: {{ #0 0x.* in main .*global-overflow.cc:9}}
+ // Check-Common: {{0x.* is located 0 bytes to the right of global variable}}
+ // Check-Common: {{.*YYY.* of size 10}}
+ res += XXX[argc] + ZZZ[argc];
+ return res;
+}
diff --git a/lib/asan/output_tests/heap-overflow.cc b/lib/asan/output_tests/heap-overflow.cc
new file mode 100644
index 0000000..534fbe0
--- /dev/null
+++ b/lib/asan/output_tests/heap-overflow.cc
@@ -0,0 +1,22 @@
+#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
+ free(x);
+ return res;
+}
+
+// Check-Common: {{READ of size 1 at 0x.* thread T0}}
+// Check-Common: {{ #0 0x.* in main .*heap-overflow.cc:6}}
+// Check-Common: {{0x.* is located 0 bytes to the right of 10-byte region}}
+// Check-Common: {{allocated by thread T0 here:}}
+
+// Check-Linux: {{ #0 0x.* in .*malloc}}
+// Check-Linux: {{ #1 0x.* in main .*heap-overflow.cc:4}}
+
+// Check-Darwin: {{ #0 0x.* in .*mz_malloc.*}}
+// Check-Darwin: {{ #1 0x.* in malloc_zone_malloc.*}}
+// Check-Darwin: {{ #2 0x.* in malloc.*}}
+// Check-Darwin: {{ #3 0x.* in main heap-overflow.cc:4}}
diff --git a/lib/asan/output_tests/interception_failure_test-linux.cc b/lib/asan/output_tests/interception_failure_test-linux.cc
new file mode 100644
index 0000000..9e8b753
--- /dev/null
+++ b/lib/asan/output_tests/interception_failure_test-linux.cc
@@ -0,0 +1,17 @@
+#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-Common: my_strtol_interceptor
+// CHECK-NOT: heap-use-after-free
+
diff --git a/lib/asan/output_tests/interception_malloc_test-linux.cc b/lib/asan/output_tests/interception_malloc_test-linux.cc
new file mode 100644
index 0000000..4bb3bd6
--- /dev/null
+++ b/lib/asan/output_tests/interception_malloc_test-linux.cc
@@ -0,0 +1,19 @@
+#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-Common: malloc call
+// Check-Common: heap-use-after-free
+
diff --git a/lib/asan/output_tests/interception_test-linux.cc b/lib/asan/output_tests/interception_test-linux.cc
new file mode 100644
index 0000000..0523510
--- /dev/null
+++ b/lib/asan/output_tests/interception_test-linux.cc
@@ -0,0 +1,18 @@
+#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-Common: my_strtol_interceptor
+// Check-Common: heap-use-after-free
+
diff --git a/lib/asan/output_tests/large_func_test.cc b/lib/asan/output_tests/large_func_test.cc
new file mode 100644
index 0000000..49751b3
--- /dev/null
+++ b/lib/asan/output_tests/large_func_test.cc
@@ -0,0 +1,48 @@
+#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]++;
+
+ x[zero + 111]++; // we should report this exact line
+
+ 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);
+ delete x;
+}
+
+// Check-Common: {{.*ERROR: AddressSanitizer heap-buffer-overflow on address}}
+// Check-Common: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}}
+// Check-Common: {{READ of size 4 at 0x.* thread T0}}
+
+// atos incorrectly extracts the symbol name for the static functions on
+// Darwin.
+// Check-Linux: {{ #0 0x.* in LargeFunction.*large_func_test.cc:15}}
+// Check-Darwin: {{ #0 0x.* in .*LargeFunction.*large_func_test.cc:15}}
+
+// Check-Common: {{ #1 0x.* in main .*large_func_test.cc:31}}
+// Check-Common: {{0x.* is located 44 bytes to the right of 400-byte region}}
+// Check-Common: {{allocated by thread T0 here:}}
+// Check-Common: {{ #0 0x.* in operator new.*}}
+// Check-Common: {{ #1 0x.* in main .*large_func_test.cc:30}}
diff --git a/lib/asan/output_tests/memcmp_test.cc b/lib/asan/output_tests/memcmp_test.cc
new file mode 100644
index 0000000..d0e5a43
--- /dev/null
+++ b/lib/asan/output_tests/memcmp_test.cc
@@ -0,0 +1,10 @@
+#include <string.h>
+int main(int argc, char **argv) {
+ char a1[] = {argc, 2, 3, 4};
+ char a2[] = {1, 2*argc, 3, 4};
+// Check-Common: AddressSanitizer stack-buffer-overflow
+// Check-Common: {{#0.*memcmp}}
+// Check-Common: {{#1.*main}}
+ int res = memcmp(a1, a2, 4 + argc); // BOOM
+ return res;
+}
diff --git a/lib/asan/output_tests/null_deref.cc b/lib/asan/output_tests/null_deref.cc
new file mode 100644
index 0000000..c152a42
--- /dev/null
+++ b/lib/asan/output_tests/null_deref.cc
@@ -0,0 +1,17 @@
+__attribute__((noinline))
+static void NullDeref(int *ptr) {
+ ptr[10]++;
+}
+int main() {
+ NullDeref((int*)0);
+}
+
+// Check-Common: {{.*ERROR: AddressSanitizer crashed on unknown address}}
+// Check-Common: {{0x0*00028 .*pc 0x.*}}
+// Check-Common: {{AddressSanitizer can not provide additional info. ABORTING}}
+
+// atos on Mac cannot extract the symbol name correctly.
+// Check-Linux: {{ #0 0x.* in NullDeref.*null_deref.cc:3}}
+// Check-Darwin: {{ #0 0x.* in .*NullDeref.*null_deref.cc:3}}
+
+// Check-Common: {{ #1 0x.* in main.*null_deref.cc:6}}
diff --git a/lib/asan/output_tests/shared-lib-test-so.cc b/lib/asan/output_tests/shared-lib-test-so.cc
new file mode 100644
index 0000000..686a245
--- /dev/null
+++ b/lib/asan/output_tests/shared-lib-test-so.cc
@@ -0,0 +1,21 @@
+//===----------- 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]++;
+}
diff --git a/lib/asan/output_tests/shared-lib-test.cc b/lib/asan/output_tests/shared-lib-test.cc
new file mode 100644
index 0000000..060fcde
--- /dev/null
+++ b/lib/asan/output_tests/shared-lib-test.cc
@@ -0,0 +1,42 @@
+//===----------- shared-lib-test.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 <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
+ return 0;
+}
+
+// Check-Common: {{.*ERROR: AddressSanitizer global-buffer-overflow}}
+// Check-Common: {{READ of size 4 at 0x.* thread T0}}
+// Check-Common: {{ #0 0x.*}}
+// Check-Common: {{ #1 0x.* in main .*shared-lib-test.cc:35}}
diff --git a/lib/asan/output_tests/stack-overflow.cc b/lib/asan/output_tests/stack-overflow.cc
new file mode 100644
index 0000000..35fa8a6
--- /dev/null
+++ b/lib/asan/output_tests/stack-overflow.cc
@@ -0,0 +1,11 @@
+#include <string.h>
+int main(int argc, char **argv) {
+ char x[10];
+ memset(x, 0, 10);
+ int res = x[argc * 10]; // BOOOM
+ return res;
+}
+
+// Check-Common: {{READ of size 1 at 0x.* thread T0}}
+// Check-Common: {{ #0 0x.* in main .*stack-overflow.cc:5}}
+// Check-Common: {{Address 0x.* is .* frame <main>}}
diff --git a/lib/asan/output_tests/stack-use-after-return.cc.disabled b/lib/asan/output_tests/stack-use-after-return.cc.disabled
new file mode 100644
index 0000000..f497157
--- /dev/null
+++ b/lib/asan/output_tests/stack-use-after-return.cc.disabled
@@ -0,0 +1,27 @@
+#include <stdio.h>
+
+__attribute__((noinline))
+char *Ident(char *x) {
+ fprintf(stderr, "1: %p\n", x);
+ return x;
+}
+
+__attribute__((noinline))
+char *Func1() {
+ char local;
+ return Ident(&local);
+}
+
+__attribute__((noinline))
+void Func2(char *x) {
+ fprintf(stderr, "2: %p\n", x);
+ *x = 1;
+ // Check-Common: {{WRITE of size 1 .* thread T0}}
+ // Check-Common: {{ #0.*Func2.*stack-use-after-return.cc:18}}
+ // Check-Common: {{is located in frame <.*Func1.*> of T0's stack}}
+}
+
+int main(int argc, char **argv) {
+ Func2(Func1());
+ return 0;
+}
diff --git a/lib/asan/output_tests/strncpy-overflow.cc b/lib/asan/output_tests/strncpy-overflow.cc
new file mode 100644
index 0000000..66d5810
--- /dev/null
+++ b/lib/asan/output_tests/strncpy-overflow.cc
@@ -0,0 +1,24 @@
+#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
+ return short_buffer[8];
+}
+
+// Check-Common: {{WRITE of size 1 at 0x.* thread T0}}
+// Check-Linux: {{ #0 0x.* in .*strncpy}}
+// Check-Darwin: {{ #0 0x.* in wrap_strncpy}}
+// Check-Common: {{ #1 0x.* in main .*strncpy-overflow.cc:7}}
+// Check-Common: {{0x.* is located 0 bytes to the right of 9-byte region}}
+// Check-Common: {{allocated by thread T0 here:}}
+
+// Check-Linux: {{ #0 0x.* in .*malloc}}
+// Check-Linux: {{ #1 0x.* in main .*strncpy-overflow.cc:6}}
+
+// Check-Darwin: {{ #0 0x.* in .*mz_malloc.*}}
+// Check-Darwin: {{ #1 0x.* in malloc_zone_malloc.*}}
+// Check-Darwin: {{ #2 0x.* in malloc.*}}
+// Check-Darwin: {{ #3 0x.* in main .*strncpy-overflow.cc:6}}
diff --git a/lib/asan/output_tests/test_output.sh b/lib/asan/output_tests/test_output.sh
new file mode 100755
index 0000000..6510043
--- /dev/null
+++ b/lib/asan/output_tests/test_output.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+
+set -e # fail on any error
+
+OS=`uname`
+CXX=$1
+CC=$2
+FILE_CHECK=$3
+CXXFLAGS="-mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-optimize-sibling-calls -g"
+SYMBOLIZER=../scripts/asan_symbolize.py
+TMP_ASAN_REPORT=asan_report.tmp
+
+run_program() {
+ ./$1 2>&1 | $SYMBOLIZER 2> /dev/null | c++filt > $TMP_ASAN_REPORT
+}
+
+# check_program exe_file source_file check_prefixf
+check_program() {
+ run_program $1
+ $FILE_CHECK $2 --check-prefix=$3 < $TMP_ASAN_REPORT
+ rm -f $TMP_ASAN_REPORT
+}
+
+C_TEST=use-after-free
+echo "Sanity checking a test in pure C"
+$CC -g -faddress-sanitizer -O2 $C_TEST.c
+check_program a.out $C_TEST.c CHECK
+rm ./a.out
+
+echo "Sanity checking a test in pure C with -pie"
+$CC -g -faddress-sanitizer -O2 $C_TEST.c -pie
+check_program a.out $C_TEST.c CHECK
+rm ./a.out
+
+echo "Testing sleep_before_dying"
+$CC -g -faddress-sanitizer -O2 $C_TEST.c
+export ASAN_OPTIONS="sleep_before_dying=1"
+check_program a.out $C_TEST.c CHECKSLEEP
+export ASAN_OPTIONS=""
+rm ./a.out
+
+# FIXME: some tests do not need to be ran for all the combinations of arch
+# and optimization mode.
+for t in *.cc; do
+ for b in 32 64; do
+ for O in 0 1 2 3; do
+ c=`basename $t .cc`
+ if [[ "$c" == *"-so" ]]; then
+ continue
+ fi
+ if [[ "$c" == *"-linux" ]]; then
+ if [[ "$OS" != "Linux" ]]; then
+ continue
+ fi
+ fi
+ c_so=$c-so
+ exe=$c.$b.O$O
+ so=$c.$b.O$O-so.so
+ echo testing $exe
+ build_command="$CXX $CXXFLAGS -m$b -faddress-sanitizer -O$O $c.cc -o $exe"
+ [ "$DEBUG" == "1" ] && echo $build_command
+ $build_command
+ [ -e "$c_so.cc" ] && $CXX $CXXFLAGS -m$b -faddress-sanitizer -O$O $c_so.cc -fPIC -shared -o $so
+ run_program $exe
+ # Check common expected lines for OS.
+ $FILE_CHECK $c.cc --check-prefix="Check-Common" < $TMP_ASAN_REPORT
+ # Check OS-specific lines.
+ if [ `grep -c "Check-$OS" $c.cc` -gt 0 ]
+ then
+ $FILE_CHECK $c.cc --check-prefix="Check-$OS" < $TMP_ASAN_REPORT
+ fi
+ rm ./$exe
+ rm ./$TMP_ASAN_REPORT
+ [ -e "$so" ] && rm ./$so
+ done
+ done
+done
+
+exit 0
diff --git a/lib/asan/output_tests/use-after-free.c b/lib/asan/output_tests/use-after-free.c
new file mode 100644
index 0000000..801d3f6
--- /dev/null
+++ b/lib/asan/output_tests/use-after-free.c
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+}
+
+// CHECK: heap-use-after-free
+// CHECKSLEEP: Sleeping for 1 second
diff --git a/lib/asan/output_tests/use-after-free.cc b/lib/asan/output_tests/use-after-free.cc
new file mode 100644
index 0000000..c3e9dbe
--- /dev/null
+++ b/lib/asan/output_tests/use-after-free.cc
@@ -0,0 +1,31 @@
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+}
+
+// Check-Common: {{.*ERROR: AddressSanitizer heap-use-after-free on address}}
+// Check-Common: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}}
+// Check-Common: {{READ of size 1 at 0x.* thread T0}}
+// Check-Common: {{ #0 0x.* in main .*use-after-free.cc:5}}
+// Check-Common: {{0x.* is located 5 bytes inside of 10-byte region .0x.*,0x.*}}
+// Check-Common: {{freed by thread T0 here:}}
+
+// Check-Linux: {{ #0 0x.* in .*free}}
+// Check-Linux: {{ #1 0x.* in main .*use-after-free.cc:4}}
+
+// Check-Darwin: {{ #0 0x.* in .*mz_free.*}}
+// We override free() on Darwin, thus no malloc_zone_free
+// Check-Darwin: {{ #1 0x.* in wrap_free}}
+// Check-Darwin: {{ #2 0x.* in main .*use-after-free.cc:4}}
+
+// Check-Common: {{previously allocated by thread T0 here:}}
+
+// Check-Linux: {{ #0 0x.* in .*malloc}}
+// Check-Linux: {{ #1 0x.* in main .*use-after-free.cc:3}}
+
+// Check-Darwin: {{ #0 0x.* in .*mz_malloc.*}}
+// Check-Darwin: {{ #1 0x.* in malloc_zone_malloc.*}}
+// Check-Darwin: {{ #2 0x.* in malloc.*}}
+// Check-Darwin: {{ #3 0x.* in main .*use-after-free.cc:3}}
OpenPOWER on IntegriCloud