[clang][Driver] Support simplified triple versions for config files (#111387)
[llvm-project.git] / compiler-rt / lib / sanitizer_common / tests / sanitizer_posix_test.cpp
blob5016b09c15307fd5cbafc66fbeec7860eb58a983
1 //===-- sanitizer_posix_test.cpp ------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Tests for POSIX-specific code.
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_common/sanitizer_platform.h"
14 #if SANITIZER_POSIX
16 # include <pthread.h>
17 # include <sys/mman.h>
19 # include <algorithm>
20 # include <numeric>
22 # include "gtest/gtest.h"
23 # include "sanitizer_common/sanitizer_common.h"
25 namespace __sanitizer {
27 static pthread_key_t key;
28 static bool destructor_executed;
30 extern "C"
31 void destructor(void *arg) {
32 uptr iter = reinterpret_cast<uptr>(arg);
33 if (iter > 1) {
34 ASSERT_EQ(0, pthread_setspecific(key, reinterpret_cast<void *>(iter - 1)));
35 return;
37 destructor_executed = true;
40 extern "C"
41 void *thread_func(void *arg) {
42 return reinterpret_cast<void*>(pthread_setspecific(key, arg));
45 static void SpawnThread(uptr iteration) {
46 destructor_executed = false;
47 pthread_t tid;
48 ASSERT_EQ(0, pthread_create(&tid, 0, &thread_func,
49 reinterpret_cast<void *>(iteration)));
50 void *retval;
51 ASSERT_EQ(0, pthread_join(tid, &retval));
52 ASSERT_EQ(0, retval);
55 TEST(SanitizerCommon, PthreadDestructorIterations) {
56 ASSERT_EQ(0, pthread_key_create(&key, &destructor));
57 SpawnThread(GetPthreadDestructorIterations());
58 EXPECT_TRUE(destructor_executed);
59 SpawnThread(GetPthreadDestructorIterations() + 1);
60 #if SANITIZER_SOLARIS
61 // Solaris continues calling destructors beyond PTHREAD_DESTRUCTOR_ITERATIONS.
62 EXPECT_TRUE(destructor_executed);
63 #else
64 EXPECT_FALSE(destructor_executed);
65 #endif
66 ASSERT_EQ(0, pthread_key_delete(key));
69 TEST(SanitizerCommon, IsAccessibleMemoryRange) {
70 const int page_size = GetPageSize();
71 InternalMmapVector<char> buffer(3 * page_size);
72 uptr mem = reinterpret_cast<uptr>(buffer.data());
73 // Protect the middle page.
74 mprotect((void *)(mem + page_size), page_size, PROT_NONE);
75 EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size - 1));
76 EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size));
77 EXPECT_FALSE(IsAccessibleMemoryRange(mem, page_size + 1));
78 EXPECT_TRUE(IsAccessibleMemoryRange(mem + page_size - 1, 1));
79 EXPECT_FALSE(IsAccessibleMemoryRange(mem + page_size - 1, 2));
80 EXPECT_FALSE(IsAccessibleMemoryRange(mem + 2 * page_size - 1, 1));
81 EXPECT_TRUE(IsAccessibleMemoryRange(mem + 2 * page_size, page_size));
82 EXPECT_FALSE(IsAccessibleMemoryRange(mem, 3 * page_size));
83 EXPECT_FALSE(IsAccessibleMemoryRange(0x0, 2));
86 TEST(SanitizerCommon, IsAccessibleMemoryRangeLarge) {
87 InternalMmapVector<char> buffer(10000 * GetPageSize());
88 EXPECT_TRUE(IsAccessibleMemoryRange(reinterpret_cast<uptr>(buffer.data()),
89 buffer.size()));
92 TEST(SanitizerCommon, TryMemCpy) {
93 std::vector<char> src(10000000);
94 std::iota(src.begin(), src.end(), 123);
95 std::vector<char> dst;
97 // Don't use ::testing::ElementsAreArray or similar, as the huge output on an
98 // error is not helpful.
100 dst.assign(1, 0);
101 EXPECT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
102 EXPECT_TRUE(std::equal(dst.begin(), dst.end(), src.begin()));
104 dst.assign(100, 0);
105 EXPECT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
106 EXPECT_TRUE(std::equal(dst.begin(), dst.end(), src.begin()));
108 dst.assign(534, 0);
109 EXPECT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
110 EXPECT_TRUE(std::equal(dst.begin(), dst.end(), src.begin()));
112 dst.assign(GetPageSize(), 0);
113 EXPECT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
114 EXPECT_TRUE(std::equal(dst.begin(), dst.end(), src.begin()));
116 dst.assign(src.size(), 0);
117 EXPECT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
118 EXPECT_TRUE(std::equal(dst.begin(), dst.end(), src.begin()));
120 dst.assign(src.size() - 1, 0);
121 EXPECT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
122 EXPECT_TRUE(std::equal(dst.begin(), dst.end(), src.begin()));
125 TEST(SanitizerCommon, TryMemCpyNull) {
126 std::vector<char> dst(100);
127 EXPECT_FALSE(TryMemCpy(dst.data(), nullptr, dst.size()));
130 TEST(SanitizerCommon, MemCpyAccessible) {
131 const int page_num = 1000;
132 const int page_size = GetPageSize();
133 InternalMmapVector<char> src(page_num * page_size);
134 std::iota(src.begin(), src.end(), 123);
135 std::vector<char> dst;
136 std::vector<char> exp = {src.begin(), src.end()};
138 // Protect some pages.
139 for (int i = 7; i < page_num; i *= 2) {
140 mprotect(src.data() + i * page_size, page_size, PROT_NONE);
141 std::fill(exp.data() + i * page_size, exp.data() + (i + 1) * page_size, 0);
144 dst.assign(src.size(), 0);
145 EXPECT_FALSE(TryMemCpy(dst.data(), src.data(), dst.size()));
147 // Full page aligned range with mprotect pages.
148 dst.assign(src.size(), 0);
149 MemCpyAccessible(dst.data(), src.data(), dst.size());
150 EXPECT_TRUE(std::equal(dst.begin(), dst.end(), exp.begin()));
152 // Misaligned range with mprotect pages.
153 size_t offb = 3;
154 size_t offe = 7;
155 dst.assign(src.size() - offb - offe, 0);
156 MemCpyAccessible(dst.data(), src.data() + offb, dst.size());
157 EXPECT_TRUE(std::equal(dst.begin(), dst.end(), exp.begin() + offb));
159 // Misaligned range with ends in mprotect pages.
160 offb = 3 + 7 * page_size;
161 offe = 7 + 14 * page_size;
162 dst.assign(src.size() - offb - offe, 0);
163 MemCpyAccessible(dst.data(), src.data() + offb, dst.size());
164 EXPECT_TRUE(std::equal(dst.begin(), dst.end(), exp.begin() + offb));
167 } // namespace __sanitizer
169 #endif // SANITIZER_POSIX