aboutsummaryrefslogtreecommitdiff
path: root/test/asan/TestCases/Posix
diff options
context:
space:
mode:
Diffstat (limited to 'test/asan/TestCases/Posix')
-rw-r--r--test/asan/TestCases/Posix/allow_user_segv.cc59
-rw-r--r--test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc63
-rw-r--r--test/asan/TestCases/Posix/asprintf.cc20
-rw-r--r--test/asan/TestCases/Posix/assign_large_valloc_to_global.cc9
-rw-r--r--test/asan/TestCases/Posix/glob.cc33
-rw-r--r--test/asan/TestCases/Posix/glob_test_root/aa0
-rw-r--r--test/asan/TestCases/Posix/glob_test_root/ab0
-rw-r--r--test/asan/TestCases/Posix/glob_test_root/ba0
-rw-r--r--test/asan/TestCases/Posix/init-order-dlopen.cc72
-rw-r--r--test/asan/TestCases/Posix/ioctl.cc24
-rw-r--r--test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc39
-rw-r--r--test/asan/TestCases/Posix/lit.local.cfg9
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_test.cc24
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc38
-rw-r--r--test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc38
-rw-r--r--test/asan/TestCases/Posix/readv.cc32
-rw-r--r--test/asan/TestCases/Posix/shared-lib-test.cc57
-rw-r--r--test/asan/TestCases/Posix/start-deactivated.cc69
-rw-r--r--test/asan/TestCases/Posix/strerror_r_test.cc14
-rw-r--r--test/asan/TestCases/Posix/tsd_dtor_leak.cc39
-rw-r--r--test/asan/TestCases/Posix/wait.cc45
-rw-r--r--test/asan/TestCases/Posix/wait4.cc43
-rw-r--r--test/asan/TestCases/Posix/waitid.cc28
23 files changed, 755 insertions, 0 deletions
diff --git a/test/asan/TestCases/Posix/allow_user_segv.cc b/test/asan/TestCases/Posix/allow_user_segv.cc
new file mode 100644
index 000000000000..b6443fab85df
--- /dev/null
+++ b/test/asan/TestCases/Posix/allow_user_segv.cc
@@ -0,0 +1,59 @@
+// 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 %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true not %run %t 2>&1 | FileCheck %s
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct sigaction original_sigaction_sigbus;
+struct sigaction original_sigaction_sigsegv;
+
+void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) {
+ fprintf(stderr, "User sigaction called\n");
+ struct sigaction original_sigaction;
+ if (signum == SIGBUS)
+ original_sigaction = original_sigaction_sigbus;
+ else if (signum == SIGSEGV)
+ original_sigaction = original_sigaction_sigsegv;
+ else {
+ printf("Invalid signum");
+ exit(1);
+ }
+ 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 InstallHandler(int signum, struct sigaction *original_sigaction) {
+ struct sigaction user_sigaction;
+ user_sigaction.sa_sigaction = User_OnSIGSEGV;
+ user_sigaction.sa_flags = SA_SIGINFO;
+ if (sigaction(signum, &user_sigaction, original_sigaction)) {
+ perror("sigaction");
+ return 1;
+ }
+ return 0;
+}
+
+int main() {
+ // Let's install handlers for both SIGSEGV and SIGBUS, since pre-Yosemite
+ // 32-bit Darwin triggers SIGBUS instead.
+ if (InstallHandler(SIGSEGV, &original_sigaction_sigsegv)) return 1;
+ if (InstallHandler(SIGBUS, &original_sigaction_sigbus)) 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/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
new file mode 100644
index 000000000000..6ed02f4d5374
--- /dev/null
+++ b/test/asan/TestCases/Posix/asan-symbolize-sanity-test.cc
@@ -0,0 +1,63 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// Check that asan_symbolize.py script works (for binaries, ASan RTL and
+// shared object files.
+
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: env ASAN_OPTIONS=symbolize=0 not %run %t 2>&1 | %asan_symbolize | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+// XFAIL: armv7l-unknown-linux-gnueabihf
+
+#if !defined(SHARED_LIB)
+#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 {{.*}}asan-symbolize-sanity-test.cc:[[@LINE+21]]
+ // 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;
+}
+#else // SHARED_LIBS
+#include <stdio.h>
+#include <string.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]++;
+}
+#endif // SHARED_LIBS
diff --git a/test/asan/TestCases/Posix/asprintf.cc b/test/asan/TestCases/Posix/asprintf.cc
new file mode 100644
index 000000000000..6946e5013d2c
--- /dev/null
+++ b/test/asan/TestCases/Posix/asprintf.cc
@@ -0,0 +1,20 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv) {
+ char *p;
+ int res = asprintf(&p, "%d", argc);
+ fprintf(stderr, "x%d %sx\n", res, p);
+ // CHECK: x1 1x
+ free(p);
+ fprintf(stderr, "DONE\n");
+ // CHECK: DONE
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc b/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc
new file mode 100644
index 000000000000..ad547ce0ce1b
--- /dev/null
+++ b/test/asan/TestCases/Posix/assign_large_valloc_to_global.cc
@@ -0,0 +1,9 @@
+// Make sure we don't report a leak nor hang.
+// RUN: %clangxx_asan -O3 %s -o %t && %run %t
+#include <stdlib.h>
+#include <unistd.h>
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
+# include <malloc.h>
+#endif // !__APPLE__ && !__FreeBSD__
+int *p = (int*)valloc(1 << 20);
+int main() { }
diff --git a/test/asan/TestCases/Posix/glob.cc b/test/asan/TestCases/Posix/glob.cc
new file mode 100644
index 000000000000..e0eeb33cca24
--- /dev/null
+++ b/test/asan/TestCases/Posix/glob.cc
@@ -0,0 +1,33 @@
+// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316
+// XFAIL: android
+//
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+
+#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/test/asan/TestCases/Posix/glob_test_root/aa b/test/asan/TestCases/Posix/glob_test_root/aa
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/asan/TestCases/Posix/glob_test_root/aa
diff --git a/test/asan/TestCases/Posix/glob_test_root/ab b/test/asan/TestCases/Posix/glob_test_root/ab
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/asan/TestCases/Posix/glob_test_root/ab
diff --git a/test/asan/TestCases/Posix/glob_test_root/ba b/test/asan/TestCases/Posix/glob_test_root/ba
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/asan/TestCases/Posix/glob_test_root/ba
diff --git a/test/asan/TestCases/Posix/init-order-dlopen.cc b/test/asan/TestCases/Posix/init-order-dlopen.cc
new file mode 100644
index 000000000000..6f204775eb4e
--- /dev/null
+++ b/test/asan/TestCases/Posix/init-order-dlopen.cc
@@ -0,0 +1,72 @@
+// 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 -DSHARED_LIB %s \
+// RUN: -fPIC -shared -o %t-so.so -Wl,-U,_inc_global || \
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s \
+// 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 -pthread -o %t -Wl,--export-dynamic || \
+// RUN: %clangxx_asan -O0 %s -pthread -o %t
+// RUN: ASAN_OPTIONS=strict_init_order=true %run %t 2>&1 | FileCheck %s
+#if !defined(SHARED_LIB)
+#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;
+}
+#else // SHARED_LIB
+#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();
+#endif // SHARED_LIB
diff --git a/test/asan/TestCases/Posix/ioctl.cc b/test/asan/TestCases/Posix/ioctl.cc
new file mode 100644
index 000000000000..78f152fe93fe
--- /dev/null
+++ b/test/asan/TestCases/Posix/ioctl.cc
@@ -0,0 +1,24 @@
+// RUN: %clangxx_asan -O0 -g %s -o %t && ASAN_OPTIONS=handle_ioctl=1 not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 -g %s -o %t && ASAN_OPTIONS=handle_ioctl=1 not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -O0 -g %s -o %t && %run %t
+// RUN: %clangxx_asan -O3 -g %s -o %t && %run %t
+
+#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/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc b/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc
new file mode 100644
index 000000000000..0a4998049cb0
--- /dev/null
+++ b/test/asan/TestCases/Posix/large_allocator_unpoisons_on_free.cc
@@ -0,0 +1,39 @@
+// Test that LargeAllocator unpoisons memory before releasing it to the OS.
+// RUN: %clangxx_asan %s -o %t
+// The memory is released only when the deallocated chunk leaves the quarantine,
+// otherwise the mmap(p, ...) call overwrites the malloc header.
+// RUN: ASAN_OPTIONS=quarantine_size=1 %run %t
+
+#include <assert.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef __ANDROID__
+#include <malloc.h>
+void *my_memalign(size_t boundary, size_t size) {
+ return memalign(boundary, size);
+}
+#else
+void *my_memalign(size_t boundary, size_t size) {
+ void *p;
+ posix_memalign(&p, boundary, size);
+ return p;
+}
+#endif
+
+int main() {
+ const long kPageSize = sysconf(_SC_PAGESIZE);
+ void *p = my_memalign(kPageSize, 1024 * 1024);
+ free(p);
+
+ char *q = (char *)mmap(p, kPageSize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ assert(q == p);
+
+ memset(q, 42, kPageSize);
+
+ munmap(q, kPageSize);
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/lit.local.cfg b/test/asan/TestCases/Posix/lit.local.cfg
new file mode 100644
index 000000000000..60a9460820a6
--- /dev/null
+++ b/test/asan/TestCases/Posix/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 in ['Windows']:
+ config.unsupported = True
diff --git a/test/asan/TestCases/Posix/new_array_cookie_test.cc b/test/asan/TestCases/Posix/new_array_cookie_test.cc
new file mode 100644
index 000000000000..85d51f361835
--- /dev/null
+++ b/test/asan/TestCases/Posix/new_array_cookie_test.cc
@@ -0,0 +1,24 @@
+// REQUIRES: asan-64-bits
+// RUN: %clangxx_asan -O3 %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=poison_array_cookie=1 not %run %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=poison_array_cookie=0 not %run %t 2>&1 | FileCheck %s --check-prefix=NO_COOKIE
+#include <stdio.h>
+#include <stdlib.h>
+struct C {
+ int x;
+ ~C() {
+ fprintf(stderr, "ZZZZZZZZ\n");
+ exit(1);
+ }
+};
+
+int main(int argc, char **argv) {
+ C *buffer = new C[argc];
+ buffer[-2].x = 10;
+// CHECK: AddressSanitizer: heap-buffer-overflow
+// CHECK: in main {{.*}}new_array_cookie_test.cc:[[@LINE-2]]
+// CHECK: is located 0 bytes inside of 12-byte region
+// NO_COOKIE: ZZZZZZZZ
+ delete [] buffer;
+}
diff --git a/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc b/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc
new file mode 100644
index 000000000000..c35ccebb8c79
--- /dev/null
+++ b/test/asan/TestCases/Posix/new_array_cookie_uaf_test.cc
@@ -0,0 +1,38 @@
+// REQUIRES: asan-64-bits
+// RUN: %clangxx_asan -O3 %s -o %t
+// RUN: ASAN_OPTIONS=poison_array_cookie=1 not %run %t 2>&1 | FileCheck %s --check-prefix=COOKIE
+// RUN: ASAN_OPTIONS=poison_array_cookie=0 not %run %t 2>&1 | FileCheck %s --check-prefix=NO_COOKIE
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+int dtor_counter;
+struct C {
+ int x;
+ ~C() {
+ dtor_counter++;
+ fprintf(stderr, "DTOR %d\n", dtor_counter);
+ }
+};
+
+__attribute__((noinline)) void Delete(C *c) { delete[] c; }
+__attribute__((no_sanitize_address)) void Write42ToCookie(C *c) {
+ long *p = reinterpret_cast<long*>(c);
+ p[-1] = 42;
+}
+
+int main(int argc, char **argv) {
+ C *buffer = new C[argc];
+ delete [] buffer;
+ Write42ToCookie(buffer);
+ delete [] buffer;
+// COOKIE: DTOR 1
+// COOKIE-NOT: DTOR 2
+// COOKIE: AddressSanitizer: loaded array cookie from free-d memory
+// COOKIE: AddressSanitizer: attempting double-free
+// NO_COOKIE: DTOR 1
+// NO_COOKIE: DTOR 43
+// NO_COOKIE-NOT: DTOR 44
+// NO_COOKIE-NOT: AddressSanitizer: loaded array cookie from free-d memory
+// NO_COOKIE: AddressSanitizer: attempting double-free
+
+}
diff --git a/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc b/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc
new file mode 100644
index 000000000000..1cea6f68adb2
--- /dev/null
+++ b/test/asan/TestCases/Posix/new_array_cookie_with_new_from_class.cc
@@ -0,0 +1,38 @@
+// Test that we do not poison the array cookie if the operator new is defined
+// inside the class.
+// RUN: %clangxx_asan %s -o %t && %run %t
+//
+// XFAIL: android
+// XFAIL: armv7l-unknown-linux-gnueabihf
+#include <new>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <assert.h>
+struct Foo {
+ void *operator new(size_t s) { return Allocate(s); }
+ void *operator new[] (size_t s) { return Allocate(s); }
+ ~Foo();
+ static void *allocated;
+ static void *Allocate(size_t s) {
+ assert(!allocated);
+ return allocated = ::new char[s];
+ }
+};
+
+Foo::~Foo() {}
+void *Foo::allocated;
+
+Foo *getFoo(size_t n) {
+ return new Foo[n];
+}
+
+int main() {
+ Foo *foo = getFoo(10);
+ fprintf(stderr, "foo : %p\n", foo);
+ fprintf(stderr, "alloc: %p\n", Foo::allocated);
+ assert(reinterpret_cast<uintptr_t>(foo) ==
+ reinterpret_cast<uintptr_t>(Foo::allocated) + sizeof(void*));
+ *reinterpret_cast<uintptr_t*>(Foo::allocated) = 42;
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/readv.cc b/test/asan/TestCases/Posix/readv.cc
new file mode 100644
index 000000000000..27436a1ad3d9
--- /dev/null
+++ b/test/asan/TestCases/Posix/readv.cc
@@ -0,0 +1,32 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t
+// RUN: %clangxx_asan -O0 %s -DPOSITIVE -o %t && not %run %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/test/asan/TestCases/Posix/shared-lib-test.cc b/test/asan/TestCases/Posix/shared-lib-test.cc
new file mode 100644
index 000000000000..a0827b5fefbf
--- /dev/null
+++ b/test/asan/TestCases/Posix/shared-lib-test.cc
@@ -0,0 +1,57 @@
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O1 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O2 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+
+#if !defined(SHARED_LIB)
+#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;
+}
+#else // SHARED_LIB
+#include <stdio.h>
+#include <string.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]++;
+}
+#endif // SHARED_LIB
diff --git a/test/asan/TestCases/Posix/start-deactivated.cc b/test/asan/TestCases/Posix/start-deactivated.cc
new file mode 100644
index 000000000000..d60677a8a5bb
--- /dev/null
+++ b/test/asan/TestCases/Posix/start-deactivated.cc
@@ -0,0 +1,69 @@
+// Test for ASAN_OPTIONS=start_deactivated=1 mode.
+// Main executable is uninstrumented, but linked to ASan runtime. The shared
+// library is instrumented. Memory errors before dlopen are not detected.
+
+// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
+// RUN: %clangxx -O0 %s -c -o %t.o
+// RUN: %clangxx_asan -O0 %t.o -o %t
+// RUN: ASAN_OPTIONS=start_deactivated=1 not %run %t 2>&1 | FileCheck %s
+// XFAIL: arm-linux-gnueabi
+// XFAIL: armv7l-unknown-linux-gnueabihf
+
+#if !defined(SHARED_LIB)
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "sanitizer/asan_interface.h"
+
+void test_malloc_shadow() {
+ char *p = (char *)malloc(100);
+ char *q = (char *)__asan_region_is_poisoned(p + 95, 8);
+ fprintf(stderr, "=%zd=\n", q ? q - (p + 95) : -1);
+ free(p);
+}
+
+typedef void (*Fn)();
+
+int main(int argc, char *argv[]) {
+ test_malloc_shadow();
+ // CHECK: =-1=
+
+ std::string path = std::string(argv[0]) + "-so.so";
+ void *dso = dlopen(path.c_str(), RTLD_NOW);
+ if (!dso) {
+ fprintf(stderr, "dlopen failed: %s\n", dlerror());
+ return 1;
+ }
+
+ test_malloc_shadow();
+ // CHECK: =5=
+
+ void *fn = dlsym(dso, "do_another_bad_thing");
+ if (!fn) {
+ fprintf(stderr, "dlsym failed: %s\n", dlerror());
+ return 1;
+ }
+
+ ((Fn)fn)();
+ // CHECK: AddressSanitizer: heap-buffer-overflow
+ // CHECK: READ of size 1
+ // CHECK: {{#0 .* in do_another_bad_thing}}
+ // CHECK: is located 5 bytes to the right of 100-byte region
+ // CHECK: in do_another_bad_thing
+
+ return 0;
+}
+#else // SHARED_LIB
+#include <stdio.h>
+#include <stdlib.h>
+
+extern "C" void do_another_bad_thing() {
+ char *volatile p = (char *)malloc(100);
+ printf("%hhx\n", p[105]);
+}
+#endif // SHARED_LIB
diff --git a/test/asan/TestCases/Posix/strerror_r_test.cc b/test/asan/TestCases/Posix/strerror_r_test.cc
new file mode 100644
index 000000000000..e6df441770df
--- /dev/null
+++ b/test/asan/TestCases/Posix/strerror_r_test.cc
@@ -0,0 +1,14 @@
+// RUN: %clangxx_asan -O0 %s -o %t && %run %t
+
+// Regression test for PR17138.
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+int main() {
+ char buf[1024];
+ char *res = (char *)strerror_r(300, buf, sizeof(buf));
+ printf("%p\n", res);
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/tsd_dtor_leak.cc b/test/asan/TestCases/Posix/tsd_dtor_leak.cc
new file mode 100644
index 000000000000..32253afc8b25
--- /dev/null
+++ b/test/asan/TestCases/Posix/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 -pthread -o %t
+// RUN: ASAN_OPTIONS=quarantine_size=1 %run %t
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <sanitizer/allocator_interface.h>
+
+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 = __sanitizer_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/test/asan/TestCases/Posix/wait.cc b/test/asan/TestCases/Posix/wait.cc
new file mode 100644
index 000000000000..99d0212acfab
--- /dev/null
+++ b/test/asan/TestCases/Posix/wait.cc
@@ -0,0 +1,45 @@
+// RUN: %clangxx_asan -DWAIT -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAITPID -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAITPID -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT3 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT3 -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT3_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT3_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+
+#include <assert.h>
+#include <sys/wait.h>
+#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(WAIT3)
+ res = wait3(status, WNOHANG, NULL);
+#elif defined(WAIT3_RUSAGE)
+ struct rusage *ru = (struct rusage*)(x + argc * 3);
+ int good_status;
+ res = wait3(&good_status, WNOHANG, ru);
+#endif
+ // CHECK: stack-buffer-overflow
+ // CHECK: {{WRITE of size .* at 0x.* thread T0}}
+ // CHECK: {{in .*wait}}
+ // CHECK: {{in main .*wait.cc:}}
+ // CHECK: is located in stack of thread T0 at offset
+ // CHECK: {{in main}}
+ return res == -1 ? 1 : 0;
+ }
+ // child
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/wait4.cc b/test/asan/TestCases/Posix/wait4.cc
new file mode 100644
index 000000000000..b95246efa0e4
--- /dev/null
+++ b/test/asan/TestCases/Posix/wait4.cc
@@ -0,0 +1,43 @@
+// RUN: %clangxx_asan -DWAIT4 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT4 -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// RUN: %clangxx_asan -DWAIT4_RUSAGE -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -DWAIT4_RUSAGE -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+// XFAIL: android
+
+#include <assert.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ // This test passes on some versions of Android NDK and fails on other.
+ // https://code.google.com/p/memory-sanitizer/issues/detail?id=64
+ // Make it fail unconditionally on Android.
+#ifdef __ANDROID__
+ return 0;
+#endif
+
+ pid_t pid = fork();
+ if (pid) { // parent
+ int x[3];
+ int *status = x + argc * 3;
+ int res;
+#if defined(WAIT4)
+ res = wait4(pid, status, WNOHANG, NULL);
+#elif defined(WAIT4_RUSAGE)
+ struct rusage *ru = (struct rusage*)(x + argc * 3);
+ int good_status;
+ res = wait4(pid, &good_status, WNOHANG, ru);
+#endif
+ // CHECK: stack-buffer-overflow
+ // CHECK: {{WRITE of size .* at 0x.* thread T0}}
+ // CHECK: {{in .*wait}}
+ // CHECK: {{in main .*wait4.cc:}}
+ // CHECK: is located in stack of thread T0 at offset
+ // CHECK: {{in main}}
+ return res == -1 ? 1 : 0;
+ }
+ // child
+ return 0;
+}
diff --git a/test/asan/TestCases/Posix/waitid.cc b/test/asan/TestCases/Posix/waitid.cc
new file mode 100644
index 000000000000..8b516dca9086
--- /dev/null
+++ b/test/asan/TestCases/Posix/waitid.cc
@@ -0,0 +1,28 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <assert.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+
+int main(int argc, char **argv) {
+ pid_t pid = fork();
+ if (pid) { // parent
+ int x[3];
+ int *status = x + argc * 3;
+ int res;
+
+ siginfo_t *si = (siginfo_t*)(x + argc * 3);
+ res = waitid(P_ALL, 0, si, WEXITED | WNOHANG);
+ // CHECK: stack-buffer-overflow
+ // CHECK: {{WRITE of size .* at 0x.* thread T0}}
+ // CHECK: {{in .*waitid}}
+ // CHECK: {{in main .*waitid.cc:}}
+ // CHECK: is located in stack of thread T0 at offset
+ // CHECK: {{in main}}
+ return res != -1;
+ }
+ // child
+ return 0;
+}