diff options
Diffstat (limited to 'lib/sanitizer_common/tests')
22 files changed, 684 insertions, 109 deletions
diff --git a/lib/sanitizer_common/tests/CMakeLists.txt b/lib/sanitizer_common/tests/CMakeLists.txt index 25e57507ad14..5b66917b05b0 100644 --- a/lib/sanitizer_common/tests/CMakeLists.txt +++ b/lib/sanitizer_common/tests/CMakeLists.txt @@ -5,20 +5,24 @@ set(SANITIZER_UNITTESTS sanitizer_atomic_test.cc sanitizer_common_test.cc sanitizer_flags_test.cc + sanitizer_ioctl_test.cc sanitizer_libc_test.cc sanitizer_linux_test.cc sanitizer_list_test.cc sanitizer_mutex_test.cc + sanitizer_nolibc_test.cc + sanitizer_posix_test.cc sanitizer_printf_test.cc sanitizer_scanf_interceptor_test.cc sanitizer_stackdepot_test.cc sanitizer_stacktrace_test.cc sanitizer_stoptheworld_test.cc + sanitizer_suppressions_test.cc sanitizer_test_main.cc - sanitizer_thread_registry_test.cc - ) + sanitizer_thread_registry_test.cc) -set(SANITIZER_TEST_HEADERS) +set(SANITIZER_TEST_HEADERS + sanitizer_test_utils.h) foreach(header ${SANITIZER_HEADERS}) list(APPEND SANITIZER_TEST_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../${header}) endforeach() @@ -86,6 +90,24 @@ macro(add_sanitizer_tests_for_arch arch) DEPS ${SANITIZER_TEST_OBJECTS} ${SANITIZER_COMMON_LIB} LINK_FLAGS ${SANITIZER_TEST_LINK_FLAGS_COMMON} -lpthread ${TARGET_FLAGS}) + + if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" AND "${arch}" STREQUAL "x86_64") + # Test that the libc-independent part of sanitizer_common is indeed + # independent of libc, by linking this binary without libc (here) and + # executing it (unit test in sanitizer_nolibc_test.cc). + clang_compile(sanitizer_nolibc_test_main.${arch}.o + sanitizer_nolibc_test_main.cc + CFLAGS ${SANITIZER_TEST_CFLAGS_COMMON} ${TARGET_FLAGS} + DEPS ${SANITIZER_RUNTIME_LIBRARIES} ${SANITIZER_TEST_HEADERS}) + add_compiler_rt_test(SanitizerUnitTests "Sanitizer-${arch}-Test-Nolibc" + OBJECTS sanitizer_nolibc_test_main.${arch}.o + -Wl,-whole-archive + libRTSanitizerCommon.test.nolibc.${arch}.a + -Wl,-no-whole-archive + DEPS sanitizer_nolibc_test_main.${arch}.o + RTSanitizerCommon.test.nolibc.${arch} + LINK_FLAGS -nostdlib ${TARGET_FLAGS}) + endif() endmacro() if(COMPILER_RT_CAN_EXECUTE_TESTS) @@ -99,6 +121,8 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS) add_sanitizer_common_lib("RTSanitizerCommon.test.x86_64" $<TARGET_OBJECTS:RTSanitizerCommon.x86_64> $<TARGET_OBJECTS:RTSanitizerCommonLibc.x86_64>) + add_sanitizer_common_lib("RTSanitizerCommon.test.nolibc.x86_64" + $<TARGET_OBJECTS:RTSanitizerCommon.x86_64>) endif() if(CAN_TARGET_i386) add_sanitizer_common_lib("RTSanitizerCommon.test.i386" diff --git a/lib/sanitizer_common/tests/lit.cfg b/lib/sanitizer_common/tests/lit.cfg deleted file mode 100644 index 303d56c91079..000000000000 --- a/lib/sanitizer_common/tests/lit.cfg +++ /dev/null @@ -1,28 +0,0 @@ -# -*- Python -*- - -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 attributes common for all compiler-rt projects. -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) - -# Setup config name. -config.name = 'SanitizerCommon-Unit' - -# Setup test source and exec root. For unit tests, we define -# it as build directory with sanitizer_common unit tests. -llvm_obj_root = get_required_attr(config, "llvm_obj_root") -config.test_exec_root = os.path.join(llvm_obj_root, "projects", - "compiler-rt", "lib", - "sanitizer_common", "tests") -config.test_source_root = config.test_exec_root diff --git a/lib/sanitizer_common/tests/lit.site.cfg.in b/lib/sanitizer_common/tests/lit.site.cfg.in index 50485aa16ec2..5ceb9e4c5c28 100644 --- a/lib/sanitizer_common/tests/lit.site.cfg.in +++ b/lib/sanitizer_common/tests/lit.site.cfg.in @@ -1,16 +1,14 @@ ## Autogenerated by LLVM/Clang configuration. # Do not edit! -config.llvm_obj_root = "@LLVM_BINARY_DIR@" -config.llvm_src_root = "@LLVM_SOURCE_DIR@" -config.compiler_rt_src_root = "@COMPILER_RT_SOURCE_DIR@" -config.llvm_build_mode = "@LLVM_BUILD_MODE@" +# Load common config for all compiler-rt unit tests. +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/lib/lit.common.unit.configured") -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)) +# Setup config name. +config.name = 'SanitizerCommon-Unit' -# Let the main config do the real work. -lit.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg") +# Setup test source and exec root. For unit tests, we define +# it as build directory with sanitizer_common tests. +config.test_exec_root = os.path.join("@COMPILER_RT_BINARY_DIR@", "lib", + "sanitizer_common", "tests") +config.test_source_root = config.test_exec_root diff --git a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc index de949ca7defe..d92a07fe4c2d 100644 --- a/lib/sanitizer_common/tests/sanitizer_allocator_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_allocator_test.cc @@ -12,7 +12,9 @@ // //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_allocator.h" +#include "sanitizer_common/sanitizer_allocator_internal.h" #include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_test_utils.h" @@ -67,6 +69,10 @@ TEST(SanitizerCommon, CompactSizeClassMap) { TestSizeClassMap<CompactSizeClassMap>(); } +TEST(SanitizerCommon, InternalSizeClassMap) { + TestSizeClassMap<InternalSizeClassMap>(); +} + template <class Allocator> void TestSizeClassAllocator() { Allocator *a = new Allocator; @@ -411,12 +417,20 @@ void TestCombinedAllocator() { memset(&cache, 0, sizeof(cache)); a->InitCache(&cache); + bool allocator_may_return_null = common_flags()->allocator_may_return_null; + common_flags()->allocator_may_return_null = true; EXPECT_EQ(a->Allocate(&cache, -1, 1), (void*)0); EXPECT_EQ(a->Allocate(&cache, -1, 1024), (void*)0); EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1024, 1), (void*)0); EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1024, 1024), (void*)0); EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1023, 1024), (void*)0); + common_flags()->allocator_may_return_null = false; + EXPECT_DEATH(a->Allocate(&cache, -1, 1), + "allocator is terminating the process"); + // Restore the original value. + common_flags()->allocator_may_return_null = allocator_may_return_null; + const uptr kNumAllocs = 100000; const uptr kNumIter = 10; for (uptr iter = 0; iter < kNumIter; iter++) { @@ -611,6 +625,11 @@ TEST(Allocator, Stress) { } } +TEST(Allocator, InternalAllocFailure) { + EXPECT_DEATH(Ident(InternalAlloc(10 << 20)), + "Unexpected mmap in InternalAllocator!"); +} + TEST(Allocator, ScopedBuffer) { const int kSize = 512; { @@ -625,16 +644,9 @@ TEST(Allocator, ScopedBuffer) { } } -class IterationTestCallback { - public: - explicit IterationTestCallback(std::set<void *> *chunks) - : chunks_(chunks) {} - void operator()(void *chunk) const { - chunks_->insert(chunk); - } - private: - std::set<void *> *chunks_; -}; +void IterationTestCallback(uptr chunk, void *arg) { + reinterpret_cast<std::set<uptr> *>(arg)->insert(chunk); +} template <class Allocator> void TestSizeClassAllocatorIteration() { @@ -663,15 +675,15 @@ void TestSizeClassAllocatorIteration() { } } - std::set<void *> reported_chunks; - IterationTestCallback callback(&reported_chunks); + std::set<uptr> reported_chunks; a->ForceLock(); - a->ForEachChunk(callback); + a->ForEachChunk(IterationTestCallback, &reported_chunks); a->ForceUnlock(); for (uptr i = 0; i < allocated.size(); i++) { // Don't use EXPECT_NE. Reporting the first mismatch is enough. - ASSERT_NE(reported_chunks.find(allocated[i]), reported_chunks.end()); + ASSERT_NE(reported_chunks.find(reinterpret_cast<uptr>(allocated[i])), + reported_chunks.end()); } a->TestOnlyUnmap(); @@ -698,22 +710,61 @@ TEST(SanitizerCommon, LargeMmapAllocatorIteration) { char *allocated[kNumAllocs]; static const uptr size = 40; // Allocate some. - for (uptr i = 0; i < kNumAllocs; i++) { + for (uptr i = 0; i < kNumAllocs; i++) allocated[i] = (char *)a.Allocate(&stats, size, 1); - } - std::set<void *> reported_chunks; - IterationTestCallback callback(&reported_chunks); + std::set<uptr> reported_chunks; a.ForceLock(); - a.ForEachChunk(callback); + a.ForEachChunk(IterationTestCallback, &reported_chunks); a.ForceUnlock(); for (uptr i = 0; i < kNumAllocs; i++) { // Don't use EXPECT_NE. Reporting the first mismatch is enough. - ASSERT_NE(reported_chunks.find(allocated[i]), reported_chunks.end()); + ASSERT_NE(reported_chunks.find(reinterpret_cast<uptr>(allocated[i])), + reported_chunks.end()); + } + for (uptr i = 0; i < kNumAllocs; i++) + a.Deallocate(&stats, allocated[i]); +} + +TEST(SanitizerCommon, LargeMmapAllocatorBlockBegin) { + LargeMmapAllocator<> a; + a.Init(); + AllocatorStats stats; + stats.Init(); + + static const uptr kNumAllocs = 1024; + static const uptr kNumExpectedFalseLookups = 10000000; + char *allocated[kNumAllocs]; + static const uptr size = 4096; + // Allocate some. + for (uptr i = 0; i < kNumAllocs; i++) { + allocated[i] = (char *)a.Allocate(&stats, size, 1); } + + a.ForceLock(); + for (uptr i = 0; i < kNumAllocs * kNumAllocs; i++) { + // if ((i & (i - 1)) == 0) fprintf(stderr, "[%zd]\n", i); + char *p1 = allocated[i % kNumAllocs]; + EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1)); + EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1 + size / 2)); + EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1 + size - 1)); + EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1 - 100)); + } + + for (uptr i = 0; i < kNumExpectedFalseLookups; i++) { + void *p = reinterpret_cast<void *>(i % 1024); + EXPECT_EQ((void *)0, a.GetBlockBeginFastLocked(p)); + p = reinterpret_cast<void *>(~0L - (i % 1024)); + EXPECT_EQ((void *)0, a.GetBlockBeginFastLocked(p)); + } + a.ForceUnlock(); + + for (uptr i = 0; i < kNumAllocs; i++) + a.Deallocate(&stats, allocated[i]); } + #if SANITIZER_WORDSIZE == 64 // Regression test for out-of-memory condition in PopulateFreeList(). TEST(SanitizerCommon, SizeClassAllocator64PopulateFreeListOOM) { diff --git a/lib/sanitizer_common/tests/sanitizer_common_test.cc b/lib/sanitizer_common/tests/sanitizer_common_test.cc index 424c279d4ada..608f90487a7b 100644 --- a/lib/sanitizer_common/tests/sanitizer_common_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_common_test.cc @@ -10,7 +10,9 @@ // This file is a part of ThreadSanitizer/AddressSanitizer runtime. // //===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_allocator_internal.h" #include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_platform.h" #include "gtest/gtest.h" @@ -97,8 +99,8 @@ TEST(SanitizerCommon, SanitizerSetThreadName) { } #endif -TEST(SanitizerCommon, InternalVector) { - InternalVector<uptr> vector(1); +TEST(SanitizerCommon, InternalMmapVector) { + InternalMmapVector<uptr> vector(1); for (uptr i = 0; i < 100; i++) { EXPECT_EQ(i, vector.size()); vector.push_back(i); @@ -158,4 +160,100 @@ TEST(SanitizerCommon, ThreadStackTlsWorker) { pthread_join(t, 0); } +bool UptrLess(uptr a, uptr b) { + return a < b; +} + +TEST(SanitizerCommon, InternalBinarySearch) { + static const uptr kSize = 5; + uptr arr[kSize]; + for (uptr i = 0; i < kSize; i++) arr[i] = i * i; + + for (uptr i = 0; i < kSize; i++) + ASSERT_EQ(InternalBinarySearch(arr, 0, kSize, i * i, UptrLess), i); + + ASSERT_EQ(InternalBinarySearch(arr, 0, kSize, 7, UptrLess), kSize + 1); +} + +#if SANITIZER_LINUX && !SANITIZER_ANDROID +TEST(SanitizerCommon, FindPathToBinary) { + char *true_path = FindPathToBinary("true"); + EXPECT_NE((char*)0, internal_strstr(true_path, "/bin/true")); + InternalFree(true_path); + EXPECT_EQ(0, FindPathToBinary("unexisting_binary.ergjeorj")); +} +#endif + +TEST(SanitizerCommon, StripPathPrefix) { + EXPECT_EQ(0, StripPathPrefix(0, "prefix")); + EXPECT_STREQ("foo", StripPathPrefix("foo", 0)); + EXPECT_STREQ("dir/file.cc", + StripPathPrefix("/usr/lib/dir/file.cc", "/usr/lib/")); + EXPECT_STREQ("/file.cc", StripPathPrefix("/usr/myroot/file.cc", "/myroot")); + EXPECT_STREQ("file.h", StripPathPrefix("/usr/lib/./file.h", "/usr/lib/")); +} + +TEST(SanitizerCommon, InternalScopedString) { + InternalScopedString str(10); + EXPECT_EQ(0U, str.length()); + EXPECT_STREQ("", str.data()); + + str.append("foo"); + EXPECT_EQ(3U, str.length()); + EXPECT_STREQ("foo", str.data()); + + int x = 1234; + str.append("%d", x); + EXPECT_EQ(7U, str.length()); + EXPECT_STREQ("foo1234", str.data()); + + str.append("%d", x); + EXPECT_EQ(9U, str.length()); + EXPECT_STREQ("foo123412", str.data()); + + str.clear(); + EXPECT_EQ(0U, str.length()); + EXPECT_STREQ("", str.data()); + + str.append("0123456789"); + EXPECT_EQ(9U, str.length()); + EXPECT_STREQ("012345678", str.data()); +} + +TEST(SanitizerCommon, PrintSourceLocation) { + InternalScopedString str(128); + PrintSourceLocation(&str, "/dir/file.cc", 10, 5); + EXPECT_STREQ("/dir/file.cc:10:5", str.data()); + + str.clear(); + PrintSourceLocation(&str, "/dir/file.cc", 11, 0); + EXPECT_STREQ("/dir/file.cc:11", str.data()); + + str.clear(); + PrintSourceLocation(&str, "/dir/file.cc", 0, 0); + EXPECT_STREQ("/dir/file.cc", str.data()); + + // Check that we strip file prefix if necessary. + const char *old_strip_path_prefix = common_flags()->strip_path_prefix; + common_flags()->strip_path_prefix = "/dir/"; + str.clear(); + PrintSourceLocation(&str, "/dir/file.cc", 10, 5); + EXPECT_STREQ("file.cc:10:5", str.data()); + common_flags()->strip_path_prefix = old_strip_path_prefix; +} + +TEST(SanitizerCommon, PrintModuleAndOffset) { + InternalScopedString str(128); + PrintModuleAndOffset(&str, "/dir/exe", 0x123); + EXPECT_STREQ("(/dir/exe+0x123)", str.data()); + + // Check that we strip file prefix if necessary. + const char *old_strip_path_prefix = common_flags()->strip_path_prefix; + common_flags()->strip_path_prefix = "/dir/"; + str.clear(); + PrintModuleAndOffset(&str, "/dir/exe", 0x123); + EXPECT_STREQ("(exe+0x123)", str.data()); + common_flags()->strip_path_prefix = old_strip_path_prefix; +} + } // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc b/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc new file mode 100644 index 000000000000..154d9860b79f --- /dev/null +++ b/lib/sanitizer_common/tests/sanitizer_ioctl_test.cc @@ -0,0 +1,77 @@ +//===-- sanitizer_ioctl_test.cc -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Tests for ioctl interceptor implementation in sanitizer_common. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_LINUX + +#include <linux/input.h> +#include <vector> + +#include "interception/interception.h" +#include "sanitizer_test_utils.h" +#include "sanitizer_common/sanitizer_platform_limits_posix.h" +#include "sanitizer_common/sanitizer_common.h" +#include "gtest/gtest.h" + + +using namespace __sanitizer; + +#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, sz) \ + do { \ + (void) ctx; \ + (void) ptr; \ + (void) sz; \ + } while (0) +#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sz) \ + do { \ + (void) ctx; \ + (void) ptr; \ + (void) sz; \ + } while (0) + +#include "sanitizer_common/sanitizer_common_interceptors_ioctl.inc" + +static struct IoctlInit { + IoctlInit() { + ioctl_init(); + // Avoid unused function warnings. + (void)&ioctl_common_pre; + (void)&ioctl_common_post; + } +} ioctl_static_initializer; + +TEST(SanitizerIoctl, Fixup) { + EXPECT_EQ((unsigned)FIONBIO, ioctl_request_fixup(FIONBIO)); + + EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(0, 16))); + EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(1, 16))); + EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(1, 17))); + EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(31, 16))); + EXPECT_NE(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(32, 16))); + + EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(0))); + EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(5))); + EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(63))); + EXPECT_NE(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(64))); + + EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(0))); + EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(5))); + EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(63))); + EXPECT_NE(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(64))); + + const ioctl_desc *desc = ioctl_lookup(EVIOCGKEY(16)); + EXPECT_NE((void *)0, desc); + EXPECT_EQ(EVIOCGKEY(0), desc->req); +} + +#endif // SANITIZER_LINUX diff --git a/lib/sanitizer_common/tests/sanitizer_libc_test.cc b/lib/sanitizer_common/tests/sanitizer_libc_test.cc index 39c29d357327..c4f3d8033c2d 100644 --- a/lib/sanitizer_common/tests/sanitizer_libc_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_libc_test.cc @@ -115,3 +115,10 @@ TEST(SanitizerCommon, FileOps) { internal_close(fd); } +TEST(SanitizerCommon, InternalStrFunctions) { + const char *haystack = "haystack"; + EXPECT_EQ(haystack + 2, internal_strchr(haystack, 'y')); + EXPECT_EQ(haystack + 2, internal_strchrnul(haystack, 'y')); + EXPECT_EQ(0, internal_strchr(haystack, 'z')); + EXPECT_EQ(haystack + 8, internal_strchrnul(haystack, 'z')); +} diff --git a/lib/sanitizer_common/tests/sanitizer_linux_test.cc b/lib/sanitizer_common/tests/sanitizer_linux_test.cc index b18aeb030acf..592d9c3eeaf5 100644 --- a/lib/sanitizer_common/tests/sanitizer_linux_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_linux_test.cc @@ -19,9 +19,6 @@ #include "sanitizer_common/sanitizer_common.h" #include "gtest/gtest.h" -#ifdef __x86_64__ -#include <asm/prctl.h> -#endif #include <pthread.h> #include <sched.h> #include <stdlib.h> @@ -29,10 +26,6 @@ #include <algorithm> #include <vector> -#ifdef __x86_64__ -extern "C" int arch_prctl(int code, __sanitizer::uptr *addr); -#endif - namespace __sanitizer { struct TidReporterArgument { @@ -202,23 +195,37 @@ TEST(SanitizerCommon, SetEnvTest) { EXPECT_EQ(0, getenv(kEnvName)); } -#ifdef __x86_64__ -// libpthread puts the thread descriptor (%fs:0x0) at the end of stack space. -void *thread_descriptor_test_func(void *arg) { - uptr fs; - arch_prctl(ARCH_GET_FS, &fs); +#if defined(__x86_64__) || defined(__i386__) +void *thread_self_offset_test_func(void *arg) { + bool result = + *(uptr *)((char *)ThreadSelf() + ThreadSelfOffset()) == ThreadSelf(); + return (void *)result; +} + +TEST(SanitizerLinux, ThreadSelfOffset) { + EXPECT_TRUE((bool)thread_self_offset_test_func(0)); + pthread_t tid; + void *result; + ASSERT_EQ(0, pthread_create(&tid, 0, thread_self_offset_test_func, 0)); + ASSERT_EQ(0, pthread_join(tid, &result)); + EXPECT_TRUE((bool)result); +} + +// libpthread puts the thread descriptor at the end of stack space. +void *thread_descriptor_size_test_func(void *arg) { + uptr descr_addr = ThreadSelf(); pthread_attr_t attr; pthread_getattr_np(pthread_self(), &attr); void *stackaddr; - uptr stacksize; + size_t stacksize; pthread_attr_getstack(&attr, &stackaddr, &stacksize); - return (void *)((uptr)stackaddr + stacksize - fs); + return (void *)((uptr)stackaddr + stacksize - descr_addr); } TEST(SanitizerLinux, ThreadDescriptorSize) { pthread_t tid; void *result; - pthread_create(&tid, 0, thread_descriptor_test_func, 0); + ASSERT_EQ(0, pthread_create(&tid, 0, thread_descriptor_size_test_func, 0)); ASSERT_EQ(0, pthread_join(tid, &result)); EXPECT_EQ((uptr)result, ThreadDescriptorSize()); } diff --git a/lib/sanitizer_common/tests/sanitizer_mutex_test.cc b/lib/sanitizer_common/tests/sanitizer_mutex_test.cc index 1dc9bef20710..06f742b41796 100644 --- a/lib/sanitizer_common/tests/sanitizer_mutex_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_mutex_test.cc @@ -65,7 +65,6 @@ class TestData { }; const int kThreads = 8; -const int kWriteRate = 1024; #if SANITIZER_DEBUG const int kIters = 16*1024; #else diff --git a/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc b/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc new file mode 100644 index 000000000000..d0d5a5e13898 --- /dev/null +++ b/lib/sanitizer_common/tests/sanitizer_nolibc_test.cc @@ -0,0 +1,31 @@ +//===-- sanitizer_nolibc_test.cc ------------------------------------------===// +// +// 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 ThreadSanitizer/AddressSanitizer runtime. +// Tests for libc independence of sanitizer_common. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" + +#include "gtest/gtest.h" + +#include <stdlib.h> + +extern const char *argv0; + +#if SANITIZER_LINUX && defined(__x86_64__) +TEST(SanitizerCommon, NolibcMain) { + std::string NolibcTestPath = argv0; + NolibcTestPath += "-Nolibc"; + int status = system(NolibcTestPath.c_str()); + EXPECT_EQ(true, WIFEXITED(status)); + EXPECT_EQ(0, WEXITSTATUS(status)); +} +#endif diff --git a/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc b/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc new file mode 100644 index 000000000000..72df621d07ff --- /dev/null +++ b/lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc @@ -0,0 +1,19 @@ +//===-- sanitizer_nolibc_test_main.cc -------------------------------------===// +// +// 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 ThreadSanitizer/AddressSanitizer runtime. +// Tests for libc independence of sanitizer_common. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_libc.h" + +extern "C" void _start() { + internal__exit(0); +} diff --git a/lib/sanitizer_common/tests/sanitizer_posix_test.cc b/lib/sanitizer_common/tests/sanitizer_posix_test.cc new file mode 100644 index 000000000000..035899c83022 --- /dev/null +++ b/lib/sanitizer_common/tests/sanitizer_posix_test.cc @@ -0,0 +1,62 @@ +//===-- sanitizer_posix_test.cc -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Tests for POSIX-specific code. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_POSIX + +#include "sanitizer_common/sanitizer_common.h" +#include "gtest/gtest.h" + +#include <pthread.h> + +namespace __sanitizer { + +static pthread_key_t key; +static bool destructor_executed; + +extern "C" +void destructor(void *arg) { + uptr iter = reinterpret_cast<uptr>(arg); + if (iter > 1) { + ASSERT_EQ(0, pthread_setspecific(key, reinterpret_cast<void *>(iter - 1))); + return; + } + destructor_executed = true; +} + +extern "C" +void *thread_func(void *arg) { + return reinterpret_cast<void*>(pthread_setspecific(key, arg)); +} + +static void SpawnThread(uptr iteration) { + destructor_executed = false; + pthread_t tid; + ASSERT_EQ(0, pthread_create(&tid, 0, &thread_func, + reinterpret_cast<void *>(iteration))); + void *retval; + ASSERT_EQ(0, pthread_join(tid, &retval)); + ASSERT_EQ(0, retval); +} + +TEST(SanitizerCommon, PthreadDestructorIterations) { + ASSERT_EQ(0, pthread_key_create(&key, &destructor)); + SpawnThread(kPthreadDestructorIterations); + EXPECT_TRUE(destructor_executed); + SpawnThread(kPthreadDestructorIterations + 1); + EXPECT_FALSE(destructor_executed); +} + +} // namespace __sanitizer + +#endif // SANITIZER_POSIX diff --git a/lib/sanitizer_common/tests/sanitizer_printf_test.cc b/lib/sanitizer_common/tests/sanitizer_printf_test.cc index b1889cd8794e..2c478cc74286 100644 --- a/lib/sanitizer_common/tests/sanitizer_printf_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_printf_test.cc @@ -104,22 +104,36 @@ TEST(Printf, OverflowPtr) { } template<typename T> -static void TestMinMax(const char *fmt, T min, T max) { +static void TestAgainstLibc(const char *fmt, T arg1, T arg2) { char buf[1024]; - uptr len = internal_snprintf(buf, sizeof(buf), fmt, min, max); + uptr len = internal_snprintf(buf, sizeof(buf), fmt, arg1, arg2); char buf2[1024]; - snprintf(buf2, sizeof(buf2), fmt, min, max); + snprintf(buf2, sizeof(buf2), fmt, arg1, arg2); EXPECT_EQ(len, strlen(buf)); EXPECT_STREQ(buf2, buf); } TEST(Printf, MinMax) { - TestMinMax<int>("%d-%d", INT_MIN, INT_MAX); // NOLINT - TestMinMax<long>("%zd-%zd", LONG_MIN, LONG_MAX); // NOLINT - TestMinMax<unsigned>("%u-%u", 0, UINT_MAX); // NOLINT - TestMinMax<unsigned long>("%zu-%zu", 0, ULONG_MAX); // NOLINT - TestMinMax<unsigned>("%x-%x", 0, UINT_MAX); // NOLINT - TestMinMax<unsigned long>("%zx-%zx", 0, ULONG_MAX); // NOLINT + TestAgainstLibc<int>("%d-%d", INT_MIN, INT_MAX); // NOLINT + TestAgainstLibc<long>("%zd-%zd", LONG_MIN, LONG_MAX); // NOLINT + TestAgainstLibc<unsigned>("%u-%u", 0, UINT_MAX); // NOLINT + TestAgainstLibc<unsigned long>("%zu-%zu", 0, ULONG_MAX); // NOLINT + TestAgainstLibc<unsigned>("%x-%x", 0, UINT_MAX); // NOLINT + TestAgainstLibc<unsigned long>("%zx-%zx", 0, ULONG_MAX); // NOLINT + Report("%zd\n", LONG_MIN); +} + +TEST(Printf, Padding) { + TestAgainstLibc<int>("%3d - %3d", 1, 0); + TestAgainstLibc<int>("%3d - %3d", -1, 123); + TestAgainstLibc<int>("%3d - %3d", -1, -123); + TestAgainstLibc<int>("%3d - %3d", 12, 1234); + TestAgainstLibc<int>("%3d - %3d", -12, -1234); + TestAgainstLibc<int>("%03d - %03d", 1, 0); + TestAgainstLibc<int>("%03d - %03d", -1, 123); + TestAgainstLibc<int>("%03d - %03d", -1, -123); + TestAgainstLibc<int>("%03d - %03d", 12, 1234); + TestAgainstLibc<int>("%03d - %03d", -12, -1234); } } // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc b/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc new file mode 100644 index 000000000000..d16e2eebf98e --- /dev/null +++ b/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc @@ -0,0 +1,30 @@ +//===-- sanitizer_procmaps_test.cc ----------------------------------------===// +// +// 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 ThreadSanitizer/AddressSanitizer runtime. +// +//===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_procmaps.h" +//#include "sanitizer_common/sanitizer_internal_defs.h" +//#include "sanitizer_common/sanitizer_libc.h" +#include "gtest/gtest.h" + +namespace __sanitizer { + +#ifdef SANITIZER_LINUX +TEST(ProcMaps, CodeRange) { + uptr start, end; + bool res = GetCodeRangeForFile("[vdso]", &start, &end); + EXPECT_EQ(res, true); + EXPECT_GT(start, (uptr)0); + EXPECT_LT(start, end); +} +#endif + +} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc b/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc index 1df2bcfd4bec..e0354062508f 100644 --- a/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc @@ -169,7 +169,7 @@ TEST(SanitizerCommonInterceptors, Scanf) { testScanfPartial("%d%d%d%d //3\n", 3, 3, I, I, I); testScanfPartial("%d%d%d%d //4\n", 4, 4, I, I, I, I); - testScanfPartial("%d%n%n%d //1\n", 1, 1, I); + testScanfPartial("%d%n%n%d //1\n", 1, 3, I, I, I); testScanfPartial("%d%n%n%d //2\n", 2, 4, I, I, I, I); testScanfPartial("%d%n%n%d %s %s", 3, 5, I, I, I, I, scanf_buf_size); diff --git a/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc b/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc index 5350c2ab8dbc..5c075d53ebff 100644 --- a/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc @@ -66,4 +66,27 @@ TEST(SanitizerCommon, StackDepotSeveral) { EXPECT_NE(i1, i2); } +TEST(SanitizerCommon, StackDepotReverseMap) { + uptr s1[] = {1, 2, 3, 4, 5}; + uptr s2[] = {7, 1, 3, 0}; + uptr s3[] = {10, 2, 5, 3}; + uptr s4[] = {1, 3, 2, 5}; + u32 ids[4] = {0}; + ids[0] = StackDepotPut(s1, ARRAY_SIZE(s1)); + ids[1] = StackDepotPut(s2, ARRAY_SIZE(s2)); + ids[2] = StackDepotPut(s3, ARRAY_SIZE(s3)); + ids[3] = StackDepotPut(s4, ARRAY_SIZE(s4)); + + StackDepotReverseMap map; + + for (uptr i = 0; i < 4; i++) { + uptr sz_depot, sz_map; + const uptr *sp_depot, *sp_map; + sp_depot = StackDepotGet(ids[i], &sz_depot); + sp_map = map.Get(ids[i], &sz_map); + EXPECT_EQ(sz_depot, sz_map); + EXPECT_EQ(sp_depot, sp_map); + } +} + } // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc b/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc index 3d352cb97a5e..2b842cd8134a 100644 --- a/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc @@ -20,6 +20,13 @@ namespace __sanitizer { class FastUnwindTest : public ::testing::Test { protected: virtual void SetUp(); + bool TryFastUnwind(uptr max_depth) { + if (!StackTrace::WillUseFastUnwind(true)) + return false; + trace.Unwind(max_depth, start_pc, (uptr)&fake_stack[0], fake_top, + fake_bottom, true); + return true; + } uptr fake_stack[10]; uptr start_pc; @@ -47,16 +54,11 @@ void FastUnwindTest::SetUp() { // Bottom is one slot before the start because FastUnwindStack uses >. fake_bottom = (uptr)&fake_stack[-1]; start_pc = PC(0); - - // This is common setup done by __asan::GetStackTrace(). - trace.size = 0; - trace.max_size = ARRAY_SIZE(fake_stack); - trace.trace[0] = start_pc; } TEST_F(FastUnwindTest, Basic) { - trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], - fake_top, fake_bottom); + if (!TryFastUnwind(kStackTraceMax)) + return; // Should get all on-stack retaddrs and start_pc. EXPECT_EQ(6U, trace.size); EXPECT_EQ(start_pc, trace.trace[0]); @@ -69,8 +71,8 @@ TEST_F(FastUnwindTest, Basic) { TEST_F(FastUnwindTest, FramePointerLoop) { // Make one fp point to itself. fake_stack[4] = (uptr)&fake_stack[4]; - trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], - fake_top, fake_bottom); + if (!TryFastUnwind(kStackTraceMax)) + return; // Should get all on-stack retaddrs up to the 4th slot and start_pc. EXPECT_EQ(4U, trace.size); EXPECT_EQ(start_pc, trace.trace[0]); @@ -82,8 +84,8 @@ TEST_F(FastUnwindTest, FramePointerLoop) { TEST_F(FastUnwindTest, MisalignedFramePointer) { // Make one fp misaligned. fake_stack[4] += 3; - trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], - fake_top, fake_bottom); + if (!TryFastUnwind(kStackTraceMax)) + return; // Should get all on-stack retaddrs up to the 4th slot and start_pc. EXPECT_EQ(4U, trace.size); EXPECT_EQ(start_pc, trace.trace[0]); @@ -92,5 +94,12 @@ TEST_F(FastUnwindTest, MisalignedFramePointer) { } } +TEST_F(FastUnwindTest, OneFrameStackTrace) { + if (!TryFastUnwind(1)) + return; + EXPECT_EQ(1U, trace.size); + EXPECT_EQ(start_pc, trace.trace[0]); + EXPECT_EQ((uptr)&fake_stack[0], trace.top_frame_bp); +} } // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc b/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc index a5f8516df575..b6786ba8b013 100644 --- a/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_LINUX +#if SANITIZER_LINUX && defined(__x86_64__) #include "sanitizer_common/sanitizer_stoptheworld.h" #include "gtest/gtest.h" @@ -191,4 +191,4 @@ TEST(StopTheWorld, SuspendThreadsAdvanced) { } // namespace __sanitizer -#endif // SANITIZER_LINUX +#endif // SANITIZER_LINUX && defined(__x86_64__) diff --git a/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc b/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc new file mode 100644 index 000000000000..ea8741d4f01a --- /dev/null +++ b/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc @@ -0,0 +1,152 @@ +//===-- sanitizer_suppressions_test.cc ------------------------------------===// +// +// 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 ThreadSanitizer/AddressSanitizer runtime. +// +//===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_suppressions.h" +#include "gtest/gtest.h" + +#include <string.h> + +namespace __sanitizer { + +static bool MyMatch(const char *templ, const char *func) { + char tmp[1024]; + strcpy(tmp, templ); // NOLINT + return TemplateMatch(tmp, func); +} + +TEST(Suppressions, Match) { + EXPECT_TRUE(MyMatch("foobar$", "foobar")); + + EXPECT_TRUE(MyMatch("foobar", "foobar")); + EXPECT_TRUE(MyMatch("*foobar*", "foobar")); + EXPECT_TRUE(MyMatch("foobar", "prefix_foobar_postfix")); + EXPECT_TRUE(MyMatch("*foobar*", "prefix_foobar_postfix")); + EXPECT_TRUE(MyMatch("foo*bar", "foo_middle_bar")); + EXPECT_TRUE(MyMatch("foo*bar", "foobar")); + EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_bar_another_baz")); + EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_barbaz")); + EXPECT_TRUE(MyMatch("^foobar", "foobar")); + EXPECT_TRUE(MyMatch("^foobar", "foobar_postfix")); + EXPECT_TRUE(MyMatch("^*foobar", "foobar")); + EXPECT_TRUE(MyMatch("^*foobar", "prefix_foobar")); + EXPECT_TRUE(MyMatch("foobar$", "foobar")); + EXPECT_TRUE(MyMatch("foobar$", "prefix_foobar")); + EXPECT_TRUE(MyMatch("*foobar*$", "foobar")); + EXPECT_TRUE(MyMatch("*foobar*$", "foobar_postfix")); + EXPECT_TRUE(MyMatch("^foobar$", "foobar")); + + EXPECT_FALSE(MyMatch("foo", "baz")); + EXPECT_FALSE(MyMatch("foobarbaz", "foobar")); + EXPECT_FALSE(MyMatch("foobarbaz", "barbaz")); + EXPECT_FALSE(MyMatch("foo*bar", "foobaz")); + EXPECT_FALSE(MyMatch("foo*bar", "foo_baz")); + EXPECT_FALSE(MyMatch("^foobar", "prefix_foobar")); + EXPECT_FALSE(MyMatch("foobar$", "foobar_postfix")); + EXPECT_FALSE(MyMatch("^foobar$", "prefix_foobar")); + EXPECT_FALSE(MyMatch("^foobar$", "foobar_postfix")); + EXPECT_FALSE(MyMatch("foo^bar", "foobar")); + EXPECT_FALSE(MyMatch("foo$bar", "foobar")); + EXPECT_FALSE(MyMatch("foo$^bar", "foobar")); +} + +TEST(Suppressions, TypeStrings) { + CHECK(!internal_strcmp(SuppressionTypeString(SuppressionNone), "none")); + CHECK(!internal_strcmp(SuppressionTypeString(SuppressionRace), "race")); + CHECK(!internal_strcmp(SuppressionTypeString(SuppressionMutex), "mutex")); + CHECK(!internal_strcmp(SuppressionTypeString(SuppressionThread), "thread")); + CHECK(!internal_strcmp(SuppressionTypeString(SuppressionSignal), "signal")); + CHECK(!internal_strcmp(SuppressionTypeString(SuppressionLeak), "leak")); + CHECK(!internal_strcmp(SuppressionTypeString(SuppressionLib), + "called_from_lib")); + // Ensure this test is up-to-date when suppression types are added. + CHECK_EQ(SuppressionTypeCount, 7); +} + +class SuppressionContextTest : public ::testing::Test { + public: + virtual void SetUp() { ctx_ = new(placeholder_) SuppressionContext; } + virtual void TearDown() { ctx_->~SuppressionContext(); } + + protected: + InternalMmapVector<Suppression> *Suppressions() { + return &ctx_->suppressions_; + } + SuppressionContext *ctx_; + ALIGNED(64) char placeholder_[sizeof(SuppressionContext)]; +}; + +TEST_F(SuppressionContextTest, Parse) { + ctx_->Parse( + "race:foo\n" + " race:bar\n" // NOLINT + "race:baz \n" // NOLINT + "# a comment\n" + "race:quz\n" + ); // NOLINT + EXPECT_EQ((unsigned)4, ctx_->SuppressionCount()); + EXPECT_EQ((*Suppressions())[3].type, SuppressionRace); + EXPECT_EQ(0, strcmp((*Suppressions())[3].templ, "quz")); + EXPECT_EQ((*Suppressions())[2].type, SuppressionRace); + EXPECT_EQ(0, strcmp((*Suppressions())[2].templ, "baz")); + EXPECT_EQ((*Suppressions())[1].type, SuppressionRace); + EXPECT_EQ(0, strcmp((*Suppressions())[1].templ, "bar")); + EXPECT_EQ((*Suppressions())[0].type, SuppressionRace); + EXPECT_EQ(0, strcmp((*Suppressions())[0].templ, "foo")); +} + +TEST_F(SuppressionContextTest, Parse2) { + ctx_->Parse( + " # first line comment\n" // NOLINT + " race:bar \n" // NOLINT + "race:baz* *baz\n" + "# a comment\n" + "# last line comment\n" + ); // NOLINT + EXPECT_EQ((unsigned)2, ctx_->SuppressionCount()); + EXPECT_EQ((*Suppressions())[1].type, SuppressionRace); + EXPECT_EQ(0, strcmp((*Suppressions())[1].templ, "baz* *baz")); + EXPECT_EQ((*Suppressions())[0].type, SuppressionRace); + EXPECT_EQ(0, strcmp((*Suppressions())[0].templ, "bar")); +} + +TEST_F(SuppressionContextTest, Parse3) { + ctx_->Parse( + "# last suppression w/o line-feed\n" + "race:foo\n" + "race:bar" + ); // NOLINT + EXPECT_EQ((unsigned)2, ctx_->SuppressionCount()); + EXPECT_EQ((*Suppressions())[1].type, SuppressionRace); + EXPECT_EQ(0, strcmp((*Suppressions())[1].templ, "bar")); + EXPECT_EQ((*Suppressions())[0].type, SuppressionRace); + EXPECT_EQ(0, strcmp((*Suppressions())[0].templ, "foo")); +} + +TEST_F(SuppressionContextTest, ParseType) { + ctx_->Parse( + "race:foo\n" + "thread:bar\n" + "mutex:baz\n" + "signal:quz\n" + ); // NOLINT + EXPECT_EQ((unsigned)4, ctx_->SuppressionCount()); + EXPECT_EQ((*Suppressions())[3].type, SuppressionSignal); + EXPECT_EQ(0, strcmp((*Suppressions())[3].templ, "quz")); + EXPECT_EQ((*Suppressions())[2].type, SuppressionMutex); + EXPECT_EQ(0, strcmp((*Suppressions())[2].templ, "baz")); + EXPECT_EQ((*Suppressions())[1].type, SuppressionThread); + EXPECT_EQ(0, strcmp((*Suppressions())[1].templ, "bar")); + EXPECT_EQ((*Suppressions())[0].type, SuppressionRace); + EXPECT_EQ(0, strcmp((*Suppressions())[0].templ, "foo")); +} + +} // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_test_main.cc b/lib/sanitizer_common/tests/sanitizer_test_main.cc index 12d1d15af917..b7fd3dafab26 100644 --- a/lib/sanitizer_common/tests/sanitizer_test_main.cc +++ b/lib/sanitizer_common/tests/sanitizer_test_main.cc @@ -12,7 +12,10 @@ //===----------------------------------------------------------------------===// #include "gtest/gtest.h" +const char *argv0; + int main(int argc, char **argv) { + argv0 = argv[0]; testing::GTEST_FLAG(death_test_style) = "threadsafe"; testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/lib/sanitizer_common/tests/sanitizer_test_utils.h b/lib/sanitizer_common/tests/sanitizer_test_utils.h index a770d0fbd39e..17adb2647656 100644 --- a/lib/sanitizer_common/tests/sanitizer_test_utils.h +++ b/lib/sanitizer_common/tests/sanitizer_test_utils.h @@ -36,14 +36,14 @@ typedef __int64 int64_t; #define __has_feature(x) 0 #endif -#ifndef ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS +#ifndef ATTRIBUTE_NO_SANITIZE_ADDRESS # if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) -# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \ +# define ATTRIBUTE_NO_SANITIZE_ADDRESS \ __attribute__((no_sanitize_address)) # else -# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS +# define ATTRIBUTE_NO_SANITIZE_ADDRESS # endif -#endif // ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS +#endif // ATTRIBUTE_NO_SANITIZE_ADDRESS #if __LP64__ || defined(_WIN64) # define SANITIZER_WORDSIZE 64 diff --git a/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc b/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc index e080403fb56c..ddc8dba5d3e0 100644 --- a/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc @@ -23,8 +23,7 @@ static LowLevelAllocator tctx_allocator; template<typename TCTX> static ThreadContextBase *GetThreadContext(u32 tid) { BlockingMutexLock l(&tctx_allocator_lock); - void *mem = tctx_allocator.Allocate(sizeof(TCTX)); - return new(mem) TCTX(tid); + return new(tctx_allocator) TCTX(tid); } static const u32 kMaxRegistryThreads = 1000; |