diff options
Diffstat (limited to 'test')
37 files changed, 861 insertions, 42 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2ceb86463ae0..85a1735b1cf9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,6 +7,12 @@ configure_lit_site_cfg( # add_subdirectory(builtins) set(SANITIZER_COMMON_LIT_TEST_DEPS) +if(COMPILER_RT_STANDALONE_BUILD) + add_executable(FileCheck IMPORTED GLOBAL) + set_property(TARGET FileCheck PROPERTY IMPORTED_LOCATION ${LLVM_TOOLS_BINARY_DIR}/FileCheck) + list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS FileCheck) +endif() + # When ANDROID, we build tests with the host compiler (i.e. CMAKE_C_COMPILER), # and run tests with tools from the host toolchain. if(NOT ANDROID) @@ -51,6 +57,7 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS) if(COMPILER_RT_HAS_UBSAN) add_subdirectory(ubsan) endif() + add_subdirectory(cfi) endif() if(COMPILER_RT_STANDALONE_BUILD) diff --git a/test/asan/CMakeLists.txt b/test/asan/CMakeLists.txt index 0c46ef7e6e31..e1b81264604d 100644 --- a/test/asan/CMakeLists.txt +++ b/test/asan/CMakeLists.txt @@ -55,11 +55,7 @@ foreach(arch ${ASAN_SUPPORTED_ARCH}) endforeach() set(ASAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -if(COMPILER_RT_STANDALONE_BUILD) - add_executable(FileCheck IMPORTED GLOBAL) - set_property(TARGET FileCheck PROPERTY IMPORTED_LOCATION ${LLVM_TOOLS_BINARY_DIR}/FileCheck) - list(APPEND ASAN_TEST_DEPS FileCheck) -else() +if(NOT COMPILER_RT_STANDALONE_BUILD) list(APPEND ASAN_TEST_DEPS asan) endif() set(ASAN_DYNAMIC_TEST_DEPS ${ASAN_TEST_DEPS}) diff --git a/test/asan/TestCases/Windows/dll_host.cc b/test/asan/TestCases/Windows/dll_host.cc index d3b4c149d009..71721fe29e88 100644 --- a/test/asan/TestCases/Windows/dll_host.cc +++ b/test/asan/TestCases/Windows/dll_host.cc @@ -6,9 +6,14 @@ // // Get the list of ASan wrappers exported by the main module RTL: // RUN: dumpbin /EXPORTS %t | grep -o "__asan_wrap[^ ]*" | grep -v @ | sort | uniq > %t.exported_wrappers +// FIXME: we should really check the other __asan exports too. +// RUN: dumpbin /EXPORTS %t | grep -o "__sanitizer_[^ ]*" | grep -v @ | sort | uniq >> %t.exported_wrappers // // Get the list of ASan wrappers imported by the DLL RTL: -// RUN: grep INTERCEPT_LIBRARY_FUNCTION %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed "s/.*(\(.*\)).*/__asan_wrap_\1/" | sort | uniq > %t.dll_imports +// [BEWARE: be really careful with the sed commands, as this test can be run +// from different environemnts with different shells and seds] +// RUN: grep INTERCEPT_LIBRARY_FUNCTION %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed -e s/.*(/__asan_wrap_/ | sed -e s/).*// | sort | uniq > %t.dll_imports +// RUN: grep "^INTERFACE_FUNCTION.*sanitizer" %p/../../../../lib/asan/asan_win_dll_thunk.cc | grep -v define | sed -e s/.*(// | sed -e s/).*// | sort | uniq >> %t.dll_imports // // Now make sure the DLL thunk imports everything: // RUN: echo diff --git a/test/asan/TestCases/Windows/globals_multiple_dlls.cc b/test/asan/TestCases/Windows/globals_multiple_dlls.cc new file mode 100644 index 000000000000..634e5782796c --- /dev/null +++ b/test/asan/TestCases/Windows/globals_multiple_dlls.cc @@ -0,0 +1,51 @@ +// Make sure everything works even if the main module doesn't have any stack +// variables, thus doesn't explicitly reference any symbol exported by the +// runtime thunk. +// +// RUN: %clang_cl_asan -LD -O0 -DDLL %s -Fe%t.dll +// RUN: %clang_cl_asan -O0 -DEXE %s -Fe%te.exe +// RUN: env ASAN_OPTIONS=report_globals=2 %run %te.exe %t.dll 2>&1 | FileCheck %s + +#include <windows.h> +#include <stdio.h> +#include <string.h> + +extern "C" { +#if defined(EXE) +int main(int argc, char **argv) { + if (argc != 2) { + printf("Usage: %s [client].dll\n", argv[0]); + return 101; + } + const char *dll_name = argv[1]; + +// CHECK: time to load DLL + printf("time to load DLL\n"); + fflush(0); + +// On DLL load, the "in DLL\n" string is registered: +// CHECK: Added Global{{.*}} size=19 +// CHECK: in DLL(reason=1) + HMODULE dll = LoadLibrary(dll_name); + if (dll == NULL) + return 3; + +// CHECK: in DLL(reason=0) +// CHECK-NEXT: Removed Global{{.*}} size=19 + if (!FreeLibrary(dll)) + return 4; + +// CHECK: bye! + printf("bye!\n"); + fflush(0); +} +#elif defined(DLL) +BOOL WINAPI DllMain(HMODULE, DWORD reason, LPVOID) { + printf("in DLL(reason=%d)\n", (int)reason); + fflush(0); + return TRUE; +} +#else +# error oops! +#endif +} diff --git a/test/asan/TestCases/Windows/oom.cc b/test/asan/TestCases/Windows/oom.cc new file mode 100644 index 000000000000..b24cddf17a97 --- /dev/null +++ b/test/asan/TestCases/Windows/oom.cc @@ -0,0 +1,12 @@ +// RUN: %clang_cl_asan -O0 %s -Fe%t +// RUN: not %run %t 2>&1 | FileCheck %s + +#include <malloc.h> + +int main() { + while (true) { + void *ptr = malloc(200 * 1024 * 1024); // 200MB + free(ptr); + } +// CHECK: failed to allocate +} diff --git a/test/asan/TestCases/Windows/symbols_path.cc b/test/asan/TestCases/Windows/symbols_path.cc new file mode 100644 index 000000000000..3c69f8861d78 --- /dev/null +++ b/test/asan/TestCases/Windows/symbols_path.cc @@ -0,0 +1,22 @@ +// Make sure symbolization works even if the path to the .exe file changes. +// RUN: mkdir %t || true +// RUN: %clang_cl_asan -O0 %s -Fe%t/symbols_path.exe +// RUN: not %run %t/symbols_path.exe 2>&1 | FileCheck %s +// RUN: mkdir %t2 || true +// RUN: mv %t/* %t2 +// RUN: not %run %t2/symbols_path.exe 2>&1 | FileCheck %s + +#include <malloc.h> + +int main() { + char *buffer = (char*)malloc(42); + buffer[-1] = 42; +// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] +// CHECK: WRITE of size 1 at [[ADDR]] thread T0 +// CHECK-NEXT: {{#0 .* main .*symbols_path.cc}}:[[@LINE-3]] +// CHECK: [[ADDR]] is located 1 bytes to the left of 42-byte region +// CHECK: allocated by thread T0 here: +// CHECK-NEXT: {{#0 .* malloc }} +// CHECK-NEXT: {{#1 .* main .*symbols_path.cc}}:[[@LINE-8]] + free(buffer); +} diff --git a/test/asan/TestCases/dlclose-test.cc b/test/asan/TestCases/dlclose-test.cc index 2d31aee5a32f..369abd3127cc 100644 --- a/test/asan/TestCases/dlclose-test.cc +++ b/test/asan/TestCases/dlclose-test.cc @@ -33,6 +33,13 @@ #include <string> +#if defined(__FreeBSD__) +// The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before +// that, it was never implemented. So just define it to zero. +#undef MAP_NORESERVE +#define MAP_NORESERVE 0 +#endif + using std::string; typedef int *(fun_t)(); diff --git a/test/asan/TestCases/gc-test.cc b/test/asan/TestCases/gc-test.cc index ffbea85b2650..4ffa51dd22d3 100644 --- a/test/asan/TestCases/gc-test.cc +++ b/test/asan/TestCases/gc-test.cc @@ -1,6 +1,9 @@ // RUN: %clangxx_asan %s -pthread -o %t // RUN: env ASAN_OPTIONS=detect_stack_use_after_return=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 // RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0 +// RUN: %clangxx_asan -O3 %s -pthread -o %t +// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 +// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK0 // REQUIRES: stable-runtime #include <assert.h> @@ -9,6 +12,7 @@ #include <sanitizer/asan_interface.h> static const int kNumThreads = 2; +static const int kLeftRedzoneSize = sizeof(void *) * 4; void *Thread(void *unused) { void *fake_stack = __asan_get_current_fake_stack(); @@ -23,7 +27,7 @@ void *Thread(void *unused) { assert(real_stack); assert((char*)beg <= (char*)&var[0]); assert((char*)end > (char*)&var[0]); - for (int i = -32; i < 15; i++) { + for (int i = -kLeftRedzoneSize; i < 15; i++) { void *beg1, *end1; char *ptr = &var[0] + i; void *real_stack1 = diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg index 8be7062614b3..a6f443cfb6a5 100644 --- a/test/asan/lit.cfg +++ b/test/asan/lit.cfg @@ -3,6 +3,8 @@ import os import platform +import lit.formats + def get_required_attr(config, attr_name): attr_value = getattr(config, attr_name, None) if attr_value == None: @@ -15,6 +17,8 @@ def get_required_attr(config, attr_name): def push_dynamic_library_lookup_path(config, new_path): if platform.system() == 'Windows': dynamic_library_lookup_var = 'PATH' + elif platform.system() == 'Darwin': + dynamic_library_lookup_var = 'DYLD_LIBRARY_PATH' else: dynamic_library_lookup_var = 'LD_LIBRARY_PATH' @@ -25,6 +29,10 @@ def push_dynamic_library_lookup_path(config, new_path): # Setup config name. config.name = 'AddressSanitizer' + config.name_suffix +# testFormat: The test format to use to interpret tests. +external_bash = (not sys.platform in ['win32']) +config.test_format = lit.formats.ShTest(external_bash) + # Setup source root. config.test_source_root = os.path.dirname(__file__) diff --git a/test/cfi/CMakeLists.txt b/test/cfi/CMakeLists.txt new file mode 100644 index 000000000000..f519fb089505 --- /dev/null +++ b/test/cfi/CMakeLists.txt @@ -0,0 +1,23 @@ +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg + ) + +set(CFI_TEST_DEPS) +if(NOT COMPILER_RT_STANDALONE_BUILD) + list(APPEND CFI_TEST_DEPS + FileCheck + clang + not + ) + if(LLVM_ENABLE_PIC AND LLVM_BINUTILS_INCDIR) + list(APPEND CFI_TEST_DEPS + LLVMgold + ) + endif() +endif() + +add_lit_testsuite(check-cfi "Running the cfi regression tests" + ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${CFI_TEST_DEPS}) +set_target_properties(check-cfi PROPERTIES FOLDER "Tests") diff --git a/test/cfi/anon-namespace.cpp b/test/cfi/anon-namespace.cpp new file mode 100644 index 000000000000..0c2c689966f1 --- /dev/null +++ b/test/cfi/anon-namespace.cpp @@ -0,0 +1,93 @@ +// RUN: %clangxx_cfi -c -DTU1 -o %t1.o %s +// RUN: %clangxx_cfi -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp +// RUN: %clangxx_cfi -o %t %t1.o %t2.o +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -c -DTU1 -DB32 -o %t1.o %s +// RUN: %clangxx_cfi -c -DTU2 -DB32 -o %t2.o %S/../cfi/anon-namespace.cpp +// RUN: %clangxx_cfi -o %t %t1.o %t2.o +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -c -DTU1 -DB64 -o %t1.o %s +// RUN: %clangxx_cfi -c -DTU2 -DB64 -o %t2.o %S/../cfi/anon-namespace.cpp +// RUN: %clangxx_cfi -o %t %t1.o %t2.o +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -c -DTU1 -DBM -o %t1.o %s +// RUN: %clangxx_cfi -c -DTU2 -DBM -o %t2.o %S/../cfi/anon-namespace.cpp +// RUN: %clangxx_cfi -o %t %t1.o %t2.o +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx -c -DTU1 -o %t1.o %s +// RUN: %clangxx -c -DTU2 -o %t2.o %S/../cfi/anon-namespace.cpp +// RUN: %clangxx -o %t %t1.o %t2.o +// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s + +// Tests that the CFI mechanism treats classes in the anonymous namespace in +// different translation units as having distinct identities. This is done by +// compiling two translation units TU1 and TU2 containing a class named B in an +// anonymous namespace, and testing that the program crashes if TU2 attempts to +// use a TU1 B as a TU2 B. + +// FIXME: This test should not require that the paths supplied to the compiler +// are different. It currently does so because bitset names have global scope +// so we have to mangle the file path into the bitset name. + +#include <stdio.h> +#include "utils.h" + +struct A { + virtual void f() = 0; +}; + +namespace { + +struct B : A { + virtual void f() {} +}; + +} + +A *mkb(); + +#ifdef TU1 + +A *mkb() { + return new B; +} + +#endif // TU1 + +#ifdef TU2 + +int main() { +#ifdef B32 + break_optimization(new Deriver<B, 0>); +#endif + +#ifdef B64 + break_optimization(new Deriver<B, 0>); + break_optimization(new Deriver<B, 1>); +#endif + +#ifdef BM + break_optimization(new Deriver<B, 0>); + break_optimization(new Deriver<B, 1>); + break_optimization(new Deriver<B, 2>); +#endif + + A *a = mkb(); + break_optimization(a); + + // CFI: 1 + // NCFI: 1 + fprintf(stderr, "1\n"); + + ((B *)a)->f(); // UB here + + // CFI-NOT: 2 + // NCFI: 2 + fprintf(stderr, "2\n"); +} + +#endif // TU2 diff --git a/test/cfi/lit.cfg b/test/cfi/lit.cfg new file mode 100644 index 000000000000..d78820daa055 --- /dev/null +++ b/test/cfi/lit.cfg @@ -0,0 +1,35 @@ +import lit.formats +import os +import subprocess +import sys + +config.name = 'cfi' +config.suffixes = ['.cpp'] +config.test_source_root = os.path.dirname(__file__) + +def is_darwin_lto_supported(): + return os.path.exists(os.path.join(config.llvm_shlib_dir, 'libLTO.dylib')) + +def is_linux_lto_supported(): + if not os.path.exists(os.path.join(config.llvm_shlib_dir, 'LLVMgold.so')): + return False + + ld_cmd = subprocess.Popen([config.gold_executable, '--help'], stdout = subprocess.PIPE) + ld_out = ld_cmd.stdout.read().decode() + ld_cmd.wait() + + if not '-plugin' in ld_out: + return False + + return True + +clangxx = ' '.join([config.clang] + config.cxx_mode_flags) + +config.substitutions.append((r"%clangxx ", clangxx + ' ')) + +if sys.platform == 'darwin' and is_darwin_lto_supported(): + config.substitutions.append((r"%clangxx_cfi ", 'env DYLD_LIBRARY_PATH=' + config.llvm_shlib_dir + ' ' + clangxx + ' -fsanitize=cfi ')) +elif sys.platform.startswith('linux') and is_linux_lto_supported(): + config.substitutions.append((r"%clangxx_cfi ", clangxx + ' -fuse-ld=gold -fsanitize=cfi ')) +else: + config.unsupported = True diff --git a/test/cfi/lit.site.cfg.in b/test/cfi/lit.site.cfg.in new file mode 100644 index 000000000000..76897e701874 --- /dev/null +++ b/test/cfi/lit.site.cfg.in @@ -0,0 +1,2 @@ +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") +lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") diff --git a/test/cfi/multiple-inheritance.cpp b/test/cfi/multiple-inheritance.cpp new file mode 100644 index 000000000000..523af6f72f2f --- /dev/null +++ b/test/cfi/multiple-inheritance.cpp @@ -0,0 +1,82 @@ +// RUN: %clangxx_cfi -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s +// RUN: not --crash %t x 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx -o %t %s +// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s +// RUN: %t x 2>&1 | FileCheck --check-prefix=NCFI %s + +// Tests that the CFI mechanism is sensitive to multiple inheritance and only +// permits calls via virtual tables for the correct base class. + +#include <stdio.h> +#include "utils.h" + +struct A { + virtual void f() = 0; +}; + +struct B { + virtual void g() = 0; +}; + +struct C : A, B { + virtual void f(), g(); +}; + +void C::f() {} +void C::g() {} + +int main(int argc, char **argv) { +#ifdef B32 + break_optimization(new Deriver<A, 0>); + break_optimization(new Deriver<B, 0>); +#endif + +#ifdef B64 + break_optimization(new Deriver<A, 0>); + break_optimization(new Deriver<A, 1>); + break_optimization(new Deriver<B, 0>); + break_optimization(new Deriver<B, 1>); +#endif + +#ifdef BM + break_optimization(new Deriver<A, 0>); + break_optimization(new Deriver<A, 1>); + break_optimization(new Deriver<A, 2>); + break_optimization(new Deriver<B, 0>); + break_optimization(new Deriver<B, 1>); + break_optimization(new Deriver<B, 2>); +#endif + + C *c = new C; + break_optimization(c); + + // CFI: 1 + // NCFI: 1 + fprintf(stderr, "1\n"); + + if (argc > 1) { + A *a = c; + ((B *)a)->g(); // UB here + } else { + B *b = c; + ((A *)b)->f(); // UB here + } + + // CFI-NOT: 2 + // NCFI: 2 + fprintf(stderr, "2\n"); +} diff --git a/test/cfi/overwrite.cpp b/test/cfi/overwrite.cpp new file mode 100644 index 000000000000..d7e58d9277e9 --- /dev/null +++ b/test/cfi/overwrite.cpp @@ -0,0 +1,67 @@ +// RUN: %clangxx_cfi -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx -o %t %s +// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s + +// Tests that the CFI mechanism crashes the program when a virtual table is +// replaced with a compatible table of function pointers that does not belong to +// any class, by manually overwriting the virtual table of an object and +// attempting to make a call through it. + +#include <stdio.h> +#include "utils.h" + +struct A { + virtual void f(); +}; + +void A::f() {} + +void foo() { + fprintf(stderr, "foo\n"); +} + +void *fake_vtable[] = { (void *)&foo }; + +int main() { +#ifdef B32 + break_optimization(new Deriver<A, 0>); +#endif + +#ifdef B64 + break_optimization(new Deriver<A, 0>); + break_optimization(new Deriver<A, 1>); +#endif + +#ifdef BM + break_optimization(new Deriver<A, 0>); + break_optimization(new Deriver<A, 1>); + break_optimization(new Deriver<A, 2>); +#endif + + A *a = new A; + *((void **)a) = fake_vtable; // UB here + break_optimization(a); + + // CFI: 1 + // NCFI: 1 + fprintf(stderr, "1\n"); + + // CFI-NOT: foo + // NCFI: foo + a->f(); + + // CFI-NOT: 2 + // NCFI: 2 + fprintf(stderr, "2\n"); +} diff --git a/test/cfi/simple-fail.cpp b/test/cfi/simple-fail.cpp new file mode 100644 index 000000000000..cf24f86e0064 --- /dev/null +++ b/test/cfi/simple-fail.cpp @@ -0,0 +1,99 @@ +// RUN: %clangxx_cfi -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O1 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O1 -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O1 -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O1 -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O2 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O2 -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O2 -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O2 -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O3 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O3 -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O3 -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -O3 -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx -o %t %s +// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s + +// Tests that the CFI mechanism crashes the program when making a virtual call +// to an object of the wrong class but with a compatible vtable, by casting a +// pointer to such an object and attempting to make a call through it. + +#include <stdio.h> +#include "utils.h" + +struct A { + virtual void f(); +}; + +void A::f() {} + +struct B { + virtual void f(); +}; + +void B::f() {} + +int main() { +#ifdef B32 + break_optimization(new Deriver<B, 0>); +#endif + +#ifdef B64 + break_optimization(new Deriver<B, 0>); + break_optimization(new Deriver<B, 1>); +#endif + +#ifdef BM + break_optimization(new Deriver<B, 0>); + break_optimization(new Deriver<B, 1>); + break_optimization(new Deriver<B, 2>); +#endif + + A *a = new A; + break_optimization(a); + + // CFI: 1 + // NCFI: 1 + fprintf(stderr, "1\n"); + + ((B *)a)->f(); // UB here + + // CFI-NOT: 2 + // NCFI: 2 + fprintf(stderr, "2\n"); +} diff --git a/test/cfi/simple-pass.cpp b/test/cfi/simple-pass.cpp new file mode 100644 index 000000000000..50e7d9256084 --- /dev/null +++ b/test/cfi/simple-pass.cpp @@ -0,0 +1,97 @@ +// RUN: %clangxx_cfi -o %t %s +// RUN: %t + +// Tests that the CFI mechanism does not crash the program when making various +// kinds of valid calls involving classes with various different linkages and +// types of inheritance. + +#include "utils.h" + +struct A { + virtual void f(); +}; + +void A::f() {} + +struct A2 : A { + virtual void f(); +}; + +void A2::f() {} + +struct B { + virtual void f() {} +}; + +struct B2 : B { + virtual void f() {} +}; + +namespace { + +struct C { + virtual void f(); +}; + +void C::f() {} + +struct C2 : C { + virtual void f(); +}; + +void C2::f() {} + +struct D { + virtual void f() {} +}; + +struct D2 : D { + virtual void f() {} +}; + +} + +struct E { + virtual void f() {} +}; + +struct E2 : virtual E { + virtual void f() {} +}; + +int main() { + A *a = new A; + break_optimization(a); + a->f(); + a = new A2; + break_optimization(a); + a->f(); + + B *b = new B; + break_optimization(b); + b->f(); + b = new B2; + break_optimization(b); + b->f(); + + C *c = new C; + break_optimization(c); + c->f(); + c = new C2; + break_optimization(c); + c->f(); + + D *d = new D; + break_optimization(d); + d->f(); + d = new D2; + break_optimization(d); + d->f(); + + E *e = new E; + break_optimization(e); + e->f(); + e = new E2; + break_optimization(e); + e->f(); +} diff --git a/test/cfi/utils.h b/test/cfi/utils.h new file mode 100644 index 000000000000..5c290d151069 --- /dev/null +++ b/test/cfi/utils.h @@ -0,0 +1,53 @@ +#ifndef UTILS_H +#define UTILS_H + +inline void break_optimization(void *arg) { + __asm__ __volatile__("" : : "r" (arg) : "memory"); +} + +// Tests will instantiate this class to pad out bit sets to test out the various +// ways we can represent the bit set (32-bit inline, 64-bit inline, memory). +// This class has 37 virtual member functions, which forces us to use a +// pointer-aligned bitset. +template <typename T, unsigned I> +class Deriver : T { + virtual void f() {} + virtual void g() {} + virtual void f1() {} + virtual void f2() {} + virtual void f3() {} + virtual void f4() {} + virtual void f5() {} + virtual void f6() {} + virtual void f7() {} + virtual void f8() {} + virtual void f9() {} + virtual void f10() {} + virtual void f11() {} + virtual void f12() {} + virtual void f13() {} + virtual void f14() {} + virtual void f15() {} + virtual void f16() {} + virtual void f17() {} + virtual void f18() {} + virtual void f19() {} + virtual void f20() {} + virtual void f21() {} + virtual void f22() {} + virtual void f23() {} + virtual void f24() {} + virtual void f25() {} + virtual void f26() {} + virtual void f27() {} + virtual void f28() {} + virtual void f29() {} + virtual void f30() {} + virtual void f31() {} + virtual void f32() {} + virtual void f33() {} + virtual void f34() {} + virtual void f35() {} +}; + +#endif diff --git a/test/cfi/vdtor.cpp b/test/cfi/vdtor.cpp new file mode 100644 index 000000000000..e21883c380dd --- /dev/null +++ b/test/cfi/vdtor.cpp @@ -0,0 +1,62 @@ +// RUN: %clangxx_cfi -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB32 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DB64 -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx_cfi -DBM -o %t %s +// RUN: not --crash %t 2>&1 | FileCheck --check-prefix=CFI %s + +// RUN: %clangxx -o %t %s +// RUN: %t 2>&1 | FileCheck --check-prefix=NCFI %s + +// Tests that the CFI enforcement also applies to virtual destructor calls made +// via 'delete'. + +#include <stdio.h> +#include "utils.h" + +struct A { + virtual ~A(); +}; + +A::~A() {} + +struct B { + virtual ~B(); +}; + +B::~B() {} + +int main() { +#ifdef B32 + break_optimization(new Deriver<B, 0>); +#endif + +#ifdef B64 + break_optimization(new Deriver<B, 0>); + break_optimization(new Deriver<B, 1>); +#endif + +#ifdef BM + break_optimization(new Deriver<B, 0>); + break_optimization(new Deriver<B, 1>); + break_optimization(new Deriver<B, 2>); +#endif + + A *a = new A; + break_optimization(a); + + // CFI: 1 + // NCFI: 1 + fprintf(stderr, "1\n"); + + delete (B *)a; // UB here + + // CFI-NOT: 2 + // NCFI: 2 + fprintf(stderr, "2\n"); +} diff --git a/test/lit.common.cfg b/test/lit.common.cfg index 0ee2b84481da..0a551862c32b 100644 --- a/test/lit.common.cfg +++ b/test/lit.common.cfg @@ -61,7 +61,8 @@ path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH'])) config.environment['PATH'] = path # Help MSVS link.exe find the standard libraries. -if platform.system() == 'Windows': +# Make sure we only try to use it when targetting Windows. +if platform.system() == 'Windows' and '-win' in config.target_triple: config.environment['LIB'] = os.environ['LIB'] # Use ugly construction to explicitly prohibit "clang", "clang++" etc. diff --git a/test/lit.common.configured.in b/test/lit.common.configured.in index ceab67d4ad07..4a5966e44f32 100644 --- a/test/lit.common.configured.in +++ b/test/lit.common.configured.in @@ -18,6 +18,8 @@ set_default("llvm_obj_root", "@LLVM_BINARY_DIR@") set_default("compiler_rt_src_root", "@COMPILER_RT_SOURCE_DIR@") set_default("compiler_rt_obj_root", "@COMPILER_RT_BINARY_DIR@") set_default("llvm_tools_dir", "@LLVM_TOOLS_DIR@") +set_default("llvm_shlib_dir", "@SHLIBDIR@") +set_default("gold_executable", "@GOLD_EXECUTABLE@") set_default("clang", "@COMPILER_RT_TEST_COMPILER@") set_default("compiler_id", "@COMPILER_RT_TEST_COMPILER_ID@") set_default("compiler_rt_arch", "@COMPILER_RT_SUPPORTED_ARCH@") diff --git a/test/lsan/lit.common.cfg b/test/lsan/lit.common.cfg index bd1aa2769c42..ba9c283ca84a 100644 --- a/test/lsan/lit.common.cfg +++ b/test/lsan/lit.common.cfg @@ -44,8 +44,8 @@ config.substitutions.append( ("%clangxx ", build_invocation(clang_cxxflags)) ) config.substitutions.append( ("%clang_lsan ", build_invocation(clang_lsan_cflags)) ) config.substitutions.append( ("%clangxx_lsan ", build_invocation(clang_lsan_cxxflags)) ) -# LeakSanitizer tests are currently supported on x86-64 Linux only. -if config.host_os not in ['Linux'] or config.host_arch not in ['x86_64']: +# LeakSanitizer tests are currently supported on x86-64 Linux and mips64 Linux only. +if config.host_os not in ['Linux'] or config.host_arch not in ['x86_64', 'mips64']: config.unsupported = True config.suffixes = ['.c', '.cc', '.cpp'] diff --git a/test/msan/mmap_below_shadow.cc b/test/msan/mmap_below_shadow.cc index 4b5890ba0fb8..0b982d58930d 100644 --- a/test/msan/mmap_below_shadow.cc +++ b/test/msan/mmap_below_shadow.cc @@ -15,8 +15,13 @@ int main(void) { // Hint address just below shadow. +#if defined(__x86_64__) uintptr_t hint = 0x4f0000000000ULL; const uintptr_t app_start = 0x600000000000ULL; +#elif defined (__mips64) + uintptr_t hint = 0x4f00000000ULL; + const uintptr_t app_start = 0x6000000000ULL; +#endif uintptr_t p = (uintptr_t)mmap( (void *)hint, 4096, PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | (FIXED ? MAP_FIXED : 0), -1, 0); diff --git a/test/msan/strlen_of_shadow.cc b/test/msan/strlen_of_shadow.cc index bb9fe17d41cd..8f1b4e1fc6bb 100644 --- a/test/msan/strlen_of_shadow.cc +++ b/test/msan/strlen_of_shadow.cc @@ -9,7 +9,11 @@ #include <string.h> const char *mem_to_shadow(const char *p) { +#if defined(__x86_64__) return (char *)((uintptr_t)p & ~0x400000000000ULL); +#elif defined (__mips64) + return (char *)((uintptr_t)p & ~0x4000000000ULL); +#endif } int main(void) { diff --git a/test/msan/vector_select.cc b/test/msan/vector_select.cc index e8d55423293c..afeb1ad50c8b 100644 --- a/test/msan/vector_select.cc +++ b/test/msan/vector_select.cc @@ -4,10 +4,18 @@ // Regression test for MemorySanitizer instrumentation of a select instruction // with vector arguments. +#if defined(__x86_64__) #include <emmintrin.h> __m128d select(bool b, __m128d c, __m128d d) { return b ? c : d; } +#elif defined (__mips64) +typedef double __w64d __attribute__ ((vector_size(16))); +__w64d select(bool b, __w64d c, __w64d d) +{ + return b ? c : d; +} +#endif diff --git a/test/sanitizer_common/TestCases/Linux/ptrace.cc b/test/sanitizer_common/TestCases/Linux/ptrace.cc index 2bf0fd2f0f35..ba318169ee7d 100644 --- a/test/sanitizer_common/TestCases/Linux/ptrace.cc +++ b/test/sanitizer_common/TestCases/Linux/ptrace.cc @@ -8,6 +8,10 @@ #include <sys/user.h> #include <sys/wait.h> #include <unistd.h> +#if __mips64 + #include <asm/ptrace.h> + #include <sys/procfs.h> +#endif int main(void) { pid_t pid; @@ -33,19 +37,23 @@ int main(void) { printf("%x\n", fpregs.mxcsr); #endif // __x86_64__ -#if __powerpc64__ +#if (__powerpc64__ || __mips64) struct pt_regs regs; res = ptrace((enum __ptrace_request)PTRACE_GETREGS, pid, NULL, ®s); assert(!res); +#if (__powerpc64__) if (regs.nip) printf("%lx\n", regs.nip); - +#else + if (regs.cp0_epc) + printf("%lx\n", regs.cp0_epc); +#endif elf_fpregset_t fpregs; res = ptrace((enum __ptrace_request)PTRACE_GETFPREGS, pid, NULL, &fpregs); assert(!res); if ((elf_greg_t)fpregs[32]) // fpscr printf("%lx\n", (elf_greg_t)fpregs[32]); -#endif // __powerpc64__ +#endif // (__powerpc64__ || __mips64) siginfo_t siginfo; res = ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo); diff --git a/test/tsan/global_race.cc b/test/tsan/global_race.cc index d70bee4a556b..3128ec411749 100644 --- a/test/tsan/global_race.cc +++ b/test/tsan/global_race.cc @@ -11,9 +11,9 @@ void *Thread(void *a) { int main() { barrier_init(&barrier, 2); - // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not - // match to the format used in the diagnotic message. - fprintf(stderr, "addr=0x%012lx\n", (unsigned long) GlobalData); + fprintf(stderr, "addr="); + print_address(GlobalData); + fprintf(stderr, "\n"); pthread_t t; pthread_create(&t, 0, Thread, 0); GlobalData[2] = 43; diff --git a/test/tsan/global_race2.cc b/test/tsan/global_race2.cc index 6631008d85a5..4ab2842e7eef 100644 --- a/test/tsan/global_race2.cc +++ b/test/tsan/global_race2.cc @@ -11,9 +11,9 @@ void *Thread(void *a) { int main() { barrier_init(&barrier, 2); - // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not - // match to the format used in the diagnotic message. - fprintf(stderr, "addr2=0x%012lx\n", (unsigned long) &x); + fprintf(stderr, "addr2="); + print_address(&x); + fprintf(stderr, "\n"); pthread_t t; pthread_create(&t, 0, Thread, 0); x = 0; diff --git a/test/tsan/global_race3.cc b/test/tsan/global_race3.cc index e7e9a7fef028..1531d7830f78 100644 --- a/test/tsan/global_race3.cc +++ b/test/tsan/global_race3.cc @@ -16,9 +16,9 @@ void *Thread(void *a) { int main() { barrier_init(&barrier, 2); - // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not - // match to the format used in the diagnotic message. - fprintf(stderr, "addr3=0x%012lx\n", (unsigned long) XXX::YYY::ZZZ); + fprintf(stderr, "addr3="); + print_address(XXX::YYY::ZZZ); + fprintf(stderr, "\n"); pthread_t t; pthread_create(&t, 0, Thread, 0); XXX::YYY::ZZZ[0] = 0; diff --git a/test/tsan/map32bit.cc b/test/tsan/map32bit.cc index 9dae6880e7fe..d9a04655ddca 100644 --- a/test/tsan/map32bit.cc +++ b/test/tsan/map32bit.cc @@ -7,6 +7,9 @@ // Test for issue: // https://code.google.com/p/thread-sanitizer/issues/detail?id=5 +// MAP_32BIT flag for mmap is supported only for x86_64. +// XFAIL: mips64 + void *Thread(void *ptr) { *(int*)ptr = 42; barrier_wait(&barrier); diff --git a/test/tsan/mmap_large.cc b/test/tsan/mmap_large.cc index e715ea666231..4ae4c0863501 100644 --- a/test/tsan/mmap_large.cc +++ b/test/tsan/mmap_large.cc @@ -5,7 +5,11 @@ #include <sys/mman.h> int main() { +#ifdef __x86_64__ const size_t kLog2Size = 39; +#elif defined(__mips64) + const size_t kLog2Size = 32; +#endif const uintptr_t kLocation = 0x40ULL << kLog2Size; void *p = mmap( reinterpret_cast<void*>(kLocation), diff --git a/test/tsan/signal_segv_handler.cc b/test/tsan/signal_segv_handler.cc new file mode 100644 index 000000000000..2d806eef6764 --- /dev/null +++ b/test/tsan/signal_segv_handler.cc @@ -0,0 +1,39 @@ +// RUN: %clang_tsan -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" %run %t 2>&1 | FileCheck %s + +// JVM uses SEGV to preempt threads. All threads do a load from a known address +// periodically. When runtime needs to preempt threads, it unmaps the page. +// Threads start triggering SEGV one by one. The signal handler blocks +// threads while runtime does its thing. Then runtime maps the page again +// and resumes the threads. +// Previously this pattern conflicted with stop-the-world machinery, +// because it briefly reset SEGV handler to SIG_DFL. +// As the consequence JVM just silently died. + +// This test sets memory flushing rate to maximum, then does series of +// "benign" SEGVs that are handled by signal handler, and ensures that +// the process survive. + +#include "test.h" +#include <signal.h> +#include <sys/mman.h> + +void *guard; + +void handler(int signo, siginfo_t *info, void *uctx) { + mprotect(guard, 4096, PROT_READ | PROT_WRITE); +} + +int main() { + struct sigaction a; + a.sa_sigaction = handler; + a.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &a, 0); + guard = mmap(0, 4096, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); + for (int i = 0; i < 1000000; i++) { + mprotect(guard, 4096, PROT_NONE); + *(int*)guard = 1; + } + fprintf(stderr, "DONE\n"); +} + +// CHECK: DONE diff --git a/test/tsan/test.h b/test/tsan/test.h index 4496e56cda87..bb861b07745e 100644 --- a/test/tsan/test.h +++ b/test/tsan/test.h @@ -29,3 +29,12 @@ void barrier_init(pthread_barrier_t *barrier, unsigned count) { // Default instance of the barrier, but a test can declare more manually. pthread_barrier_t barrier; +void print_address(void *address) { +// On FreeBSD, the %p conversion specifier works as 0x%x and thus does not match +// to the format used in the diagnotic message. +#ifdef __x86_64__ + fprintf(stderr, "0x%012lx", (unsigned long) address); +#elif defined(__mips64) + fprintf(stderr, "0x%010lx", (unsigned long) address); +#endif +} diff --git a/test/ubsan/TestCases/TypeCheck/Function/function.cpp b/test/ubsan/TestCases/TypeCheck/Function/function.cpp index deca77d459c0..2609c6a8f666 100644 --- a/test/ubsan/TestCases/TypeCheck/Function/function.cpp +++ b/test/ubsan/TestCases/TypeCheck/Function/function.cpp @@ -12,13 +12,24 @@ void f() {} void g(int x) {} -int main(void) { - // CHECK: runtime error: call to function f() through pointer to incorrect function type 'void (*)(int)' +void make_valid_call() { + // CHECK-NOT: runtime error: call to function g + reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(g))(42); +} + +void make_invalid_call() { + // CHECK: function.cpp:25:3: runtime error: call to function f() through pointer to incorrect function type 'void (*)(int)' // CHECK-NEXT: function.cpp:11: note: f() defined here - // NOSYM: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)' + // NOSYM: function.cpp:25:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)' // NOSYM-NEXT: ({{.*}}+0x{{.*}}): note: (unknown) defined here reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(f))(42); +} - // CHECK-NOT: runtime error: call to function g - reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(g))(42); +int main(void) { + make_valid_call(); + make_invalid_call(); + // Check that no more errors will be printed. + // CHECK-NOT: runtime error: call to function + // NOSYM-NOT: runtime error: call to function + make_invalid_call(); } diff --git a/test/ubsan/TestCases/TypeCheck/null.cpp b/test/ubsan/TestCases/TypeCheck/null.cpp index 2a90f7fb956b..190dc30e5dfe 100644 --- a/test/ubsan/TestCases/TypeCheck/null.cpp +++ b/test/ubsan/TestCases/TypeCheck/null.cpp @@ -18,21 +18,21 @@ int main(int, char **argv) { switch (argv[1][0]) { case 'l': - // CHECK-LOAD: null.cpp:22:12: runtime error: load of null pointer of type 'int' + // CHECK-LOAD: null.cpp:[[@LINE+1]]:12: runtime error: load of null pointer of type 'int' return *p; case 's': - // CHECK-STORE: null.cpp:25:5: runtime error: store to null pointer of type 'int' + // CHECK-STORE: null.cpp:[[@LINE+1]]:5: runtime error: store to null pointer of type 'int' *p = 1; break; case 'r': - // CHECK-REFERENCE: null.cpp:29:15: runtime error: reference binding to null pointer of type 'int' + // CHECK-REFERENCE: null.cpp:[[@LINE+1]]:15: runtime error: reference binding to null pointer of type 'int' {int &r = *p;} break; case 'm': - // CHECK-MEMBER: null.cpp:33:15: runtime error: member access within null pointer of type 'S' + // CHECK-MEMBER: null.cpp:[[@LINE+1]]:15: runtime error: member access within null pointer of type 'S' return s->k; case 'f': - // CHECK-MEMFUN: null.cpp:36:12: runtime error: member call on null pointer of type 'S' + // CHECK-MEMFUN: null.cpp:[[@LINE+1]]:12: runtime error: member call on null pointer of type 'S' return s->f(); } } diff --git a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp index 033da24451c2..806e45c7d357 100644 --- a/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp +++ b/test/ubsan/TestCases/TypeCheck/vptr-virtual-base.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t +// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t // RUN: not %run %t 2>&1 | FileCheck %s // FIXME: This test produces linker errors on Darwin. diff --git a/test/ubsan/TestCases/TypeCheck/vptr.cpp b/test/ubsan/TestCases/TypeCheck/vptr.cpp index 98eac271c3a1..1f8ee02641a8 100644 --- a/test/ubsan/TestCases/TypeCheck/vptr.cpp +++ b/test/ubsan/TestCases/TypeCheck/vptr.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx -fsanitize=vptr -g %s -O3 -o %t +// RUN: %clangxx -frtti -fsanitize=vptr -g %s -O3 -o %t // RUN: %run %t rT && %run %t mT && %run %t fT && %run %t cT // RUN: %run %t rU && %run %t mU && %run %t fU && %run %t cU // RUN: %run %t rS && %run %t rV && %run %t oV @@ -12,16 +12,16 @@ // RUN: %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --strict-whitespace // RUN: (echo "vptr_check:S"; echo "vptr_check:T"; echo "vptr_check:U") > %t.supp -// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mS 2>&1 -// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fS 2>&1 -// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cS 2>&1 -// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mV 2>&1 -// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fV 2>&1 -// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cV 2>&1 -// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t oU 2>&1 +// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mS 2>&1 +// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fS 2>&1 +// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cS 2>&1 +// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mV 2>&1 +// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fV 2>&1 +// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cV 2>&1 +// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t oU 2>&1 // RUN: echo "vptr_check:S" > %t.loc-supp -// RUN: ASAN_OPTIONS="suppressions='%t.loc-supp'" UBSAN_OPTIONS="suppressions='%t.loc-supp':halt_on_error=1" not %run %t x- 2>&1 | FileCheck %s --check-prefix=CHECK-LOC-SUPPRESS +// RUN: UBSAN_OPTIONS="suppressions='%t.loc-supp':halt_on_error=1" not %run %t x- 2>&1 | FileCheck %s --check-prefix=CHECK-LOC-SUPPRESS // FIXME: This test produces linker errors on Darwin. // XFAIL: darwin |