===================================================================
@@ -16,8 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# GCC testsuite that uses the `dg.exp' driver.
-
# Load support procs.
load_lib gcc-dg.exp
load_lib asan-dg.exp
@@ -30,8 +28,89 @@ if ![check_effective_target_faddress_san
dg-init
asan_init
+set default_asan_torture_options [list { -O0 -m32 } { -O1 -m32 } { -O2 -m32 } { -O3 -m32 } \
+ { -O0 -m64 } { -O1 -m64 } { -O2 -m64 } { -O3 -m64 }]
+
+if { [info procs target_compile] != [list] \
+ && [info procs saved_asan_target_compile] == [list] } {
+ rename target_compile saved_asan_target_compile
+
+ proc target_compile { source dest type options } {
+ global srcdir subdir
+
+ if { [string match "*blacklist-1.c" $source] } {
+ set blacklist_options $options
+ set blist_tmp [glob $srcdir/c-c++-common/asan/Helpers/blacklist-1.tmp]
+ lappend blacklist_options "additional_flags=-asan-blacklist=$blist_tmp"
+ set result [eval [list saved_asan_target_compile $source $dest $type $blacklist_options]]
+ return $result
+ } elseif { [string match "*interface-symbols-1.c" $source] } {
+ set result [eval [list saved_asan_target_compile \
+ $source "interface-symbols-1.exe" \
+ "executable" $options]]
+ if { [string match "" $result] } {
+ set exefile [glob interface-symbols-1.exe]
+ set asan_interface_h [glob $srcdir/../../libsanitizer/include/sanitizer/asan_interface.h]
+ set script [glob $srcdir/c-c++-common/asan/Helpers/interface_symbols.sh]
+ set diff_result [exec sh $script $exefile $asan_interface_h]
+ if { ![string match "" $diff_result] } {
+ fail "$source -- diff result not empty: $diff_result"
+ }
+ }
+ } elseif { [string match "*initialization-bug-any-order-1.c" $source] } {
+ set auxfile [glob $srcdir/c-c++-common/asan/Helpers/initialization-bug-extra-1.c]
+ global subtest
+ if { [string match "subtest1" $subtest] } {
+ set source "$source $auxfile"
+ } else {
+ set source "$auxfile $source"
+ }
+ set result [eval [list saved_asan_target_compile $source $dest $type $options]]
+ } else {
+ set result [eval [list saved_asan_target_compile $source $dest $type $options]]
+ }
+ return $result
+ }
+}
+
# Main loop.
-gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/asan/*.c]] ""
+foreach srcfile [lsort [glob -nocomplain \
+ $srcdir/$subdir/*.c \
+ $srcdir/c-c++-common/asan/*.c \
+ $srcdir/c-c++-common/asan/linux/*.c]] {
+ set asan_torture_options $default_asan_torture_options
+ if { [string match "*force-inline-opt0-1.c" $srcfile] } {
+ set asan_torture_options [list { -O0 -m64 } { -O1 -m64 }]
+ } elseif { [string match "*initialization-bug-1.c" $srcfile] } {
+ set asan_torture_options [list { -O0 -m32 } { -O0 -m64 }]
+ } elseif { [string match "*interface-symbols-1.c" $srcfile] } {
+ set asan_torture_options [list { -O2 }]
+ } elseif { [string match "*sleep-before-dying-1.c" $srcfile] } {
+ setenv ASAN_OPTIONS "sleep_before_dying=1"
+ set asan_torture_options [list { -O2 }]
+ } elseif { [string match "*strip-path-prefix-1.c" $srcfile] } {
+ setenv ASAN_OPTIONS "strip_path_prefix='/'"
+ set asan_torture_options [list { -O2 }]
+ } elseif { [string match "*initialization-bug-any-order-1.c" $srcfile] } {
+ set asan_torture_options [list { -O0 }]
+ set-torture-options $asan_torture_options
+ global subtest
+ set subtest "subtest1"
+ gcc-dg-runtest $srcfile ""
+ set subtest "subtest2"
+ } elseif { [string match "*rlimit-mmap-test-1.c" $srcfile] } {
+ set asan_torture_options [list { }]
+ set-torture-options $asan_torture_options
+ }
+
+ set-torture-options $asan_torture_options
+ gcc-dg-runtest $srcfile ""
+
+ if { [string match "*sleep-before-dying-1.c" $srcfile]
+ || [string match "*strip-path-prefix-1.c" $srcfile] } {
+ unsetenv ASAN_OPTIONS
+ }
+}
# All done.
asan_finish
===================================================================
@@ -0,0 +1,2 @@
+global-init:*badGlobal*
+global-init-type:*badNamespace::BadClass*
===================================================================
@@ -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; }
===================================================================
@@ -0,0 +1,55 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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);
+}
+
+/* { dg-output "ERROR: AddressSanitizer: heap-use-after-free.*(\n|\r\n|\r)" } */
+/* { dg-output "WRITE of size 4 at 0x\[0-9a-f\]+ thread T(\[0-9\]+).*(\n|\r\n|\r)" } */
+/* { dg-output "freed by thread T(\[0-9\]+) here:.*(\n|\r\n|\r)" } */
+/* { dg-output "previously allocated by thread T(\[0-9\]+) here:.*(\n|\r\n|\r)" } */
+/* { dg-output "Thread T\\2 created by T(\[0-9\]+) here:.*(\n|\r\n|\r)" } */
+/* { dg-output "Thread T\\8 created by T0 here:.*(\n|\r\n|\r)" } */
+/* { dg-output "Thread T\\4 created by T(\[0-9\]+) here:.*(\n|\r\n|\r)" } */
+/* { dg-output "Thread T\\11 created by T0 here:.*(\n|\r\n|\r)" } */
+/* { dg-output "Thread T\\6 created by T(\[0-9\]+) here:.*(\n|\r\n|\r)" } */
+/* { dg-output "Thread T\\14 created by T0 here:" } */
===================================================================
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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;
+}
+
+/* { dg-output "ERROR: AddressSanitizer global-buffer-overflow\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main \[^\n\r]*(shared-lib-test-1.C:26|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,32 @@
+// Check that we can store lots of stack frames if asked to.
+
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+#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 = new char[10];
+ // deep_free(x);
+ DeepFree<200>::free(x);
+ return x[5];
+}
+
+/* { dg-output "ERROR: AddressSanitizer heap-use-after-free on address.*(\n|\r\n|\r)" } */
+/* { dg-output " #37 0x\[0-9a-f\]+ (in \[^\n\r]*DeepFree\[^\n\r]*36|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output " #99 0x\[0-9a-f\]+ (in \[^\n\r]*DeepFree\[^\n\r]*98|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output " #116 0x\[0-9a-f\]+ (in \[^\n\r]*DeepFree\[^\n\r]*115|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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];
+}
+
+/* { dg-output "__asan_on_error called.*(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-asan-initialization-order" } */
+/* { dg-additional-sources "Helpers/initialization-blacklist-extra-1.C" } */
+
+// 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 main(int argc, char **argv) {
+ return argc + x + y - 1;
+}
===================================================================
@@ -28,8 +28,124 @@ if ![check_effective_target_faddress_san
dg-init
asan_init
+# Compiling dlclose-test-1.C needs to build dlclose-test-so-1.so beforehand.
+if { [info procs target_compile] != [list] \
+ && [info procs saved_asan_target_compile] == [list] } {
+ rename target_compile saved_asan_target_compile
+
+ proc target_compile { source dest type options } {
+ global srcdir subdir
+
+ if { [string match "*blacklist-1.c" $source] } {
+ set blacklist_options $options
+ set blist_tmp [glob $srcdir/c-c++-common/asan/Helpers/blacklist-1.tmp]
+ lappend blacklist_options "additional_flags=-asan-blacklist=$blist_tmp"
+ set result [eval [list saved_asan_target_compile \
+ $source $dest $type $blacklist_options]]
+ } elseif { [string match "*initialization-blacklist-1.C" $source] } {
+ set blacklist_options $options
+ set blist_tmp [glob $srcdir/$subdir/Helpers/initialization-blacklist-1.tmp]
+ lappend blacklist_options "additional_flags=-asan-blacklist=$blist_tmp"
+ set result [eval [list saved_asan_target_compile \
+ $source $dest $type $blacklist_options]]
+ } elseif { [string match "*dlclose-test-1.C" $source] } {
+ set dlclose_so_options $options
+ lappend dlclose_so_options "additional_flags=-fPIC -shared"
+ set auxfile [glob $srcdir/$subdir/SharedLibs/dlclose-test-1-so.C]
+ set result [eval [list saved_asan_target_compile \
+ $auxfile \
+ "dlclose-test-1.exe-so.so" \
+ "executable" $dlclose_so_options]]
+ set result [eval [list saved_asan_target_compile \
+ $source $dest $type $options]]
+ file delete "dlclose-test-1.exe-so.so"
+ } elseif { [string match "*shared-lib-test-1.C" $source] } {
+ set shared_lib_so_options $options
+ lappend shared_lib_so_options "additional_flags=-fPIC -shared"
+ set auxfile [glob $srcdir/$subdir/SharedLibs/shared-lib-test-1-so.C]
+ set result [eval [list saved_asan_target_compile \
+ $auxfile \
+ "shared-lib-test-1.exe-so.so" \
+ "executable" $shared_lib_so_options]]
+ set result [eval [list saved_asan_target_compile \
+ $source $dest $type $options]]
+ file delete "shared-lib-test-1.exe-so.so"
+ } elseif { [string match "*interface-symbols-1.c" $source] } {
+ set result [eval [list saved_asan_target_compile \
+ $source "interface-symbols-1.exe" \
+ "executable" $options]]
+ if { [string match "" $result] } {
+ set exefile [glob interface-symbols-1.exe]
+ set asan_interface_h [glob $srcdir/../../libsanitizer/include/sanitizer/asan_interface.h]
+ set script [glob $srcdir/c-c++-common/asan/Helpers/interface_symbols.sh]
+ set diff_result [exec sh $script $exefile $asan_interface_h]
+ if { ![string match "" $diff_result] } {
+ fail "$source -- diff result not empty: $diff_result"
+ }
+ }
+ } elseif { [string match "*initialization-bug-any-order-1.c" $source] } {
+ set auxfile [glob $srcdir/c-c++-common/asan/Helpers/initialization-bug-extra-1.c]
+ global subtest
+ if { [string match "subtest1" $subtest] } {
+ set source "$source $auxfile"
+ } else {
+ set source "$auxfile $source"
+ }
+ set result [eval [list saved_asan_target_compile $source $dest $type $options]]
+ } else {
+ set result [eval [list saved_asan_target_compile $source $dest $type $options]]
+ }
+ return $result
+ }
+}
+
+set default_asan_torture_options [list { -O0 -m32 } { -O1 -m32 } { -O2 -m32 } { -O3 -m32 } \
+ { -O0 -m64 } { -O1 -m64 } { -O2 -m64 } { -O3 -m64 }]
+
# Main loop.
-gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C $srcdir/c-c++-common/asan/*.c]] ""
+foreach srcfile [lsort [glob -nocomplain \
+ $srcdir/$subdir/*.C \
+ $srcdir/$subdir/linux/*.C \
+ $srcdir/c-c++-common/asan/*.c \
+ $srcdir/c-c++-common/asan/linux/*.c]] {
+
+ set asan_torture_options $default_asan_torture_options
+ if { [string match "*deep-stack-uaf-1.C" $srcfile] } {
+ setenv ASAN_OPTIONS "malloc_context_size=120:redzone=512"
+ } elseif { [string match "*force-inline-opt0-1.c" $srcfile] } {
+ set asan_torture_options [list { -O0 -m64 } { -O1 -m64 }]
+ } elseif { [string match "*initialization-bug-1.c" $srcfile] } {
+ set asan_torture_options [list { -O0 -m32 } { -O0 -m64 }]
+ } elseif { [string match "*interface-symbols-1.c" $srcfile]
+ || [string match "*symbolize-callback-1.C" $srcfile]
+ || [string match "*malloc-hook-1.C" $srcfile] } {
+ set asan_torture_options [list { -O2 }]
+ } elseif { [string match "*sleep-before-dying-1.c" $srcfile] } {
+ setenv ASAN_OPTIONS "sleep_before_dying=1"
+ set asan_torture_options [list { -O2 }]
+ } elseif { [string match "*strip-path-prefix-1.c" $srcfile] } {
+ setenv ASAN_OPTIONS "strip_path_prefix='/'"
+ set asan_torture_options [list { -O2 }]
+ } elseif { [string match "*initialization-bug-any-order-1.c" $srcfile] } {
+ set asan_torture_options [list { -O0 }]
+ set-torture-options $asan_torture_options
+ global subtest
+ set subtest "subtest1"
+ gcc-dg-runtest $srcfile ""
+ set subtest "subtest2"
+ } elseif { [string match "*rlimit-mmap-test-1.c" $srcfile] } {
+ set asan_torture_options [list { }]
+ }
+
+ set-torture-options $asan_torture_options
+ gcc-dg-runtest $srcfile ""
+
+ if { [string match "*deep-stack-uaf-1.C" $srcfile]
+ || [string match "*sleep-before-dying-1.c" $srcfile]
+ || [string match "*strip-path-prefix-1.c" $srcfile] } {
+ unsetenv ASAN_OPTIONS
+ }
+}
# All done.
asan_finish
===================================================================
@@ -0,0 +1,51 @@
+// A collection of various initializers which shouldn't trip up initialization
+// order checking. If successful, this will just return 0.
+
+/* { dg-do run } */
+/* { dg-options "--std=c++11 -asan-initialization-order" } */
+
+// 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;
+}
+
+// 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).
+
+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; }
===================================================================
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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;
+}
+
+/* { dg-output "ERROR: AddressSanitizer heap-buffer-overflow on address\[^\n\r]*" } */
+/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" } */
+/* { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in (operator new|_Znwm)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #2 0x\[0-9a-f\]+ (in _*main\[^\n\r]*(large-func-test-1.C:33|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
===================================================================
@@ -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__);
+}
===================================================================
@@ -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]++;
+}
===================================================================
@@ -0,0 +1,67 @@
+// 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
+
+/* { dg-do run } */
+
+#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: PASS
+ return 0;
+}
+
+/* { dg-output "PASS" } */
===================================================================
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+#include <stdlib.h>
+#include <unistd.h>
+
+extern "C" {
+// Note: avoid calling functions that allocate memory in malloc/free
+// to avoid infinite recursion.
+void __asan_malloc_hook(void *ptr, size_t sz) {
+ write(1, "MallocHook\n", sizeof("MallocHook\n"));
+}
+void __asan_free_hook(void *ptr) {
+ write(1, "FreeHook\n", sizeof("FreeHook\n"));
+}
+} // extern "C"
+
+int main() {
+ volatile int *x = new int;
+ *x = 0;
+ delete x;
+ return 0;
+}
+
+/* { dg-output "MallocHook(\n|\r\n|\r)" } */
+/* { dg-output "FreeHook(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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];
+}
+
+/* { dg-output "MySymbolizer" } */
===================================================================
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+const char *kAsanDefaultOptions="verbosity=1 foo=bar";
+
+extern "C"
+__attribute__((no_address_safety_analysis))
+const char *__asan_default_options() {
+ return kAsanDefaultOptions;
+}
+
+int main() {
+ return 0;
+}
+
+/* { dg-output "Using the defaults from __asan_default_options:.* foo=bar.*(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-optimize-sibling-calls" } */
+/* { dg-shouldfail "asan" } */
+
+int global[10];
+void __attribute__((noinline)) call4(int i) { global[i+10]++; }
+void __attribute__((noinline)) call3(int i) { call4(i); }
+void __attribute__((noinline)) call2(int i) { call3(i); }
+void __attribute__((noinline)) call1(int i) { call2(i); }
+int main(int argc, char **argv) {
+ call1(argc);
+ return global[0];
+}
+
+/* { dg-output "AddressSanitizer global-buffer-overflow.*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in \[^\n\r]*call4\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in \[^\n\r]*call3\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #2 0x\[0-9a-f\]+ (in \[^\n\r]*call2\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #3 0x\[0-9a-f\]+ (in \[^\n\r]*call1\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #4 0x\[0-9a-f\]+ (in \[^\n\r]*main\[^\n\r]*|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,22 @@
+// ASan interceptor can be accessed with __interceptor_ prefix.
+
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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);
+}
+
+/* { dg-output "my_strtol_interceptor.*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*heap-use-after-free" } */
===================================================================
@@ -0,0 +1,21 @@
+// If user provides his own libc functions, ASan doesn't
+// intercept these functions.
+
+/* { dg-do run } */
+
+#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
+}
+
+/* { dg-output "my_strtol_interceptor" } */
===================================================================
@@ -0,0 +1,23 @@
+// ASan interceptor can be accessed with __interceptor_ prefix.
+
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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);
+}
+
+/* { dg-output "malloc call.*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*heap-use-after-free" } */
===================================================================
@@ -75,6 +75,7 @@ proc asan_init { args } {
set link_flags "[asan_link_flags [get_multilibs ${TOOL_OPTIONS}]]"
} else {
set link_flags "[asan_link_flags [get_multilibs]]"
+ set link_flags "[asan_link_flags [get_multilibs -m32]] $link_flags"
}
}
===================================================================
@@ -0,0 +1,24 @@
+// Check the presense of interface symbols in compiled file.
+
+// RUN: %clang -fsanitize=address -dead_strip -O2 %s -o %t.exe
+// RUN: nm %t.exe | egrep " [TW] " | sed "s/.* T //" | sed "s/.* W //" \
+// RUN: | grep "__asan_" | sed "s/___asan_/__asan_/" > %t.symbols
+// RUN: cat %p/../../../include/sanitizer/asan_interface.h \
+// RUN: | sed "s/\/\/.*//" | sed "s/typedef.*//" \
+// 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: cat %t.interface | sort -u | diff %t.symbols -
+
+/* { dg-options "-static-libasan -lpthread -ldl" } */
+
+int main() { return 0; }
===================================================================
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+}
+
+/* { dg-output "heap-use-after-free.*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ \[(\]\[^/\]\[^\n\r]*(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,15 @@
+// This test checks that we are no instrumenting a memory access twice
+// (before and after inlining)
+
+/* { dg-do run } */
+/* { dg-options "-Wno-attributes" } */
+__attribute__((always_inline))
+void foo(int *x) {
+ *x = 0;
+}
+
+int main() {
+ int x;
+ foo(&x);
+ return x;
+}
===================================================================
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+__attribute__((noinline))
+static void NullDeref(int *ptr) {
+ ptr[10]++;
+}
+int main() {
+ NullDeref((int*)0);
+}
+
+/* { dg-output "ERROR: AddressSanitizer crashed on unknown address.*" } */
+/* { dg-output "0x\[0-9a-f\]+ .*pc 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "AddressSanitizer can not provide additional info.*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in \[^\n\r]*NullDeref\[^\n\r]*(null_deref.cc:6|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in \[^\n\r]*main\[^\n\r]*(null_deref.cc:9|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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
+ res += XXX[argc] + ZZZ[argc];
+ return res;
+}
+
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main .*global-overflow.cc:18|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable.*(\n|\r\n|\r)" } */
+/* { dg-output ".*YYY.* of size 10.*(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,50 @@
+// Test to make sure basic initialization order errors are caught.
+
+// RUN: %clangxx_asan -m64 -O0 %s %p/Helpers/initialization-bug-extra2.cc\
+// RUN: -mllvm -asan-initialization-order -o %t && %t 2>&1 \
+// RUN: | %symbolize | FileCheck %s
+// RUN: %clangxx_asan -m32 -O0 %s %p/Helpers/initialization-bug-extra2.cc\
+// RUN: -mllvm -asan-initialization-order -o %t && %t 2>&1 \
+// RUN: | %symbolize | FileCheck %s
+
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+/* { dg-options "-asan-initialization-order" } */
+/* { dg-additional-sources "Helpers/initialization-bug-extra-1.c" } */
+
+// Do not test with optimization -- the error may be optimized away.
+
+#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;
+}
+
+// This initializer begins our initialization order problems.
+static int x = initX();
+
+int main() {
+ // ASan should have caused an exit before main runs.
+ return 0;
+}
+
+/* { dg-output "AddressSanitizer: initialization-order-fiasco.*(\n|\r\n|\r)" } */
+/* { dg-output "READ of size .* at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
+/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes inside of global variable .*(y|z).*(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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];
+}
+
+/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main \[^\n\r]*(strncpy-overflow-1.c:10|\[?]\[?]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main \[^\n\r]*(strncpy-overflow-1.c:9|\[?]\[?]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+
+
===================================================================
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <string.h>
+int main(int argc, char **argv) {
+ char x[10];
+ memset(x, 0, 10);
+ int res = x[argc * 10]; // BOOOM
+ return res;
+}
+
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main \[^\n\r]*(stack-overflow-1.c:8|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "Address 0x\[0-9a-f\]+ is\[^\n\r]*frame <main>" } */
===================================================================
@@ -0,0 +1,27 @@
+// Test the blacklist functionality of ASan
+
+/* { dg-do run } */
+/* { dg-additional-sources "Helpers/blacklist-extra-1.c" } */
+
+// badGlobal is accessed improperly, but we blacklisted it.
+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-1.c, 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;
+}
===================================================================
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+}
+
+/* { dg-output "ERROR: AddressSanitizer heap-use-after-free on address\[^\n\r]*" } */
+/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main \[^\n\r]*(use-after-free-1.c:8|\[?]\[?]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ in \[^\n\r]*free\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in \[^\n\r]*main \[^\n\r]*(use-after-free-1.c:7|\[?]\[?]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ in \[^\n\r]*malloc\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in \[^\n\r]*main \[^\n\r]*(use-after-free-1.c:6|\[?]\[?]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
===================================================================
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+}
+
+/* { dg-output "heap-use-after-free.*(\n|\r\n|\r)" } */
+/* { dg-output " #0 \[^\n\r]*free\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 \[^\n\r]*(in main\[^\n\r]*(sanity-check-pure-c-1.c:7|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output " #0 \[^\n\r]*(interceptor_|)malloc\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 \[^\n\r]*(in main\[^\n\r]*(sanity-check-pure-c-1.c:6|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+
===================================================================
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+#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;
+}
+
+int main(int argc, char **argv) {
+ Func2(Func1());
+ return 0;
+}
+
+/* { dg-output "WRITE of size 1 \[^\n\r]* thread T0" } */
+/* { dg-output " #0\[^\n\r]*Func2\[^\n\r]*(stack-use-after-return.cc:28|\[?\]\[?\]:)" } */
+/* { dg-output "is located in frame <\[^\n\r]*Func1\[^\n\r]*> of T0's stack" } */
+
===================================================================
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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;
+}
+
+/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main .*(heap-overflow-1.c:9|\[?\]\[?\]:0)|\[(\]).*(\n|\r\n|\r)" } */
+/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in .*malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main .*(heap-overflow-1.c:7|\[?\]\[?\]:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+
===================================================================
@@ -0,0 +1,38 @@
+// 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.
+
+// Do not test with optimization -- the error may be optimized away.
+
+/* { dg-do run } */
+/* { options "-asan-initialization-order" } */
+/* { dg-shouldfail "asan" } */
+
+#include <cstdio>
+
+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;
+}
+
+// This initializer begins our initialization order problems.
+static int x = initX();
+
+int main() {
+ // ASan should have caused an exit before main runs.
+ return 0;
+}
+
+/* { dg-output "AddressSanitizer initialization-order-fiasco\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "READ of size \[^\n\r]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ (in \[^\n\r]*initX\[^\n\r]*(initialization-bug-any-order-1.c:31|\[?\]\[?\]:)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes inside of global variable \[^\n\r]*y\[^\n\r]*" } */
===================================================================
@@ -0,0 +1,21 @@
+// Check that we properly report mmap failure.
+// RUN: %clangxx_asan %s -o %t && %t 2>&1 | FileCheck %s
+
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#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);
+ return 0;
+}
+
+/* { dg-output "AddressSanitizer is unable to mmap" } */
===================================================================
@@ -0,0 +1,61 @@
+// Check that ASan plays well with easy cases of makecontext/swapcontext.
+
+/* { dg-do run } */
+
+#include <stdio.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+ucontext_t orig_context;
+ucontext_t child_context;
+
+void Child(int mode) {
+ char x[32] = {0}; // Stack gets poisoned.
+ printf("Child: %p\n", x);
+ // (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) {
+ int i;
+ const int kStackSize = 1 << 20;
+ char child_stack[kStackSize + 1];
+ 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 (i = 0; i < kStackSize; i++) {
+ child_stack[i] = i;
+ }
+ return child_stack[arg];
+}
+
+int main(int argc, char **argv) {
+ int ret = 0;
+ ret += Run(argc - 1, 0);
+ printf("Test1 passed\n");
+ ret += Run(argc - 1, 1);
+ printf("Test2 passed\n");
+ return ret;
+}
+
+/* { dg-output "WARNING: ASan doesn't fully support makecontext/swapcontext.*" } */
+/* { dg-output "Test1 passed.*" } */
+/* { dg-output "Test2 passed.*" } */
===================================================================
@@ -0,0 +1,46 @@
+// Regression test for:
+// http://code.google.com/p/address-sanitizer/issues/detail?id=37
+
+/* { dg-do run } */
+/* { dg-options "-D_GNU_SOURCE" } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdio.h>
+#include <stdlib.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) {
+ int i;
+ 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 (i = 0; i < kStackSize; i++)
+ child_stack[i] = i;
+ int ret = child_stack[argc - 1];
+ printf("PASSED\n");
+ return ret;
+ }
+ return 0;
+}
+
+/* { dg-output "PASSED" } */
===================================================================
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-shouldfail "asan" } */
+
+#include <stdlib.h>
+int main() {
+ char *x = (char*)malloc(10 * sizeof(char));
+ free(x);
+ return x[5];
+}
+
+/* { dg-output "Sleeping for 1 second" } */
===================================================================
@@ -0,0 +1,16 @@
+nm $1 | egrep " [TW] " | sed "s/.* T //" | sed "s/.* W //" \
+ | grep "__asan_" | sed "s/___asan_/__asan_/" > 1.t
+cat $2 | sed "s/\/\/.*//" | sed "s/typedef.*//" \
+| grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" > 2.t
+echo __asan_report_load1 >> 2.t
+echo __asan_report_load2 >> 2.t
+echo __asan_report_load4 >> 2.t
+echo __asan_report_load8 >> 2.t
+echo __asan_report_load16 >> 2.t
+echo __asan_report_store1 >> 2.t
+echo __asan_report_store2 >> 2.t
+echo __asan_report_store4 >> 2.t
+echo __asan_report_store8 >> 2.t
+echo __asan_report_store16 >> 2.t
+cat 2.t | sort -u | diff 1.t -
+rm 1.t 2.t
Property changes on: gcc/testsuite/c-c++-common/asan/Helpers/interface_symbols.sh
___________________________________________________________________
Added: svn:executable
+ *
===================================================================
@@ -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();
===================================================================
@@ -0,0 +1,3 @@
+fun:*brokenFunction*
+global:*badGlobal*
+src:*blacklist-extra-1.c
===================================================================
@@ -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
+}