diff options
Diffstat (limited to 'test/asan/TestCases/Posix')
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; +} |