diff options
Diffstat (limited to 'lib/asan/lit_tests')
67 files changed, 1194 insertions, 116 deletions
diff --git a/lib/asan/lit_tests/CMakeLists.txt b/lib/asan/lit_tests/CMakeLists.txt index 1609032d4670..d2420b50da83 100644 --- a/lib/asan/lit_tests/CMakeLists.txt +++ b/lib/asan/lit_tests/CMakeLists.txt @@ -14,9 +14,9 @@ configure_lit_site_cfg( if(COMPILER_RT_CAN_EXECUTE_TESTS) # Run ASan tests only if we're sure we may produce working binaries. set(ASAN_TEST_DEPS - clang clang-headers FileCheck count not llvm-nm llvm-symbolizer + ${SANITIZER_COMMON_LIT_TEST_DEPS} ${ASAN_RUNTIME_LIBRARIES} - ) + asan_blacklist) set(ASAN_TEST_PARAMS asan_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg ) diff --git a/lib/asan/lit_tests/Darwin/interface_symbols_darwin.c b/lib/asan/lit_tests/Darwin/interface_symbols_darwin.c new file mode 100644 index 000000000000..3fca6e915324 --- /dev/null +++ b/lib/asan/lit_tests/Darwin/interface_symbols_darwin.c @@ -0,0 +1,39 @@ +// Check the presense of interface symbols in the ASan runtime dylib. +// If you're changing this file, please also change +// ../Linux/interface_symbols.c + +// RUN: %clang -fsanitize=address -dead_strip -O2 %s -o %t.exe +// RUN: rm -f %t.symbols %t.interface + +// RUN: nm -g `otool -L %t.exe | grep "asan_osx_dynamic.dylib" | \ +// RUN: tr -d '\011' | \ +// RUN: sed "s/.dylib.*/.dylib/"` \ +// RUN: | grep " T " | sed "s/.* T //" \ +// RUN: | grep "__asan_" | sed "s/___asan_/__asan_/" \ +// RUN: | grep -v "__asan_malloc_hook" \ +// RUN: | grep -v "__asan_free_hook" \ +// RUN: | grep -v "__asan_symbolize" \ +// RUN: | grep -v "__asan_default_options" \ +// RUN: | grep -v "__asan_on_error" > %t.symbols + +// RUN: cat %p/../../asan_interface_internal.h \ +// RUN: | sed "s/\/\/.*//" | sed "s/typedef.*//" \ +// RUN: | grep -v "OPTIONAL" \ +// RUN: | grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" \ +// RUN: > %t.interface +// RUN: echo __asan_report_load1 >> %t.interface +// RUN: echo __asan_report_load2 >> %t.interface +// RUN: echo __asan_report_load4 >> %t.interface +// RUN: echo __asan_report_load8 >> %t.interface +// RUN: echo __asan_report_load16 >> %t.interface +// RUN: echo __asan_report_store1 >> %t.interface +// RUN: echo __asan_report_store2 >> %t.interface +// RUN: echo __asan_report_store4 >> %t.interface +// RUN: echo __asan_report_store8 >> %t.interface +// RUN: echo __asan_report_store16 >> %t.interface +// RUN: echo __asan_report_load_n >> %t.interface +// RUN: echo __asan_report_store_n >> %t.interface + +// RUN: cat %t.interface | sort -u | diff %t.symbols - + +int main() { return 0; } diff --git a/lib/asan/lit_tests/Darwin/lit.local.cfg b/lib/asan/lit_tests/Darwin/lit.local.cfg new file mode 100644 index 000000000000..a85dfcd24c08 --- /dev/null +++ b/lib/asan/lit_tests/Darwin/lit.local.cfg @@ -0,0 +1,9 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +root = getRoot(config) + +if root.host_os not in ['Darwin']: + config.unsupported = True diff --git a/lib/asan/lit_tests/Darwin/reexec-insert-libraries-env.cc b/lib/asan/lit_tests/Darwin/reexec-insert-libraries-env.cc new file mode 100644 index 000000000000..40a459fd84db --- /dev/null +++ b/lib/asan/lit_tests/Darwin/reexec-insert-libraries-env.cc @@ -0,0 +1,20 @@ +// Make sure ASan doesn't hang in an exec loop if DYLD_INSERT_LIBRARIES is set. +// This is a regression test for +// https://code.google.com/p/address-sanitizer/issues/detail?id=159 + +// RUN: %clangxx_asan -m64 %s -o %t +// RUN: %clangxx -m64 %p/../SharedLibs/darwin-dummy-shared-lib-so.cc \ +// RUN: -dynamiclib -o darwin-dummy-shared-lib-so.dylib + +// FIXME: the following command line may hang in the case of a regression. +// RUN: DYLD_INSERT_LIBRARIES=darwin-dummy-shared-lib-so.dylib \ +// RUN: %t 2>&1 | FileCheck %s || exit 1 +#include <stdio.h> +#include <stdlib.h> + +int main() { + const char kEnvName[] = "DYLD_INSERT_LIBRARIES"; + printf("%s=%s\n", kEnvName, getenv(kEnvName)); + // CHECK: {{DYLD_INSERT_LIBRARIES=.*darwin-dummy-shared-lib-so.dylib.*}} + return 0; +} diff --git a/lib/asan/lit_tests/Darwin/unset-insert-libraries-on-exec.cc b/lib/asan/lit_tests/Darwin/unset-insert-libraries-on-exec.cc new file mode 100644 index 000000000000..cf89949cf942 --- /dev/null +++ b/lib/asan/lit_tests/Darwin/unset-insert-libraries-on-exec.cc @@ -0,0 +1,20 @@ +// Make sure ASan removes the runtime library from DYLD_INSERT_LIBRARIES before +// executing other programs. + +// RUN: %clangxx_asan -m64 %s -o %t +// RUN: %clangxx -m64 %p/../SharedLibs/darwin-dummy-shared-lib-so.cc \ +// RUN: -dynamiclib -o darwin-dummy-shared-lib-so.dylib + +// Make sure DYLD_INSERT_LIBRARIES doesn't contain the runtime library before +// execl(). + +// RUN: %t >/dev/null 2>&1 +// RUN: DYLD_INSERT_LIBRARIES=darwin-dummy-shared-lib-so.dylib \ +// RUN: %t 2>&1 | FileCheck %s || exit 1 +#include <unistd.h> +int main() { + execl("/bin/bash", "/bin/bash", "-c", + "echo DYLD_INSERT_LIBRARIES=$DYLD_INSERT_LIBRARIES", NULL); + // CHECK: {{DYLD_INSERT_LIBRARIES=.*darwin-dummy-shared-lib-so.dylib.*}} + return 0; +} diff --git a/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc b/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc new file mode 100644 index 000000000000..e4189d19d099 --- /dev/null +++ b/lib/asan/lit_tests/Helpers/init-order-atexit-extra.cc @@ -0,0 +1,16 @@ +#include <stdio.h> + +class C { + public: + C() { value = 42; } + ~C() { } + int value; +}; + +C c; + +void AccessC() { + printf("C value: %d\n", c.value); +} + +int main() { return 0; } diff --git a/lib/asan/lit_tests/Helpers/initialization-blacklist-extra2.cc b/lib/asan/lit_tests/Helpers/initialization-blacklist-extra2.cc new file mode 100644 index 000000000000..69455a0a6fc9 --- /dev/null +++ b/lib/asan/lit_tests/Helpers/initialization-blacklist-extra2.cc @@ -0,0 +1,4 @@ +int zero_init(); +int badSrcGlobal = zero_init(); +int readBadSrcGlobal() { return badSrcGlobal; } + diff --git a/lib/asan/lit_tests/Helpers/initialization-blacklist.txt b/lib/asan/lit_tests/Helpers/initialization-blacklist.txt index c5f6610937f0..fa4a83667f4b 100644 --- a/lib/asan/lit_tests/Helpers/initialization-blacklist.txt +++ b/lib/asan/lit_tests/Helpers/initialization-blacklist.txt @@ -1,2 +1,3 @@ global-init:*badGlobal* global-init-type:*badNamespace::BadClass* +global-init-src:*initialization-blacklist-extra2.cc diff --git a/lib/asan/lit_tests/Helpers/initialization-constexpr-extra.cc b/lib/asan/lit_tests/Helpers/initialization-constexpr-extra.cc new file mode 100644 index 000000000000..b32466a981b3 --- /dev/null +++ b/lib/asan/lit_tests/Helpers/initialization-constexpr-extra.cc @@ -0,0 +1,3 @@ +// Constexpr: +int getCoolestInteger(); +static int coolest_integer = getCoolestInteger(); diff --git a/lib/asan/lit_tests/Helpers/initialization-nobug-extra.cc b/lib/asan/lit_tests/Helpers/initialization-nobug-extra.cc index 490b3339054a..886165affd76 100644 --- a/lib/asan/lit_tests/Helpers/initialization-nobug-extra.cc +++ b/lib/asan/lit_tests/Helpers/initialization-nobug-extra.cc @@ -4,6 +4,6 @@ static int ab = getAB(); // Function local statics: int countCalls(); static int one = countCalls(); -// Constexpr: -int getCoolestInteger(); -static int coolest_integer = getCoolestInteger(); +// Trivial constructor, non-trivial destructor: +int getStructWithDtorValue(); +static int val = getStructWithDtorValue(); diff --git a/lib/asan/lit_tests/Linux/asan_prelink_test.cc b/lib/asan/lit_tests/Linux/asan_prelink_test.cc new file mode 100644 index 000000000000..c209c39c8c42 --- /dev/null +++ b/lib/asan/lit_tests/Linux/asan_prelink_test.cc @@ -0,0 +1,28 @@ +// Test if asan works with prelink. +// It does not actually use prelink, but relies on ld's flag -Ttext-segment +// or gold's flag -Ttext (we try the first flag first, if that fails we +// try the second flag). +// +// RUN: %clangxx_asan -m64 -c %s -o %t.o +// RUN: %clangxx_asan -m64 -DBUILD_SO=1 -fPIC -shared %s -o %t.so -Wl,-Ttext-segment=0x3600000000 ||\ +// RUN: %clangxx_asan -m64 -DBUILD_SO=1 -fPIC -shared %s -o %t.so -Wl,-Ttext=0x3600000000 +// RUN: %clangxx_asan -m64 %t.o %t.so -Wl,-R. -o %t +// RUN: ASAN_OPTIONS=verbosity=1 %t 2>&1 | FileCheck %s + +// REQUIRES: x86_64-supported-target +#if BUILD_SO +int G; +int *getG() { + return &G; +} +#else +#include <stdio.h> +extern int *getG(); +int main(int argc, char **argv) { + long p = (long)getG(); + printf("SO mapped at %lx\n", p & ~0xffffffffUL); + *getG() = 0; +} +#endif +// CHECK: 0x003000000000, 0x004fffffffff{{.*}} MidMem +// CHECK: SO mapped at 3600000000 diff --git a/lib/asan/lit_tests/Linux/glob.cc b/lib/asan/lit_tests/Linux/glob.cc new file mode 100644 index 000000000000..e05228ff39e3 --- /dev/null +++ b/lib/asan/lit_tests/Linux/glob.cc @@ -0,0 +1,30 @@ +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t %p 2>&1 | FileCheck %s +// RUN: %clangxx_asan -m64 -O3 %s -o %t && %t %p 2>&1 | FileCheck %s +// RUN: %clangxx_asan -m32 -O0 %s -o %t && %t %p 2>&1 | FileCheck %s +// RUN: %clangxx_asan -m32 -O3 %s -o %t && %t %p 2>&1 | FileCheck %s + +#include <assert.h> +#include <glob.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <string> + + +int main(int argc, char *argv[]) { + std::string path = argv[1]; + std::string pattern = path + "/glob_test_root/*a"; + printf("pattern: %s\n", pattern.c_str()); + + glob_t globbuf; + int res = glob(pattern.c_str(), 0, 0, &globbuf); + + printf("%d %s\n", errno, strerror(errno)); + assert(res == 0); + assert(globbuf.gl_pathc == 2); + printf("%zu\n", strlen(globbuf.gl_pathv[0])); + printf("%zu\n", strlen(globbuf.gl_pathv[1])); + printf("PASS\n"); + // CHECK: PASS + return 0; +} diff --git a/lib/asan/lit_tests/Linux/glob_test_root/aa b/lib/asan/lit_tests/Linux/glob_test_root/aa new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/lib/asan/lit_tests/Linux/glob_test_root/aa diff --git a/lib/asan/lit_tests/Linux/glob_test_root/ab b/lib/asan/lit_tests/Linux/glob_test_root/ab new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/lib/asan/lit_tests/Linux/glob_test_root/ab diff --git a/lib/asan/lit_tests/Linux/glob_test_root/ba b/lib/asan/lit_tests/Linux/glob_test_root/ba new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/lib/asan/lit_tests/Linux/glob_test_root/ba diff --git a/lib/asan/lit_tests/Linux/heavy_uar_test.cc b/lib/asan/lit_tests/Linux/heavy_uar_test.cc new file mode 100644 index 000000000000..c0f4560fb4e7 --- /dev/null +++ b/lib/asan/lit_tests/Linux/heavy_uar_test.cc @@ -0,0 +1,55 @@ +// RUN: %clangxx_asan -fsanitize=use-after-return -m64 -O0 %s -o %t && \ +// RUN: %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -fsanitize=use-after-return -m64 -O2 %s -o %t && \ +// RUN: %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -fsanitize=use-after-return -m32 -O2 %s -o %t && \ +// RUN: %t 2>&1 | %symbolize | FileCheck %s + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +__attribute__((noinline)) +char *pretend_to_do_something(char *x) { + __asm__ __volatile__("" : : "r" (x) : "memory"); + return x; +} + +__attribute__((noinline)) +char *LeakStack() { + char x[1024]; + memset(x, 0, sizeof(x)); + return pretend_to_do_something(x); +} + +template<size_t kFrameSize> +__attribute__((noinline)) +void RecuriveFunctionWithStackFrame(int depth) { + if (depth <= 0) return; + char x[kFrameSize]; + x[0] = depth; + pretend_to_do_something(x); + RecuriveFunctionWithStackFrame<kFrameSize>(depth - 1); +} + +int main(int argc, char **argv) { + int n_iter = argc >= 2 ? atoi(argv[1]) : 1000; + int depth = argc >= 3 ? atoi(argv[2]) : 500; + for (int i = 0; i < n_iter; i++) { + RecuriveFunctionWithStackFrame<10>(depth); + RecuriveFunctionWithStackFrame<100>(depth); + RecuriveFunctionWithStackFrame<500>(depth); + RecuriveFunctionWithStackFrame<1024>(depth); + RecuriveFunctionWithStackFrame<2000>(depth); + RecuriveFunctionWithStackFrame<5000>(depth); + RecuriveFunctionWithStackFrame<10000>(depth); + } + char *stale_stack = LeakStack(); + RecuriveFunctionWithStackFrame<1024>(10); + stale_stack[100]++; + // CHECK: ERROR: AddressSanitizer: stack-use-after-return on address + // CHECK: is located in stack of thread T0 at offset 132 in frame + // CHECK: in LeakStack(){{.*}}heavy_uar_test.cc: + // CHECK: [32, 1056) 'x' + return 0; +} diff --git a/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc b/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc index 645fe1c85ed4..4f41dda18128 100644 --- a/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc +++ b/lib/asan/lit_tests/Linux/initialization-bug-any-order.cc @@ -1,12 +1,13 @@ // 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. +// independently on order in which we list source files (if we specify +// strict init-order checking). -// RUN: %clangxx_asan -m64 -O0 %s %p/../Helpers/initialization-bug-extra.cc\ -// RUN: -fsanitize=init-order -o %t && %t 2>&1 \ +// RUN: %clangxx_asan -m64 -O0 %s %p/../Helpers/initialization-bug-extra.cc -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true:strict_init_order=true %t 2>&1 \ // RUN: | %symbolize | FileCheck %s -// RUN: %clangxx_asan -m64 -O0 %p/../Helpers/initialization-bug-extra.cc %s\ -// RUN: -fsanitize=init-order -o %t && %t 2>&1 \ +// RUN: %clangxx_asan -m64 -O0 %p/../Helpers/initialization-bug-extra.cc %s -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true:strict_init_order=true %t 2>&1 \ // RUN: | %symbolize | FileCheck %s // Do not test with optimization -- the error may be optimized away. diff --git a/lib/asan/lit_tests/interface_symbols.c b/lib/asan/lit_tests/Linux/interface_symbols_linux.c index f3167f562922..4134c8744043 100644 --- a/lib/asan/lit_tests/interface_symbols.c +++ b/lib/asan/lit_tests/Linux/interface_symbols_linux.c @@ -1,14 +1,14 @@ // Check the presense of interface symbols in compiled file. -// RUN: %clang -fsanitize=address -dead_strip -O2 %s -o %t.exe -// RUN: nm %t.exe | grep " T " | sed "s/.* T //" \ +// RUN: %clang -fsanitize=address -O2 %s -o %t.exe +// RUN: nm -D %t.exe | grep " T " | sed "s/.* T //" \ // RUN: | grep "__asan_" | sed "s/___asan_/__asan_/" \ // RUN: | grep -v "__asan_malloc_hook" \ // RUN: | grep -v "__asan_free_hook" \ // RUN: | grep -v "__asan_symbolize" \ // RUN: | grep -v "__asan_default_options" \ // RUN: | grep -v "__asan_on_error" > %t.symbols -// RUN: cat %p/../../../include/sanitizer/asan_interface.h \ +// RUN: cat %p/../../asan_interface_internal.h \ // RUN: | sed "s/\/\/.*//" | sed "s/typedef.*//" \ // RUN: | grep -v "OPTIONAL" \ // RUN: | grep "__asan_.*(" | sed "s/.* __asan_/__asan_/;s/(.*//" \ @@ -23,6 +23,12 @@ // RUN: echo __asan_report_store4 >> %t.interface // RUN: echo __asan_report_store8 >> %t.interface // RUN: echo __asan_report_store16 >> %t.interface +// RUN: echo __asan_report_load_n >> %t.interface +// RUN: echo __asan_report_store_n >> %t.interface // RUN: cat %t.interface | sort -u | diff %t.symbols - +// FIXME: nm -D on powerpc somewhy shows ASan interface symbols residing +// in "initialized data section". +// REQUIRES: x86_64-supported-target,i386-supported-target + int main() { return 0; } diff --git a/lib/asan/lit_tests/Linux/malloc-in-qsort.cc b/lib/asan/lit_tests/Linux/malloc-in-qsort.cc index a3fa255b186d..ee2e81f0d2ab 100644 --- a/lib/asan/lit_tests/Linux/malloc-in-qsort.cc +++ b/lib/asan/lit_tests/Linux/malloc-in-qsort.cc @@ -1,10 +1,14 @@ -// RUN: %clangxx_asan -O2 %s -o %t +// RUN: %clangxx_asan -m64 -O2 %s -o %t // RUN: ASAN_OPTIONS=fast_unwind_on_malloc=1 %t 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK-FAST // RUN: ASAN_OPTIONS=fast_unwind_on_malloc=0 %t 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK-SLOW // Test how well we unwind in presence of qsort in the stack // (i.e. if we can unwind through a function compiled w/o frame pointers). // https://code.google.com/p/address-sanitizer/issues/detail?id=137 + +// Fast unwinder is only avaliable on x86_64 and i386. +// REQUIRES: x86_64-supported-target + #include <stdlib.h> #include <stdio.h> diff --git a/lib/asan/lit_tests/malloc_delete_mismatch.cc b/lib/asan/lit_tests/Linux/malloc_delete_mismatch.cc index f34b33a38fb3..f34b33a38fb3 100644 --- a/lib/asan/lit_tests/malloc_delete_mismatch.cc +++ b/lib/asan/lit_tests/Linux/malloc_delete_mismatch.cc diff --git a/lib/asan/lit_tests/Linux/overflow-in-qsort.cc b/lib/asan/lit_tests/Linux/overflow-in-qsort.cc index c298991a8348..8bc43ca0a5c3 100644 --- a/lib/asan/lit_tests/Linux/overflow-in-qsort.cc +++ b/lib/asan/lit_tests/Linux/overflow-in-qsort.cc @@ -1,10 +1,14 @@ -// RUN: %clangxx_asan -O2 %s -o %t +// RUN: %clangxx_asan -m64 -O2 %s -o %t // RUN: ASAN_OPTIONS=fast_unwind_on_fatal=1 %t 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK-FAST // RUN: ASAN_OPTIONS=fast_unwind_on_fatal=0 %t 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK-SLOW // Test how well we unwind in presence of qsort in the stack // (i.e. if we can unwind through a function compiled w/o frame pointers). // https://code.google.com/p/address-sanitizer/issues/detail?id=137 + +// Fast unwinder is only avaliable on x86_64 and i386. +// REQUIRES: x86_64-supported-target + #include <stdlib.h> #include <stdio.h> diff --git a/lib/asan/lit_tests/Linux/preinit_test.cc b/lib/asan/lit_tests/Linux/preinit_test.cc new file mode 100644 index 000000000000..28e509472c0c --- /dev/null +++ b/lib/asan/lit_tests/Linux/preinit_test.cc @@ -0,0 +1,27 @@ +// RUN: %clangxx -DFUNC=zzzz %s -shared -o %t.so -fPIC +// RUN: %clangxx_asan -DFUNC=main %s -o %t -Wl,-R. %t.so +// RUN: %t + +// This test ensures that we call __asan_init early enough. +// We build a shared library w/o asan instrumentation +// and the binary with asan instrumentation. +// Both files include the same header (emulated by -DFUNC here) +// with C++ template magic which runs global initializer at library load time. +// The function get() is instrumented with asan, but called +// before the usual constructors are run. +// So, we must make sure that __asan_init is executed even earlier. +// +// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56393 + +struct A { + int foo() const { return 0; } +}; +A get () { return A(); } +template <class> struct O { + static A const e; +}; +template <class T> A const O <T>::e = get(); +int FUNC() { + return O<int>::e.foo(); +} + diff --git a/lib/asan/lit_tests/Linux/rlimit_mmap_test.cc b/lib/asan/lit_tests/Linux/rlimit_mmap_test.cc index 5026e24e424d..86794756c76f 100644 --- a/lib/asan/lit_tests/Linux/rlimit_mmap_test.cc +++ b/lib/asan/lit_tests/Linux/rlimit_mmap_test.cc @@ -11,6 +11,6 @@ int main(int argc, char **argv) { struct rlimit mmap_resource_limit = { 0, 0 }; assert(0 == setrlimit(RLIMIT_AS, &mmap_resource_limit)); x = malloc(10000000); -// CHECK: AddressSanitizer is unable to mmap +// CHECK: ERROR: Failed to mmap return 0; } diff --git a/lib/asan/lit_tests/Linux/swapcontext_test.cc b/lib/asan/lit_tests/Linux/swapcontext_test.cc index 0404b4f602bd..47a8d9891f51 100644 --- a/lib/asan/lit_tests/Linux/swapcontext_test.cc +++ b/lib/asan/lit_tests/Linux/swapcontext_test.cc @@ -8,6 +8,9 @@ // RUN: %clangxx_asan -m32 -O1 %s -o %t && %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -m32 -O2 %s -o %t && %t 2>&1 | FileCheck %s // RUN: %clangxx_asan -m32 -O3 %s -o %t && %t 2>&1 | FileCheck %s +// +// This test is too sublte to try on non-x86 arch for now. +// REQUIRES: x86_64-supported-target,i386-supported-target #include <stdio.h> #include <ucontext.h> @@ -16,9 +19,26 @@ ucontext_t orig_context; ucontext_t child_context; +const int kStackSize = 1 << 20; + +__attribute__((noinline)) +void Throw() { + throw 1; +} + +__attribute__((noinline)) +void ThrowAndCatch() { + try { + Throw(); + } catch(int a) { + printf("ThrowAndCatch: %d\n", a); + } +} + void Child(int mode) { char x[32] = {0}; // Stack gets poisoned. printf("Child: %p\n", x); + ThrowAndCatch(); // Simulate __asan_handle_no_return(). // (a) Do nothing, just return to parent function. // (b) Jump into the original function. Stack remains poisoned unless we do // something. @@ -30,9 +50,7 @@ void Child(int mode) { } } -int Run(int arg, int mode) { - const int kStackSize = 1 << 20; - char child_stack[kStackSize + 1]; +int Run(int arg, int mode, char *child_stack) { printf("Child stack: %p\n", child_stack); // Setup child context. getcontext(&child_context); @@ -54,13 +72,23 @@ int Run(int arg, int mode) { } int main(int argc, char **argv) { + char stack[kStackSize + 1]; // CHECK: WARNING: ASan doesn't fully support makecontext/swapcontext int ret = 0; - ret += Run(argc - 1, 0); + ret += Run(argc - 1, 0, stack); printf("Test1 passed\n"); // CHECK: Test1 passed - ret += Run(argc - 1, 1); + ret += Run(argc - 1, 1, stack); printf("Test2 passed\n"); // CHECK: Test2 passed + char *heap = new char[kStackSize + 1]; + ret += Run(argc - 1, 0, heap); + printf("Test3 passed\n"); + // CHECK: Test3 passed + ret += Run(argc - 1, 1, heap); + printf("Test4 passed\n"); + // CHECK: Test4 passed + + delete [] heap; return ret; } diff --git a/lib/asan/lit_tests/Linux/syscalls.cc b/lib/asan/lit_tests/Linux/syscalls.cc new file mode 100644 index 000000000000..b2edcfb92375 --- /dev/null +++ b/lib/asan/lit_tests/Linux/syscalls.cc @@ -0,0 +1,22 @@ +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m64 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +#include <assert.h> +#include <errno.h> +#include <glob.h> +#include <stdio.h> +#include <string.h> + +#include <sanitizer/linux_syscall_hooks.h> + +/* Test the presence of __sanitizer_syscall_ in the tool runtime, and general + sanity of their behaviour. */ + +int main(int argc, char *argv[]) { + char buf[1000]; + __sanitizer_syscall_pre_recvmsg(0, buf - 1, 0); + // CHECK: AddressSanitizer: stack-buffer-{{.*}}erflow + // CHECK: READ of size {{.*}} at {{.*}} thread T0 + // CHECK: #0 {{.*}} in __sanitizer_syscall_pre_recvmsg + return 0; +} diff --git a/lib/asan/lit_tests/Linux/time_null_regtest.cc b/lib/asan/lit_tests/Linux/time_null_regtest.cc new file mode 100644 index 000000000000..975bca3d105a --- /dev/null +++ b/lib/asan/lit_tests/Linux/time_null_regtest.cc @@ -0,0 +1,20 @@ +// RUN: %clangxx_asan -m64 -O0 %s -fsanitize-address-zero-base-shadow -pie -o %t && %t 2>&1 | %symbolize | FileCheck %s + +// Zero-base shadow only works on x86_64 and i386. +// REQUIRES: x86_64-supported-target + +// A regression test for time(NULL), which caused ASan to crash in the +// zero-based shadow mode on Linux. +// FIXME: this test does not work on Darwin, because the code pages of the +// executable interleave with the zero-based shadow. + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +int main() { + time_t t = time(NULL); + fprintf(stderr, "Time: %s\n", ctime(&t)); // NOLINT + // CHECK: {{Time: .* .* .*}} + return 0; +} diff --git a/lib/asan/lit_tests/Linux/zero-base-shadow.cc b/lib/asan/lit_tests/Linux/zero-base-shadow.cc new file mode 100644 index 000000000000..682e7e8d7e59 --- /dev/null +++ b/lib/asan/lit_tests/Linux/zero-base-shadow.cc @@ -0,0 +1,31 @@ +// RUN: %clangxx_asan -m64 -O0 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-64 < %t.out +// RUN: %clangxx_asan -m64 -O1 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-64 < %t.out +// RUN: %clangxx_asan -m64 -O2 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-64 < %t.out +// RUN: %clangxx_asan -m32 -O0 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-32 < %t.out +// RUN: %clangxx_asan -m32 -O1 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-32 < %t.out +// RUN: %clangxx_asan -m32 -O2 -fsanitize-address-zero-base-shadow -fPIE -pie %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-32 < %t.out + +// Zero-base shadow only works on x86_64 and i386. +// REQUIRES: x86_64-supported-target,i386-supported-target + +#include <string.h> +int main(int argc, char **argv) { + char x[10]; + memset(x, 0, 10); + int res = x[argc * 10]; // BOOOM + // CHECK: {{READ of size 1 at 0x.* thread T0}} + // CHECK: {{ #0 0x.* in _?main .*zero-base-shadow.cc:}}[[@LINE-2]] + // CHECK: {{Address 0x.* is .* frame}} + // CHECK: main + + // Check that shadow for stack memory occupies lower part of address space. + // CHECK-64: =>0x0f + // CHECK-32: =>0x1 + return res; +} diff --git a/lib/asan/lit_tests/SharedLibs/darwin-dummy-shared-lib-so.cc b/lib/asan/lit_tests/SharedLibs/darwin-dummy-shared-lib-so.cc new file mode 100644 index 000000000000..5d939991476e --- /dev/null +++ b/lib/asan/lit_tests/SharedLibs/darwin-dummy-shared-lib-so.cc @@ -0,0 +1,13 @@ +//===----------- darwin-dummy-shared-lib-so.cc ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +//===----------------------------------------------------------------------===// +void foo() {} diff --git a/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc b/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc new file mode 100644 index 000000000000..20ef2d8a00bb --- /dev/null +++ b/lib/asan/lit_tests/SharedLibs/init-order-dlopen-so.cc @@ -0,0 +1,12 @@ +#include <stdio.h> +#include <unistd.h> + +void inc_global(); + +int slow_init() { + sleep(1); + inc_global(); + return 42; +} + +int slowly_init_glob = slow_init(); diff --git a/lib/asan/lit_tests/Unit/lit.cfg b/lib/asan/lit_tests/Unit/lit.cfg index 243eb7fbeec0..e24361b014e9 100644 --- a/lib/asan/lit_tests/Unit/lit.cfg +++ b/lib/asan/lit_tests/Unit/lit.cfg @@ -11,9 +11,8 @@ def get_required_attr(config, attr_name): return attr_value # Setup attributes common for all compiler-rt projects. -llvm_src_root = get_required_attr(config, 'llvm_src_root') -compiler_rt_lit_unit_cfg = os.path.join(llvm_src_root, "projects", - "compiler-rt", "lib", +compiler_rt_src_root = get_required_attr(config, 'compiler_rt_src_root') +compiler_rt_lit_unit_cfg = os.path.join(compiler_rt_src_root, "lib", "lit.common.unit.cfg") lit.load_config(config, compiler_rt_lit_unit_cfg) diff --git a/lib/asan/lit_tests/Unit/lit.site.cfg.in b/lib/asan/lit_tests/Unit/lit.site.cfg.in index 401c3a8cc2eb..315d24d1ed09 100644 --- a/lib/asan/lit_tests/Unit/lit.site.cfg.in +++ b/lib/asan/lit_tests/Unit/lit.site.cfg.in @@ -3,8 +3,15 @@ config.target_triple = "@TARGET_TRIPLE@" config.llvm_src_root = "@LLVM_SOURCE_DIR@" -config.build_type = "@CMAKE_BUILD_TYPE@" +config.compiler_rt_src_root = "@COMPILER_RT_SOURCE_DIR@" +config.llvm_build_mode = "@LLVM_BUILD_MODE@" config.asan_binary_dir = "@ASAN_BINARY_DIR@" +try: + config.llvm_build_mode = config.llvm_build_mode % lit.params +except KeyError,e: + key, = e.args + lit.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key, key)) + # Let the main config do the real work. lit.load_config(config, "@ASAN_SOURCE_DIR@/lit_tests/Unit/lit.cfg") diff --git a/lib/asan/lit_tests/allow_user_segv.cc b/lib/asan/lit_tests/allow_user_segv.cc new file mode 100644 index 000000000000..f8aed0d4ca80 --- /dev/null +++ b/lib/asan/lit_tests/allow_user_segv.cc @@ -0,0 +1,50 @@ +// Regression test for +// https://code.google.com/p/address-sanitizer/issues/detail?id=180 + +// RUN: %clangxx_asan -m64 -O0 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -m64 -O2 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -m32 -O0 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -m32 -O2 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true %t 2>&1 | FileCheck %s + +#include <signal.h> +#include <stdio.h> + +struct sigaction user_sigaction; +struct sigaction original_sigaction; + +void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) { + fprintf(stderr, "User sigaction called\n"); + if (original_sigaction.sa_flags | SA_SIGINFO) + original_sigaction.sa_sigaction(signum, siginfo, context); + else + original_sigaction.sa_handler(signum); +} + +int DoSEGV() { + volatile int *x = 0; + return *x; +} + +int main() { + user_sigaction.sa_sigaction = User_OnSIGSEGV; + user_sigaction.sa_flags = SA_SIGINFO; +#if defined(__APPLE__) && !defined(__LP64__) + // On 32-bit Darwin KERN_PROTECTION_FAILURE (SIGBUS) is delivered. + int signum = SIGBUS; +#else + // On 64-bit Darwin KERN_INVALID_ADDRESS (SIGSEGV) is delivered. + // On Linux SIGSEGV is delivered as well. + int signum = SIGSEGV; +#endif + if (sigaction(signum, &user_sigaction, &original_sigaction)) { + perror("sigaction"); + return 1; + } + fprintf(stderr, "User sigaction installed\n"); + return DoSEGV(); +} + +// CHECK: User sigaction installed +// CHECK-NEXT: User sigaction called +// CHECK-NEXT: ASAN:SIGSEGV +// CHECK: AddressSanitizer: SEGV on unknown address diff --git a/lib/asan/lit_tests/default_blacklist.cc b/lib/asan/lit_tests/default_blacklist.cc new file mode 100644 index 000000000000..25a1ae1752b0 --- /dev/null +++ b/lib/asan/lit_tests/default_blacklist.cc @@ -0,0 +1,3 @@ +// Test that ASan uses the default blacklist from resource directory. +// RUN: %clangxx_asan -### %s 2>&1 | FileCheck %s +// CHECK: fsanitize-blacklist={{.*}}asan_blacklist.txt diff --git a/lib/asan/lit_tests/default_options.cc b/lib/asan/lit_tests/default_options.cc index 950a7d879194..84b80557b852 100644 --- a/lib/asan/lit_tests/default_options.cc +++ b/lib/asan/lit_tests/default_options.cc @@ -4,7 +4,7 @@ const char *kAsanDefaultOptions="verbosity=1 foo=bar"; extern "C" -__attribute__((no_address_safety_analysis)) +__attribute__((no_sanitize_address)) const char *__asan_default_options() { // CHECK: Using the defaults from __asan_default_options: {{.*}} foo=bar return kAsanDefaultOptions; diff --git a/lib/asan/lit_tests/dlclose-test.cc b/lib/asan/lit_tests/dlclose-test.cc index 229f508294bf..b15895bf3579 100644 --- a/lib/asan/lit_tests/dlclose-test.cc +++ b/lib/asan/lit_tests/dlclose-test.cc @@ -9,6 +9,11 @@ // are globals. // 6. BOOM +// This sublte test assumes that after a foo.so is dlclose-d +// we can mmap the region of memory that has been occupied by the library. +// It works on i368/x86_64 Linux, but not necessary anywhere else. +// REQUIRES: x86_64-supported-target,i386-supported-target + // RUN: %clangxx_asan -m64 -O0 %p/SharedLibs/dlclose-test-so.cc \ // RUN: -fPIC -shared -o %t-so.so // RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | FileCheck %s @@ -39,17 +44,17 @@ #include <stdio.h> #include <string.h> #include <sys/mman.h> +#include <unistd.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"; + size_t PageSize = sysconf(_SC_PAGESIZE); printf("opening %s ... \n", path.c_str()); void *lib = dlopen(path.c_str(), RTLD_NOW); if (!lib) { @@ -73,8 +78,8 @@ int main(int argc, char *argv[]) { 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, + size_t page_beg = ((size_t)addr) & ~(PageSize - 1); + void *res = mmap((void*)(page_beg), PageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 0, 0); if (res == (char*)-1L) { diff --git a/lib/asan/lit_tests/double-free.cc b/lib/asan/lit_tests/double-free.cc new file mode 100644 index 000000000000..9e201117c563 --- /dev/null +++ b/lib/asan/lit_tests/double-free.cc @@ -0,0 +1,18 @@ +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +#include <stdlib.h> +#include <string.h> +int main(int argc, char **argv) { + char *x = (char*)malloc(10 * sizeof(char)); + memset(x, 0, 10); + int res = x[argc]; + free(x); + free(x + argc - 1); // BOOM + // CHECK: AddressSanitizer: attempting double-free{{.*}}in thread T0 + // CHECK: double-free.cc:[[@LINE-2]] + // CHECK: freed by thread T0 here: + // CHECK: double-free.cc:[[@LINE-5]] + // CHECK: allocated by thread T0 here: + // CHECK: double-free.cc:[[@LINE-10]] + return res; +} diff --git a/lib/asan/lit_tests/global-demangle.cc b/lib/asan/lit_tests/global-demangle.cc new file mode 100644 index 000000000000..5696a38a7705 --- /dev/null +++ b/lib/asan/lit_tests/global-demangle.cc @@ -0,0 +1,18 @@ +// Don't run through %symbolize to avoid c++filt demangling. +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | FileCheck %s + +namespace XXX { +class YYY { + public: + static char ZZZ[]; +}; +char YYY::ZZZ[] = "abc"; +} + +int main(int argc, char **argv) { + return (int)XXX::YYY::ZZZ[argc + 5]; // BOOM + // CHECK: {{READ of size 1 at 0x.*}} + // CHECK: {{0x.* is located 2 bytes to the right of global variable}} + // CHECK: 'XXX::YYY::ZZZ' {{.*}} of size 4 + // CHECK: 'XXX::YYY::ZZZ' is ascii string 'abc' +} diff --git a/lib/asan/lit_tests/heap-overflow.cc b/lib/asan/lit_tests/heap-overflow.cc index 2648ec7e5f1f..f1d719cd0b20 100644 --- a/lib/asan/lit_tests/heap-overflow.cc +++ b/lib/asan/lit_tests/heap-overflow.cc @@ -29,10 +29,8 @@ int main(int argc, char **argv) { // CHECK-Linux: {{ #0 0x.* in .*malloc}} // CHECK-Linux: {{ #1 0x.* in main .*heap-overflow.cc:21}} - // CHECK-Darwin: {{ #0 0x.* in .*mz_malloc.*}} - // CHECK-Darwin: {{ #1 0x.* in malloc_zone_malloc.*}} - // CHECK-Darwin: {{ #2 0x.* in malloc.*}} - // CHECK-Darwin: {{ #3 0x.* in _?main .*heap-overflow.cc:21}} + // CHECK-Darwin: {{ #0 0x.* in _?wrap_malloc.*}} + // CHECK-Darwin: {{ #1 0x.* in _?main .*heap-overflow.cc:21}} free(x); return res; } diff --git a/lib/asan/lit_tests/huge_negative_hea_oob.cc b/lib/asan/lit_tests/huge_negative_hea_oob.cc new file mode 100644 index 000000000000..a09e3bf87d60 --- /dev/null +++ b/lib/asan/lit_tests/huge_negative_hea_oob.cc @@ -0,0 +1,13 @@ +// RUN: %clangxx_asan -m64 %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -m64 -O %s -o %t && %t 2>&1 | FileCheck %s +// Check that we can find huge buffer overflows to the left. +#include <stdlib.h> +#include <string.h> +int main(int argc, char **argv) { + char *x = (char*)malloc(1 << 20); + memset(x, 0, 10); + int res = x[-argc * 4000]; // BOOOM + // CHECK: is located 4000 bytes to the left of + free(x); + return res; +} diff --git a/lib/asan/lit_tests/init-order-atexit.cc b/lib/asan/lit_tests/init-order-atexit.cc new file mode 100644 index 000000000000..45f4f17c0cb0 --- /dev/null +++ b/lib/asan/lit_tests/init-order-atexit.cc @@ -0,0 +1,31 @@ +// Test for the following situation: +// (1) global A is constructed. +// (2) exit() is called during construction of global B. +// (3) destructor of A reads uninitialized global C from another module. +// We do *not* want to report init-order bug in this case. + +// RUN: %clangxx_asan -m64 -O0 %s %p/Helpers/init-order-atexit-extra.cc -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true:strict_init_order=true %t 2>&1 | FileCheck %s + +#include <stdio.h> +#include <stdlib.h> + +void AccessC(); + +class A { + public: + A() { } + ~A() { AccessC(); printf("PASSED\n"); } + // CHECK-NOT: AddressSanitizer + // CHECK: PASSED +}; + +A a; + +class B { + public: + B() { exit(1); } + ~B() { } +}; + +B b; diff --git a/lib/asan/lit_tests/init-order-dlopen.cc b/lib/asan/lit_tests/init-order-dlopen.cc new file mode 100644 index 000000000000..228f44204c99 --- /dev/null +++ b/lib/asan/lit_tests/init-order-dlopen.cc @@ -0,0 +1,52 @@ +// Regression test for +// https://code.google.com/p/address-sanitizer/issues/detail?id=178 + +// RUN: %clangxx_asan -m64 -O0 %p/SharedLibs/init-order-dlopen-so.cc \ +// RUN: -fPIC -shared -o %t-so.so +// If the linker doesn't support --export-dynamic (which is ELF-specific), +// try to link without that option. +// FIXME: find a better solution. +// RUN: %clangxx_asan -m64 -O0 %s -o %t -Wl,--export-dynamic || \ +// RUN: %clangxx_asan -m64 -O0 %s -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true:strict_init_order=true %t 2>&1 | FileCheck %s +#include <dlfcn.h> +#include <pthread.h> +#include <stdio.h> +#include <unistd.h> + +#include <string> + +using std::string; + +int foo() { + return 42; +} +int global = foo(); + +__attribute__((visibility("default"))) +void inc_global() { + global++; +} + +void *global_poller(void *arg) { + while (true) { + if (global != 42) + break; + usleep(100); + } + return 0; +} + +int main(int argc, char *argv[]) { + pthread_t p; + pthread_create(&p, 0, global_poller, 0); + string path = string(argv[0]) + "-so.so"; + if (0 == dlopen(path.c_str(), RTLD_NOW)) { + fprintf(stderr, "dlerror: %s\n", dlerror()); + return 1; + } + pthread_join(p, 0); + printf("PASSED\n"); + // CHECK: PASSED + return 0; +} diff --git a/lib/asan/lit_tests/initialization-blacklist.cc b/lib/asan/lit_tests/initialization-blacklist.cc index f8df24c68ea6..12fbc49ed91b 100644 --- a/lib/asan/lit_tests/initialization-blacklist.cc +++ b/lib/asan/lit_tests/initialization-blacklist.cc @@ -1,23 +1,35 @@ // Test for blacklist functionality of initialization-order checker. // RUN: %clangxx_asan -m64 -O0 %s %p/Helpers/initialization-blacklist-extra.cc\ +// RUN: %p/Helpers/initialization-blacklist-extra2.cc \ // RUN: -fsanitize-blacklist=%p/Helpers/initialization-blacklist.txt \ -// RUN: -fsanitize=init-order -o %t && %t 2>&1 +// RUN: -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 // RUN: %clangxx_asan -m64 -O1 %s %p/Helpers/initialization-blacklist-extra.cc\ +// RUN: %p/Helpers/initialization-blacklist-extra2.cc \ // RUN: -fsanitize-blacklist=%p/Helpers/initialization-blacklist.txt \ -// RUN: -fsanitize=init-order -o %t && %t 2>&1 +// RUN: -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 // RUN: %clangxx_asan -m64 -O2 %s %p/Helpers/initialization-blacklist-extra.cc\ +// RUN: %p/Helpers/initialization-blacklist-extra2.cc \ // RUN: -fsanitize-blacklist=%p/Helpers/initialization-blacklist.txt \ -// RUN: -fsanitize=init-order -o %t && %t 2>&1 +// RUN: -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 // RUN: %clangxx_asan -m32 -O0 %s %p/Helpers/initialization-blacklist-extra.cc\ +// RUN: %p/Helpers/initialization-blacklist-extra2.cc \ // RUN: -fsanitize-blacklist=%p/Helpers/initialization-blacklist.txt \ -// RUN: -fsanitize=init-order -o %t && %t 2>&1 +// RUN: -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 // RUN: %clangxx_asan -m32 -O1 %s %p/Helpers/initialization-blacklist-extra.cc\ +// RUN: %p/Helpers/initialization-blacklist-extra2.cc \ // RUN: -fsanitize-blacklist=%p/Helpers/initialization-blacklist.txt \ -// RUN: -fsanitize=init-order -o %t && %t 2>&1 +// RUN: -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 // RUN: %clangxx_asan -m32 -O2 %s %p/Helpers/initialization-blacklist-extra.cc\ +// RUN: %p/Helpers/initialization-blacklist-extra2.cc \ // RUN: -fsanitize-blacklist=%p/Helpers/initialization-blacklist.txt \ -// RUN: -fsanitize=init-order -o %t && %t 2>&1 +// RUN: -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 // Function is defined in another TU. int readBadGlobal(); @@ -27,6 +39,9 @@ int x = readBadGlobal(); // init-order bug. int accessBadObject(); int y = accessBadObject(); // init-order bug. +int readBadSrcGlobal(); +int z = readBadSrcGlobal(); // init-order bug. + int main(int argc, char **argv) { - return argc + x + y - 1; + return argc + x + y + z - 1; } diff --git a/lib/asan/lit_tests/initialization-bug.cc b/lib/asan/lit_tests/initialization-bug.cc index 8f4e33ef5a35..ee2c725f0b13 100644 --- a/lib/asan/lit_tests/initialization-bug.cc +++ b/lib/asan/lit_tests/initialization-bug.cc @@ -1,14 +1,17 @@ // Test to make sure basic initialization order errors are caught. -// RUN: %clangxx_asan -m64 -O0 %s %p/Helpers/initialization-bug-extra2.cc\ -// RUN: -fsanitize=init-order -o %t && %t 2>&1 \ +// RUN: %clangxx_asan -m64 -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 \ // RUN: | %symbolize | FileCheck %s -// RUN: %clangxx_asan -m32 -O0 %s %p/Helpers/initialization-bug-extra2.cc\ -// RUN: -fsanitize=init-order -o %t && %t 2>&1 \ +// RUN: %clangxx_asan -m32 -O0 %s %p/Helpers/initialization-bug-extra2.cc -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 \ // RUN: | %symbolize | FileCheck %s // Do not test with optimization -- the error may be optimized away. +// FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=186 +// XFAIL: darwin + #include <cstdio> // The structure of the test is: diff --git a/lib/asan/lit_tests/initialization-constexpr.cc b/lib/asan/lit_tests/initialization-constexpr.cc new file mode 100644 index 000000000000..ba5410674f76 --- /dev/null +++ b/lib/asan/lit_tests/initialization-constexpr.cc @@ -0,0 +1,43 @@ +// Constexpr: +// We need to check that a global variable initialized with a constexpr +// constructor can be accessed during dynamic initialization (as a constexpr +// constructor implies that it was initialized during constant initialization, +// not dynamic initialization). + +// RUN: %clangxx_asan -m64 -O0 %s %p/Helpers/initialization-constexpr-extra.cc\ +// RUN: --std=c++11 -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m64 -O1 %s %p/Helpers/initialization-constexpr-extra.cc\ +// RUN: --std=c++11 -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m64 -O2 %s %p/Helpers/initialization-constexpr-extra.cc\ +// RUN: --std=c++11 -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m64 -O3 %s %p/Helpers/initialization-constexpr-extra.cc\ +// RUN: --std=c++11 -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m32 -O0 %s %p/Helpers/initialization-constexpr-extra.cc\ +// RUN: --std=c++11 -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m32 -O1 %s %p/Helpers/initialization-constexpr-extra.cc\ +// RUN: --std=c++11 -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m32 -O2 %s %p/Helpers/initialization-constexpr-extra.cc\ +// RUN: --std=c++11 -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m32 -O3 %s %p/Helpers/initialization-constexpr-extra.cc\ +// RUN: --std=c++11 -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 + +class Integer { + private: + int value; + + public: + constexpr Integer(int x = 0) : value(x) {} + int getValue() {return value;} +}; +Integer coolestInteger(42); +int getCoolestInteger() { return coolestInteger.getValue(); } + +int main() { return 0; } diff --git a/lib/asan/lit_tests/initialization-nobug.cc b/lib/asan/lit_tests/initialization-nobug.cc index 1b8961606811..407226e29a1b 100644 --- a/lib/asan/lit_tests/initialization-nobug.cc +++ b/lib/asan/lit_tests/initialization-nobug.cc @@ -1,24 +1,22 @@ // A collection of various initializers which shouldn't trip up initialization // order checking. If successful, this will just return 0. -// RUN: %clangxx_asan -m64 -O0 %s %p/Helpers/initialization-nobug-extra.cc\ -// RUN: --std=c++11 -fsanitize=init-order -o %t && %t 2>&1 -// RUN: %clangxx_asan -m64 -O1 %s %p/Helpers/initialization-nobug-extra.cc\ -// RUN: --std=c++11 -fsanitize=init-order -o %t && %t 2>&1 -// RUN: %clangxx_asan -m64 -O2 %s %p/Helpers/initialization-nobug-extra.cc\ -// RUN: --std=c++11 -fsanitize=init-order -o %t && %t 2>&1 -// RUN: %clangxx_asan -m64 -O3 %s %p/Helpers/initialization-nobug-extra.cc\ -// RUN: --std=c++11 -fsanitize=init-order -o %t && %t 2>&1 -// RUN: %clangxx_asan -m32 -O0 %s %p/Helpers/initialization-nobug-extra.cc\ -// RUN: --std=c++11 -fsanitize=init-order -o %t && %t 2>&1 -// RUN: %clangxx_asan -m32 -O0 %s %p/Helpers/initialization-nobug-extra.cc\ -// RUN: --std=c++11 -fsanitize=init-order -o %t && %t 2>&1 -// RUN: %clangxx_asan -m32 -O1 %s %p/Helpers/initialization-nobug-extra.cc\ -// RUN: --std=c++11 -fsanitize=init-order -o %t && %t 2>&1 -// RUN: %clangxx_asan -m32 -O2 %s %p/Helpers/initialization-nobug-extra.cc\ -// RUN: --std=c++11 -fsanitize=init-order -o %t && %t 2>&1 -// RUN: %clangxx_asan -m32 -O3 %s %p/Helpers/initialization-nobug-extra.cc\ -// RUN: --std=c++11 -fsanitize=init-order -o %t && %t 2>&1 +// RUN: %clangxx_asan -m64 -O0 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m64 -O1 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m64 -O2 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m64 -O3 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m32 -O0 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m32 -O1 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m32 -O2 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 +// RUN: %clangxx_asan -m32 -O3 %s %p/Helpers/initialization-nobug-extra.cc -fsanitize=init-order -o %t +// RUN: ASAN_OPTIONS=check_initialization_order=true %t 2>&1 // Simple access: // Make sure that accessing a global in the same TU is safe @@ -47,21 +45,12 @@ int countCalls() { 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: +// Trivial constructor, non-trivial destructor. +struct StructWithDtor { + ~StructWithDtor() { } int value; - - public: - constexpr Integer(int x = 0) : value(x) {} - int getValue() {return value;} }; -Integer coolestInteger(42); -int getCoolestInteger() { return coolestInteger.getValue(); } +StructWithDtor struct_with_dtor; +int getStructWithDtorValue() { return struct_with_dtor.value; } int main() { return 0; } diff --git a/lib/asan/lit_tests/interface_test.cc b/lib/asan/lit_tests/interface_test.cc new file mode 100644 index 000000000000..428a109fe70d --- /dev/null +++ b/lib/asan/lit_tests/interface_test.cc @@ -0,0 +1,8 @@ +// Check that user may include ASan interface header. +// RUN: %clang -fsanitize=address -I %p/../../../include %s -o %t && %t +// RUN: %clang -I %p/../../../include %s -o %t && %t +#include <sanitizer/asan_interface.h> + +int main() { + return 0; +} diff --git a/lib/asan/lit_tests/invalid-free.cc b/lib/asan/lit_tests/invalid-free.cc new file mode 100644 index 000000000000..0ef064056b63 --- /dev/null +++ b/lib/asan/lit_tests/invalid-free.cc @@ -0,0 +1,16 @@ +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +#include <stdlib.h> +#include <string.h> +int main(int argc, char **argv) { + char *x = (char*)malloc(10 * sizeof(char)); + memset(x, 0, 10); + int res = x[argc]; + free(x + 5); // BOOM + // CHECK: AddressSanitizer: attempting free on address{{.*}}in thread T0 + // CHECK: invalid-free.cc:[[@LINE-2]] + // CHECK: is located 5 bytes inside of 10-byte region + // CHECK: allocated by thread T0 here: + // CHECK: invalid-free.cc:[[@LINE-8]] + return res; +} diff --git a/lib/asan/lit_tests/large_func_test.cc b/lib/asan/lit_tests/large_func_test.cc index a74828811f74..ceecc29b7b0a 100644 --- a/lib/asan/lit_tests/large_func_test.cc +++ b/lib/asan/lit_tests/large_func_test.cc @@ -32,7 +32,7 @@ static void LargeFunction(int *x, int zero) { // CHECK: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}} // CHECK: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}} // CHECK: {{READ of size 4 at 0x.* thread T0}} - x[zero + 111]++; // we should report this exact line + x[zero + 103]++; // we should report this exact line // atos incorrectly extracts the symbol name for the static functions on // Darwin. // CHECK-Linux: {{#0 0x.* in LargeFunction.*large_func_test.cc:}}[[@LINE-3]] @@ -54,9 +54,10 @@ int main(int argc, char **argv) { int *x = new int[100]; LargeFunction(x, argc - 1); // CHECK: {{ #1 0x.* in _?main .*large_func_test.cc:}}[[@LINE-1]] - // CHECK: {{0x.* is located 44 bytes to the right of 400-byte region}} + // CHECK: {{0x.* is located 12 bytes to the right of 400-byte region}} // CHECK: {{allocated by thread T0 here:}} - // CHECK: {{ #0 0x.* in operator new.*}} - // CHECK: {{ #1 0x.* in _?main .*large_func_test.cc:}}[[@LINE-6]] + // CHECK-Linux: {{ #0 0x.* in operator new.*}} + // CHECK-Darwin: {{ #0 0x.* in .*_Zna.*}} + // CHECK: {{ #1 0x.* in _?main .*large_func_test.cc:}}[[@LINE-7]] delete x; } diff --git a/lib/asan/lit_tests/lit.cfg b/lib/asan/lit_tests/lit.cfg index 7875281b1f2f..5daecd9e557d 100644 --- a/lib/asan/lit_tests/lit.cfg +++ b/lib/asan/lit_tests/lit.cfg @@ -2,6 +2,14 @@ import os +def get_required_attr(config, attr_name): + attr_value = getattr(config, attr_name, None) + if not attr_value: + lit.fatal("No attribute %r in test configuration! You may need to run " + "tests from your build directory or add this attribute " + "to lit.site.cfg " % attr_name) + return attr_value + # Setup config name. config.name = 'AddressSanitizer' @@ -30,14 +38,6 @@ if llvm_src_root is None: if not llvm_config: DisplayNoConfigMessage() - # Validate that llvm-config points to the same source tree. - llvm_src_root = lit.util.capture(["llvm-config", "--src-root"]).strip() - asan_test_src_root = os.path.join(llvm_src_root, "projects", "compiler-rt", - "lib", "asan", "lit_tests") - if (os.path.realpath(asan_test_src_root) != - os.path.realpath(config.test_source_root)): - DisplayNoConfigMessage() - # Find out the presumed location of generated site config. llvm_obj_root = lit.util.capture(["llvm-config", "--obj-root"]).strip() asan_site_cfg = os.path.join(llvm_obj_root, "projects", "compiler-rt", @@ -49,8 +49,9 @@ if llvm_src_root is None: raise SystemExit # Setup attributes common for all compiler-rt projects. -compiler_rt_lit_cfg = os.path.join(llvm_src_root, "projects", "compiler-rt", - "lib", "lit.common.cfg") +compiler_rt_src_root = get_required_attr(config, "compiler_rt_src_root") +compiler_rt_lit_cfg = os.path.join(compiler_rt_src_root, "lib", + "lit.common.cfg") if (not compiler_rt_lit_cfg) or (not os.path.exists(compiler_rt_lit_cfg)): lit.fatal("Can't find common compiler-rt lit config at: %r" % compiler_rt_lit_cfg) diff --git a/lib/asan/lit_tests/lit.site.cfg.in b/lib/asan/lit_tests/lit.site.cfg.in index cf439309c6ad..08546cdabe02 100644 --- a/lib/asan/lit_tests/lit.site.cfg.in +++ b/lib/asan/lit_tests/lit.site.cfg.in @@ -5,8 +5,10 @@ config.target_triple = "@TARGET_TRIPLE@" config.host_os = "@HOST_OS@" config.llvm_src_root = "@LLVM_SOURCE_DIR@" config.llvm_obj_root = "@LLVM_BINARY_DIR@" +config.compiler_rt_src_root = "@COMPILER_RT_SOURCE_DIR@" config.llvm_tools_dir = "@LLVM_TOOLS_DIR@" config.clang = "@LLVM_BINARY_DIR@/bin/clang" +config.compiler_rt_arch = "@COMPILER_RT_SUPPORTED_ARCH@" # LLVM tools dir can be passed in lit parameters, so try to # apply substitution. diff --git a/lib/asan/lit_tests/log_path_fork_test.cc b/lib/asan/lit_tests/log_path_fork_test.cc.disabled index c6c1b49e994d..c6c1b49e994d 100644 --- a/lib/asan/lit_tests/log_path_fork_test.cc +++ b/lib/asan/lit_tests/log_path_fork_test.cc.disabled diff --git a/lib/asan/lit_tests/malloc_fill.cc b/lib/asan/lit_tests/malloc_fill.cc new file mode 100644 index 000000000000..c23516b33299 --- /dev/null +++ b/lib/asan/lit_tests/malloc_fill.cc @@ -0,0 +1,22 @@ +// Check that we fill malloc-ed memory correctly. +// RUN: %clangxx_asan -m64 %s -o %t +// RUN: %t | FileCheck %s +// RUN: ASAN_OPTIONS=max_malloc_fill_size=10:malloc_fill_byte=8 %t | FileCheck %s --check-prefix=CHECK-10-8 +// RUN: ASAN_OPTIONS=max_malloc_fill_size=20:malloc_fill_byte=171 %t | FileCheck %s --check-prefix=CHECK-20-ab + +#include <stdio.h> +int main(int argc, char **argv) { + // With asan allocator this makes sure we get memory from mmap. + static const int kSize = 1 << 25; + unsigned char *x = new unsigned char[kSize]; + printf("-"); + for (int i = 0; i <= 32; i++) { + printf("%02x", x[i]); + } + printf("-\n"); + delete [] x; +} + +// CHECK: -bebebebebebebebebebebebebebebebebebebebebebebebebebebebebebebebebe- +// CHECK-10-8: -080808080808080808080000000000000000000000000000000000000000000000- +// CHECK-20-ab: -abababababababababababababababababababab00000000000000000000000000- diff --git a/lib/asan/lit_tests/memcmp_strict_test.cc b/lib/asan/lit_tests/memcmp_strict_test.cc new file mode 100644 index 000000000000..00bf921c744a --- /dev/null +++ b/lib/asan/lit_tests/memcmp_strict_test.cc @@ -0,0 +1,16 @@ +// RUN: %clangxx_asan -m64 -O0 %s -o %t && ASAN_OPTIONS=strict_memcmp=0 %t 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK-nonstrict +// RUN: %clangxx_asan -m64 -O0 %s -o %t && ASAN_OPTIONS=strict_memcmp=1 %t 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK-strict +// Default to strict_memcmp=1. +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK-strict + +#include <stdio.h> +#include <string.h> +int main() { + char kFoo[] = "foo"; + char kFubar[] = "fubar"; + int res = memcmp(kFoo, kFubar, strlen(kFubar)); + printf("res: %d\n", res); + // CHECK-nonstrict: {{res: -1}} + // CHECK-strict: AddressSanitizer: stack-buffer-overflow + return 0; +} diff --git a/lib/asan/lit_tests/partial_right.cc b/lib/asan/lit_tests/partial_right.cc new file mode 100644 index 000000000000..c579262726f9 --- /dev/null +++ b/lib/asan/lit_tests/partial_right.cc @@ -0,0 +1,17 @@ +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m64 -O1 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m64 -O2 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m64 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m32 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m32 -O1 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m32 -O2 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -m32 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +#include <stdlib.h> +int main(int argc, char **argv) { + volatile int *x = (int*)malloc(2*sizeof(int) + 2); + int res = x[2]; // BOOOM + // CHECK: {{READ of size 4 at 0x.* thread T0}} + // CHECK: [[ADDR:0x[01-9a-fa-f]+]] is located 0 bytes to the right of {{.*}}-byte region [{{.*}},{{.*}}[[ADDR]]) + return res; +} diff --git a/lib/asan/lit_tests/stack-frame-demangle.cc b/lib/asan/lit_tests/stack-frame-demangle.cc index 7f4d59fc5838..bb8de16b2b8a 100644 --- a/lib/asan/lit_tests/stack-frame-demangle.cc +++ b/lib/asan/lit_tests/stack-frame-demangle.cc @@ -1,7 +1,4 @@ -// Check that ASan is able to print demangled frame name even w/o -// symbolization. - -// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s #include <string.h> @@ -11,12 +8,13 @@ struct YYY { char array[10]; memset(array, 0, 10); return array[x]; // BOOOM - // CHECK: {{ERROR: AddressSanitizer: stack-buffer-overflow}} - // CHECK: {{READ of size 1 at 0x.* thread T0}} - // CHECK: {{Address 0x.* is .* frame <XXX::YYY::ZZZ(.*)>}} + // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow + // CHECK: READ of size 1 at + // CHECK: is located in stack of thread T0 at offset + // CHECK: XXX::YYY::ZZZ } }; -}; +} // namespace XXX int main(int argc, char **argv) { int res = XXX::YYY::ZZZ(argc + 10); diff --git a/lib/asan/lit_tests/stack-oob-frames.cc b/lib/asan/lit_tests/stack-oob-frames.cc new file mode 100644 index 000000000000..0395522252e8 --- /dev/null +++ b/lib/asan/lit_tests/stack-oob-frames.cc @@ -0,0 +1,59 @@ +// RUN: %clangxx_asan -m64 -O1 %s -o %t +// RUN: %t 0 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK0 +// RUN: %t 1 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK1 +// RUN: %t 2 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK2 +// RUN: %t 3 2>&1 | %symbolize | FileCheck %s --check-prefix=CHECK3 + +#define NOINLINE __attribute__((noinline)) +inline void break_optimization(void *arg) { + __asm__ __volatile__("" : : "r" (arg) : "memory"); +} + +NOINLINE static void Frame0(int frame, char *a, char *b, char *c) { + char s[4] = {0}; + char *d = s; + break_optimization(&d); + switch (frame) { + case 3: a[5]++; break; + case 2: b[5]++; break; + case 1: c[5]++; break; + case 0: d[5]++; break; + } +} +NOINLINE static void Frame1(int frame, char *a, char *b) { + char c[4] = {0}; Frame0(frame, a, b, c); + break_optimization(0); +} +NOINLINE static void Frame2(int frame, char *a) { + char b[4] = {0}; Frame1(frame, a, b); + break_optimization(0); +} +NOINLINE static void Frame3(int frame) { + char a[4] = {0}; Frame2(frame, a); + break_optimization(0); +} + +int main(int argc, char **argv) { + if (argc != 2) return 1; + Frame3(argv[1][0] - '0'); +} + +// CHECK0: AddressSanitizer: stack-buffer-overflow +// CHECK0: #0{{.*}}Frame0 +// CHECK0: #1{{.*}}Frame1 +// CHECK0: #2{{.*}}Frame2 +// CHECK0: #3{{.*}}Frame3 +// CHECK0: is located in stack of thread T0 at offset +// CHECK0-NEXT: #0{{.*}}Frame0 +// +// CHECK1: AddressSanitizer: stack-buffer-overflow +// CHECK1: is located in stack of thread T0 at offset +// CHECK1-NEXT: #0{{.*}}Frame1 +// +// CHECK2: AddressSanitizer: stack-buffer-overflow +// CHECK2: is located in stack of thread T0 at offset +// CHECK2-NEXT: #0{{.*}}Frame2 +// +// CHECK3: AddressSanitizer: stack-buffer-overflow +// CHECK3: is located in stack of thread T0 at offset +// CHECK3-NEXT: #0{{.*}}Frame3 diff --git a/lib/asan/lit_tests/stack-overflow.cc b/lib/asan/lit_tests/stack-overflow.cc index 3deb1e91de6c..25ea43af48a4 100644 --- a/lib/asan/lit_tests/stack-overflow.cc +++ b/lib/asan/lit_tests/stack-overflow.cc @@ -14,6 +14,7 @@ int main(int argc, char **argv) { int res = x[argc * 10]; // BOOOM // CHECK: {{READ of size 1 at 0x.* thread T0}} // CHECK: {{ #0 0x.* in _?main .*stack-overflow.cc:}}[[@LINE-2]] - // CHECK: {{Address 0x.* is .* frame <main>}} + // CHECK: {{Address 0x.* is located in stack of thread T0 at offset}} + // CHECK-NEXT: in{{.*}}main{{.*}}stack-overflow.cc return res; } diff --git a/lib/asan/lit_tests/strncpy-overflow.cc b/lib/asan/lit_tests/strncpy-overflow.cc index 18711843c4c8..5133b5c1653e 100644 --- a/lib/asan/lit_tests/strncpy-overflow.cc +++ b/lib/asan/lit_tests/strncpy-overflow.cc @@ -22,7 +22,7 @@ int main(int argc, char **argv) { strcpy(hello, "hello"); char *short_buffer = (char*)malloc(9); strncpy(short_buffer, hello, 10); // BOOM - // CHECK: {{WRITE of size 1 at 0x.* thread T0}} + // CHECK: {{WRITE of size 10 at 0x.* thread T0}} // CHECK-Linux: {{ #0 0x.* in .*strncpy}} // CHECK-Darwin: {{ #0 0x.* in _?wrap_strncpy}} // CHECK: {{ #1 0x.* in _?main .*strncpy-overflow.cc:}}[[@LINE-4]] @@ -32,9 +32,7 @@ int main(int argc, char **argv) { // CHECK-Linux: {{ #0 0x.* in .*malloc}} // CHECK-Linux: {{ #1 0x.* in main .*strncpy-overflow.cc:}}[[@LINE-10]] - // CHECK-Darwin: {{ #0 0x.* in .*mz_malloc.*}} - // CHECK-Darwin: {{ #1 0x.* in malloc_zone_malloc.*}} - // CHECK-Darwin: {{ #2 0x.* in malloc.*}} - // CHECK-Darwin: {{ #3 0x.* in _?main .*strncpy-overflow.cc:}}[[@LINE-15]] + // CHECK-Darwin: {{ #0 0x.* in _?wrap_malloc.*}} + // CHECK-Darwin: {{ #1 0x.* in _?main .*strncpy-overflow.cc:}}[[@LINE-13]] return short_buffer[8]; } diff --git a/lib/asan/lit_tests/throw_call_test.cc b/lib/asan/lit_tests/throw_call_test.cc new file mode 100644 index 000000000000..974bc51d97c5 --- /dev/null +++ b/lib/asan/lit_tests/throw_call_test.cc @@ -0,0 +1,45 @@ +// RUN: %clangxx_asan %s -o %t && %t +// http://code.google.com/p/address-sanitizer/issues/detail?id=147 (not fixed). +// BROKEN: %clangxx_asan %s -o %t -static-libstdc++ && %t +#include <stdio.h> +static volatile int zero = 0; +inline void pretend_to_do_something(void *x) { + __asm__ __volatile__("" : : "r" (x) : "memory"); +} + +__attribute__((noinline, no_sanitize_address)) +void ReallyThrow() { + fprintf(stderr, "ReallyThrow\n"); + if (zero == 0) + throw 42; +} + +__attribute__((noinline)) +void Throw() { + int a, b, c, d, e; + pretend_to_do_something(&a); + pretend_to_do_something(&b); + pretend_to_do_something(&c); + pretend_to_do_something(&d); + pretend_to_do_something(&e); + fprintf(stderr, "Throw stack = %p\n", &a); + ReallyThrow(); +} + +__attribute__((noinline)) +void CheckStack() { + int ar[100]; + pretend_to_do_something(ar); + for (int i = 0; i < 100; i++) + ar[i] = i; + fprintf(stderr, "CheckStack stack = %p, %p\n", ar, ar + 100); +} + +int main(int argc, char** argv) { + try { + Throw(); + } catch(int a) { + fprintf(stderr, "a = %d\n", a); + } + CheckStack(); +} diff --git a/lib/asan/lit_tests/throw_invoke_test.cc b/lib/asan/lit_tests/throw_invoke_test.cc new file mode 100644 index 000000000000..077a940e8d19 --- /dev/null +++ b/lib/asan/lit_tests/throw_invoke_test.cc @@ -0,0 +1,50 @@ +// RUN: %clangxx_asan %s -o %t && %t +// RUN: %clangxx_asan %s -o %t -static-libstdc++ && %t +#include <stdio.h> +static volatile int zero = 0; +inline void pretend_to_do_something(void *x) { + __asm__ __volatile__("" : : "r" (x) : "memory"); +} + +__attribute__((noinline)) +void ReallyThrow() { + fprintf(stderr, "ReallyThrow\n"); + try { + if (zero == 0) + throw 42; + else if (zero == 1) + throw 1.; + } catch(double x) { + } +} + +__attribute__((noinline)) +void Throw() { + int a, b, c, d, e; + pretend_to_do_something(&a); + pretend_to_do_something(&b); + pretend_to_do_something(&c); + pretend_to_do_something(&d); + pretend_to_do_something(&e); + fprintf(stderr, "Throw stack = %p\n", &a); + ReallyThrow(); +} + +__attribute__((noinline)) +void CheckStack() { + int ar[100]; + pretend_to_do_something(ar); + for (int i = 0; i < 100; i++) + ar[i] = i; + fprintf(stderr, "CheckStack stack = %p, %p\n", ar, ar + 100); +} + +int main(int argc, char** argv) { + try { + Throw(); + } catch(int a) { + fprintf(stderr, "a = %d\n", a); + } + CheckStack(); +} + diff --git a/lib/asan/lit_tests/time_interceptor.cc b/lib/asan/lit_tests/time_interceptor.cc new file mode 100644 index 000000000000..f5f2ad62b815 --- /dev/null +++ b/lib/asan/lit_tests/time_interceptor.cc @@ -0,0 +1,16 @@ +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +// Test the time() interceptor. + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +int main() { + time_t *tm = (time_t*)malloc(sizeof(time_t)); + free(tm); + time_t t = time(tm); + printf("Time: %s\n", ctime(&t)); // NOLINT + // CHECK: use-after-free + return 0; +} diff --git a/lib/asan/lit_tests/unaligned_loads_and_stores.cc b/lib/asan/lit_tests/unaligned_loads_and_stores.cc new file mode 100644 index 000000000000..bcae089b427b --- /dev/null +++ b/lib/asan/lit_tests/unaligned_loads_and_stores.cc @@ -0,0 +1,52 @@ +// RUN: %clangxx_asan -O0 -I %p/../../../include %s -o %t +// RUN: %t A 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-A %s +// RUN: %t B 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-B %s +// RUN: %t C 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-C %s +// RUN: %t D 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-D %s +// RUN: %t E 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-E %s + +// RUN: %t K 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-K %s +// RUN: %t L 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-L %s +// RUN: %t M 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-M %s +// RUN: %t N 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-N %s +// RUN: %t O 2>&1 | %symbolize | FileCheck --check-prefix=CHECK-O %s + +#include <sanitizer/asan_interface.h> + +#include <stdlib.h> +#include <string.h> +int main(int argc, char **argv) { + if (argc != 2) return 1; + char *x = new char[16]; + memset(x, 0xab, 16); + int res = 1; + switch (argv[1][0]) { + case 'A': res = __sanitizer_unaligned_load16(x + 15); break; +// CHECK-A ERROR: AddressSanitizer: heap-buffer-overflow on address +// CHECK-A: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-2]] +// CHECK-A: is located 0 bytes to the right of 16-byte region + case 'B': res = __sanitizer_unaligned_load32(x + 14); break; +// CHECK-B: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'C': res = __sanitizer_unaligned_load32(x + 13); break; +// CHECK-C: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'D': res = __sanitizer_unaligned_load64(x + 15); break; +// CHECK-D: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'E': res = __sanitizer_unaligned_load64(x + 9); break; +// CHECK-E: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + + case 'K': __sanitizer_unaligned_store16(x + 15, 0); break; +// CHECK-K ERROR: AddressSanitizer: heap-buffer-overflow on address +// CHECK-K: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-2]] +// CHECK-K: is located 0 bytes to the right of 16-byte region + case 'L': __sanitizer_unaligned_store32(x + 15, 0); break; +// CHECK-L: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'M': __sanitizer_unaligned_store32(x + 13, 0); break; +// CHECK-M: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'N': __sanitizer_unaligned_store64(x + 10, 0); break; +// CHECK-N: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + case 'O': __sanitizer_unaligned_store64(x + 14, 0); break; +// CHECK-O: main{{.*}}unaligned_loads_and_stores.cc:[[@LINE-1]] + } + delete x; + return res; +} diff --git a/lib/asan/lit_tests/use-after-free-right.cc b/lib/asan/lit_tests/use-after-free-right.cc new file mode 100644 index 000000000000..b0de07b04a08 --- /dev/null +++ b/lib/asan/lit_tests/use-after-free-right.cc @@ -0,0 +1,46 @@ +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-%os < %t.out +// RUN: %clangxx_asan -m64 -O1 %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-%os < %t.out +// RUN: %clangxx_asan -m64 -O2 %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-%os < %t.out +// RUN: %clangxx_asan -m64 -O3 %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-%os < %t.out +// RUN: %clangxx_asan -m32 -O0 %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-%os < %t.out +// RUN: %clangxx_asan -m32 -O1 %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-%os < %t.out +// RUN: %clangxx_asan -m32 -O2 %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-%os < %t.out +// RUN: %clangxx_asan -m32 -O3 %s -o %t && %t 2>&1 | %symbolize > %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-%os < %t.out + +// Test use-after-free report in the case when access is at the right border of +// the allocation. + +#include <stdlib.h> +int main() { + volatile char *x = (char*)malloc(sizeof(char)); + free((void*)x); + *x = 42; + // CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}} + // CHECK: {{0x.* at pc 0x.* bp 0x.* sp 0x.*}} + // CHECK: {{WRITE of size 1 at 0x.* thread T0}} + // CHECK: {{ #0 0x.* in _?main .*use-after-free-right.cc:25}} + // CHECK: {{0x.* is located 0 bytes inside of 1-byte region .0x.*,0x.*}} + // CHECK: {{freed by thread T0 here:}} + + // CHECK-Linux: {{ #0 0x.* in .*free}} + // CHECK-Linux: {{ #1 0x.* in main .*use-after-free-right.cc:24}} + + // CHECK-Darwin: {{ #0 0x.* in _?wrap_free}} + // CHECK-Darwin: {{ #1 0x.* in _?main .*use-after-free-right.cc:24}} + + // CHECK: {{previously allocated by thread T0 here:}} + + // CHECK-Linux: {{ #0 0x.* in .*malloc}} + // CHECK-Linux: {{ #1 0x.* in main .*use-after-free-right.cc:23}} + + // CHECK-Darwin: {{ #0 0x.* in _?wrap_malloc.*}} + // CHECK-Darwin: {{ #1 0x.* in _?main .*use-after-free-right.cc:23}} +} diff --git a/lib/asan/lit_tests/use-after-free.cc b/lib/asan/lit_tests/use-after-free.cc index 24d5a2a54807..aee185dc4518 100644 --- a/lib/asan/lit_tests/use-after-free.cc +++ b/lib/asan/lit_tests/use-after-free.cc @@ -30,19 +30,14 @@ int main() { // CHECK-Linux: {{ #0 0x.* in .*free}} // CHECK-Linux: {{ #1 0x.* in main .*use-after-free.cc:21}} - // CHECK-Darwin: {{ #0 0x.* in .*free_common.*}} - // CHECK-Darwin: {{ #1 0x.* in .*mz_free.*}} - // We override free() on Darwin, thus no malloc_zone_free - // CHECK-Darwin: {{ #2 0x.* in _?wrap_free}} - // CHECK-Darwin: {{ #3 0x.* in _?main .*use-after-free.cc:21}} + // CHECK-Darwin: {{ #0 0x.* in _?wrap_free}} + // CHECK-Darwin: {{ #1 0x.* in _?main .*use-after-free.cc:21}} // CHECK: {{previously allocated by thread T0 here:}} // CHECK-Linux: {{ #0 0x.* in .*malloc}} // CHECK-Linux: {{ #1 0x.* in main .*use-after-free.cc:20}} - // CHECK-Darwin: {{ #0 0x.* in .*mz_malloc.*}} - // CHECK-Darwin: {{ #1 0x.* in malloc_zone_malloc.*}} - // CHECK-Darwin: {{ #2 0x.* in malloc.*}} - // CHECK-Darwin: {{ #3 0x.* in _?main .*use-after-free.cc:20}} + // CHECK-Darwin: {{ #0 0x.* in _?wrap_malloc.*}} + // CHECK-Darwin: {{ #1 0x.* in _?main .*use-after-free.cc:20}} } diff --git a/lib/asan/lit_tests/use-after-poison.cc b/lib/asan/lit_tests/use-after-poison.cc new file mode 100644 index 000000000000..d87342900245 --- /dev/null +++ b/lib/asan/lit_tests/use-after-poison.cc @@ -0,0 +1,20 @@ +// Check that __asan_poison_memory_region works. +// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// +// Check that we can disable it +// RUN: ASAN_OPTIONS=allow_user_poisoning=0 %t + +#include <stdlib.h> + +extern "C" void __asan_poison_memory_region(void *, size_t); + +int main(int argc, char **argv) { + char *x = new char[16]; + x[10] = 0; + __asan_poison_memory_region(x, 16); + int res = x[argc * 10]; // BOOOM + // CHECK: ERROR: AddressSanitizer: use-after-poison + // CHECK: main{{.*}}use-after-poison.cc:[[@LINE-2]] + delete [] x; + return res; +} diff --git a/lib/asan/lit_tests/use-after-scope-inlined.cc b/lib/asan/lit_tests/use-after-scope-inlined.cc index 3d730de6ab35..5c121ea187eb 100644 --- a/lib/asan/lit_tests/use-after-scope-inlined.cc +++ b/lib/asan/lit_tests/use-after-scope-inlined.cc @@ -23,7 +23,8 @@ int main(int argc, char *argv[]) { // CHECK: READ of size 4 at 0x{{.*}} thread T0 // CHECK: #0 0x{{.*}} in {{_?}}main // CHECK: {{.*}}use-after-scope-inlined.cc:[[@LINE-4]] - // CHECK: Address 0x{{.*}} is located at offset - // CHECK: [[OFFSET:[^ ]*]] in frame <main> of T0{{.*}}: + // CHECK: Address 0x{{.*}} is located in stack of thread T0 at offset + // CHECK: [[OFFSET:[^ ]*]] in frame + // CHECK: main // CHECK: {{\[}}[[OFFSET]], {{.*}}) 'x.i' } diff --git a/lib/asan/lit_tests/wait.cc b/lib/asan/lit_tests/wait.cc new file mode 100644 index 000000000000..88fbb17176fa --- /dev/null +++ b/lib/asan/lit_tests/wait.cc @@ -0,0 +1,77 @@ +// RUN: %clangxx_asan -DWAIT -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT -m64 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT -m32 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT -m32 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +// RUN: %clangxx_asan -DWAITPID -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAITPID -m64 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAITPID -m32 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAITPID -m32 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +// RUN: %clangxx_asan -DWAITID -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAITID -m64 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAITID -m32 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAITID -m32 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +// RUN: %clangxx_asan -DWAIT3 -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT3 -m64 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT3 -m32 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT3 -m32 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +// RUN: %clangxx_asan -DWAIT4 -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT4 -m64 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT4 -m32 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT4 -m32 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +// RUN: %clangxx_asan -DWAIT3_RUSAGE -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT3_RUSAGE -m64 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT3_RUSAGE -m32 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT3_RUSAGE -m32 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + +// RUN: %clangxx_asan -DWAIT4_RUSAGE -m64 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT4_RUSAGE -m64 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT4_RUSAGE -m32 -O0 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s +// RUN: %clangxx_asan -DWAIT4_RUSAGE -m32 -O3 %s -o %t && %t 2>&1 | %symbolize | FileCheck %s + + +#include <assert.h> +#include <sys/wait.h> +#include <unistd.h> + +int main(int argc, char **argv) { + pid_t pid = fork(); + if (pid) { // parent + int x[3]; + int *status = x + argc * 3; + int res; +#if defined(WAIT) + res = wait(status); +#elif defined(WAITPID) + res = waitpid(pid, status, WNOHANG); +#elif defined(WAITID) + siginfo_t *si = (siginfo_t*)(x + argc * 3); + res = waitid(P_ALL, 0, si, WEXITED | WNOHANG); +#elif defined(WAIT3) + res = wait3(status, WNOHANG, NULL); +#elif defined(WAIT4) + res = wait4(pid, status, WNOHANG, NULL); +#elif defined(WAIT3_RUSAGE) || defined(WAIT4_RUSAGE) + struct rusage *ru = (struct rusage*)(x + argc * 3); + int good_status; +# if defined(WAIT3_RUSAGE) + res = wait3(&good_status, WNOHANG, ru); +# elif defined(WAIT4_RUSAGE) + res = wait4(pid, &good_status, WNOHANG, ru); +# endif +#endif + // CHECK: stack-buffer-overflow + // CHECK: {{WRITE of size .* at 0x.* thread T0}} + // CHECK: {{in .*wait}} + // CHECK: {{in _?main .*wait.cc:}} + // CHECK: is located in stack of thread T0 at offset + // CHECK: {{in _?main}} + return res != -1; + } + // child + return 0; +} |