aboutsummaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/tests
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sanitizer_common/tests')
-rw-r--r--lib/sanitizer_common/tests/CMakeLists.txt30
-rw-r--r--lib/sanitizer_common/tests/lit.cfg28
-rw-r--r--lib/sanitizer_common/tests/lit.site.cfg.in20
-rw-r--r--lib/sanitizer_common/tests/sanitizer_allocator_test.cc91
-rw-r--r--lib/sanitizer_common/tests/sanitizer_common_test.cc102
-rw-r--r--lib/sanitizer_common/tests/sanitizer_ioctl_test.cc77
-rw-r--r--lib/sanitizer_common/tests/sanitizer_libc_test.cc7
-rw-r--r--lib/sanitizer_common/tests/sanitizer_linux_test.cc37
-rw-r--r--lib/sanitizer_common/tests/sanitizer_mutex_test.cc1
-rw-r--r--lib/sanitizer_common/tests/sanitizer_nolibc_test.cc31
-rw-r--r--lib/sanitizer_common/tests/sanitizer_nolibc_test_main.cc19
-rw-r--r--lib/sanitizer_common/tests/sanitizer_posix_test.cc62
-rw-r--r--lib/sanitizer_common/tests/sanitizer_printf_test.cc32
-rw-r--r--lib/sanitizer_common/tests/sanitizer_procmaps_test.cc30
-rw-r--r--lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc2
-rw-r--r--lib/sanitizer_common/tests/sanitizer_stackdepot_test.cc23
-rw-r--r--lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc31
-rw-r--r--lib/sanitizer_common/tests/sanitizer_stoptheworld_test.cc4
-rw-r--r--lib/sanitizer_common/tests/sanitizer_suppressions_test.cc152
-rw-r--r--lib/sanitizer_common/tests/sanitizer_test_main.cc3
-rw-r--r--lib/sanitizer_common/tests/sanitizer_test_utils.h8
-rw-r--r--lib/sanitizer_common/tests/sanitizer_thread_registry_test.cc3
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;