xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/sanitizer_common/tests/sanitizer_common_test.cc (revision a7c257b03e4462df2b1020128fb82716512d7856)
1 //===-- sanitizer_common_test.cc ------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11 //
12 //===----------------------------------------------------------------------===//
13 #include <algorithm>
14 
15 #include "sanitizer_common/sanitizer_allocator_internal.h"
16 #include "sanitizer_common/sanitizer_common.h"
17 #include "sanitizer_common/sanitizer_file.h"
18 #include "sanitizer_common/sanitizer_flags.h"
19 #include "sanitizer_common/sanitizer_libc.h"
20 #include "sanitizer_common/sanitizer_platform.h"
21 
22 #include "sanitizer_pthread_wrappers.h"
23 
24 #include "gtest/gtest.h"
25 
26 namespace __sanitizer {
27 
IsSorted(const uptr * array,uptr n)28 static bool IsSorted(const uptr *array, uptr n) {
29   for (uptr i = 1; i < n; i++) {
30     if (array[i] < array[i - 1]) return false;
31   }
32   return true;
33 }
34 
TEST(SanitizerCommon,SortTest)35 TEST(SanitizerCommon, SortTest) {
36   uptr array[100];
37   uptr n = 100;
38   // Already sorted.
39   for (uptr i = 0; i < n; i++) {
40     array[i] = i;
41   }
42   Sort(array, n);
43   EXPECT_TRUE(IsSorted(array, n));
44   // Reverse order.
45   for (uptr i = 0; i < n; i++) {
46     array[i] = n - 1 - i;
47   }
48   Sort(array, n);
49   EXPECT_TRUE(IsSorted(array, n));
50   // Mixed order.
51   for (uptr i = 0; i < n; i++) {
52     array[i] = (i % 2 == 0) ? i : n - 1 - i;
53   }
54   Sort(array, n);
55   EXPECT_TRUE(IsSorted(array, n));
56   // All equal.
57   for (uptr i = 0; i < n; i++) {
58     array[i] = 42;
59   }
60   Sort(array, n);
61   EXPECT_TRUE(IsSorted(array, n));
62   // All but one sorted.
63   for (uptr i = 0; i < n - 1; i++) {
64     array[i] = i;
65   }
66   array[n - 1] = 42;
67   Sort(array, n);
68   EXPECT_TRUE(IsSorted(array, n));
69   // Minimal case - sort three elements.
70   array[0] = 1;
71   array[1] = 0;
72   Sort(array, 2);
73   EXPECT_TRUE(IsSorted(array, 2));
74 }
75 
TEST(SanitizerCommon,MmapAlignedOrDieOnFatalError)76 TEST(SanitizerCommon, MmapAlignedOrDieOnFatalError) {
77   uptr PageSize = GetPageSizeCached();
78   for (uptr size = 1; size <= 32; size *= 2) {
79     for (uptr alignment = 1; alignment <= 32; alignment *= 2) {
80       for (int iter = 0; iter < 100; iter++) {
81         uptr res = (uptr)MmapAlignedOrDieOnFatalError(
82             size * PageSize, alignment * PageSize, "MmapAlignedOrDieTest");
83         EXPECT_EQ(0U, res % (alignment * PageSize));
84         internal_memset((void*)res, 1, size * PageSize);
85         UnmapOrDie((void*)res, size * PageSize);
86       }
87     }
88   }
89 }
90 
TEST(SanitizerCommon,InternalMmapVectorRoundUpCapacity)91 TEST(SanitizerCommon, InternalMmapVectorRoundUpCapacity) {
92   InternalMmapVector<uptr> v;
93   v.reserve(1);
94   CHECK_EQ(v.capacity(), GetPageSizeCached() / sizeof(uptr));
95 }
96 
TEST(SanitizerCommon,InternalMmapVectorReize)97 TEST(SanitizerCommon, InternalMmapVectorReize) {
98   InternalMmapVector<uptr> v;
99   CHECK_EQ(0U, v.size());
100   CHECK_GE(v.capacity(), v.size());
101 
102   v.reserve(1000);
103   CHECK_EQ(0U, v.size());
104   CHECK_GE(v.capacity(), 1000U);
105 
106   v.resize(10000);
107   CHECK_EQ(10000U, v.size());
108   CHECK_GE(v.capacity(), v.size());
109   uptr cap = v.capacity();
110 
111   v.resize(100);
112   CHECK_EQ(100U, v.size());
113   CHECK_EQ(v.capacity(), cap);
114 
115   v.reserve(10);
116   CHECK_EQ(100U, v.size());
117   CHECK_EQ(v.capacity(), cap);
118 }
119 
TEST(SanitizerCommon,InternalMmapVector)120 TEST(SanitizerCommon, InternalMmapVector) {
121   InternalMmapVector<uptr> vector;
122   for (uptr i = 0; i < 100; i++) {
123     EXPECT_EQ(i, vector.size());
124     vector.push_back(i);
125   }
126   for (uptr i = 0; i < 100; i++) {
127     EXPECT_EQ(i, vector[i]);
128   }
129   for (int i = 99; i >= 0; i--) {
130     EXPECT_EQ((uptr)i, vector.back());
131     vector.pop_back();
132     EXPECT_EQ((uptr)i, vector.size());
133   }
134   InternalMmapVector<uptr> empty_vector;
135   CHECK_GT(empty_vector.capacity(), 0U);
136   CHECK_EQ(0U, empty_vector.size());
137 }
138 
TEST(SanitizerCommon,InternalMmapVectorEq)139 TEST(SanitizerCommon, InternalMmapVectorEq) {
140   InternalMmapVector<uptr> vector1;
141   InternalMmapVector<uptr> vector2;
142   for (uptr i = 0; i < 100; i++) {
143     vector1.push_back(i);
144     vector2.push_back(i);
145   }
146   EXPECT_TRUE(vector1 == vector2);
147   EXPECT_FALSE(vector1 != vector2);
148 
149   vector1.push_back(1);
150   EXPECT_FALSE(vector1 == vector2);
151   EXPECT_TRUE(vector1 != vector2);
152 
153   vector2.push_back(1);
154   EXPECT_TRUE(vector1 == vector2);
155   EXPECT_FALSE(vector1 != vector2);
156 
157   vector1[55] = 1;
158   EXPECT_FALSE(vector1 == vector2);
159   EXPECT_TRUE(vector1 != vector2);
160 }
161 
TEST(SanitizerCommon,InternalMmapVectorSwap)162 TEST(SanitizerCommon, InternalMmapVectorSwap) {
163   InternalMmapVector<uptr> vector1;
164   InternalMmapVector<uptr> vector2;
165   InternalMmapVector<uptr> vector3;
166   InternalMmapVector<uptr> vector4;
167   for (uptr i = 0; i < 100; i++) {
168     vector1.push_back(i);
169     vector2.push_back(i);
170     vector3.push_back(-i);
171     vector4.push_back(-i);
172   }
173   EXPECT_NE(vector2, vector3);
174   EXPECT_NE(vector1, vector4);
175   vector1.swap(vector3);
176   EXPECT_EQ(vector2, vector3);
177   EXPECT_EQ(vector1, vector4);
178 }
179 
TestThreadInfo(bool main)180 void TestThreadInfo(bool main) {
181   uptr stk_addr = 0;
182   uptr stk_size = 0;
183   uptr tls_addr = 0;
184   uptr tls_size = 0;
185   GetThreadStackAndTls(main, &stk_addr, &stk_size, &tls_addr, &tls_size);
186 
187   int stack_var;
188   EXPECT_NE(stk_addr, (uptr)0);
189   EXPECT_NE(stk_size, (uptr)0);
190   EXPECT_GT((uptr)&stack_var, stk_addr);
191   EXPECT_LT((uptr)&stack_var, stk_addr + stk_size);
192 
193 #if SANITIZER_LINUX && defined(__x86_64__)
194   static __thread int thread_var;
195   EXPECT_NE(tls_addr, (uptr)0);
196   EXPECT_NE(tls_size, (uptr)0);
197   EXPECT_GT((uptr)&thread_var, tls_addr);
198   EXPECT_LT((uptr)&thread_var, tls_addr + tls_size);
199 
200   // Ensure that tls and stack do not intersect.
201   uptr tls_end = tls_addr + tls_size;
202   EXPECT_TRUE(tls_addr < stk_addr || tls_addr >= stk_addr + stk_size);
203   EXPECT_TRUE(tls_end  < stk_addr || tls_end  >=  stk_addr + stk_size);
204   EXPECT_TRUE((tls_addr < stk_addr) == (tls_end  < stk_addr));
205 #endif
206 }
207 
WorkerThread(void * arg)208 static void *WorkerThread(void *arg) {
209   TestThreadInfo(false);
210   return 0;
211 }
212 
TEST(SanitizerCommon,ThreadStackTlsMain)213 TEST(SanitizerCommon, ThreadStackTlsMain) {
214   InitTlsSize();
215   TestThreadInfo(true);
216 }
217 
TEST(SanitizerCommon,ThreadStackTlsWorker)218 TEST(SanitizerCommon, ThreadStackTlsWorker) {
219   InitTlsSize();
220   pthread_t t;
221   PTHREAD_CREATE(&t, 0, WorkerThread, 0);
222   PTHREAD_JOIN(t, 0);
223 }
224 
UptrLess(uptr a,uptr b)225 bool UptrLess(uptr a, uptr b) {
226   return a < b;
227 }
228 
TEST(SanitizerCommon,InternalLowerBound)229 TEST(SanitizerCommon, InternalLowerBound) {
230   static const uptr kSize = 5;
231   int arr[kSize];
232   arr[0] = 1;
233   arr[1] = 3;
234   arr[2] = 5;
235   arr[3] = 7;
236   arr[4] = 11;
237 
238   EXPECT_EQ(0u, InternalLowerBound(arr, 0, kSize, 0, UptrLess));
239   EXPECT_EQ(0u, InternalLowerBound(arr, 0, kSize, 1, UptrLess));
240   EXPECT_EQ(1u, InternalLowerBound(arr, 0, kSize, 2, UptrLess));
241   EXPECT_EQ(1u, InternalLowerBound(arr, 0, kSize, 3, UptrLess));
242   EXPECT_EQ(2u, InternalLowerBound(arr, 0, kSize, 4, UptrLess));
243   EXPECT_EQ(2u, InternalLowerBound(arr, 0, kSize, 5, UptrLess));
244   EXPECT_EQ(3u, InternalLowerBound(arr, 0, kSize, 6, UptrLess));
245   EXPECT_EQ(3u, InternalLowerBound(arr, 0, kSize, 7, UptrLess));
246   EXPECT_EQ(4u, InternalLowerBound(arr, 0, kSize, 8, UptrLess));
247   EXPECT_EQ(4u, InternalLowerBound(arr, 0, kSize, 9, UptrLess));
248   EXPECT_EQ(4u, InternalLowerBound(arr, 0, kSize, 10, UptrLess));
249   EXPECT_EQ(4u, InternalLowerBound(arr, 0, kSize, 11, UptrLess));
250   EXPECT_EQ(5u, InternalLowerBound(arr, 0, kSize, 12, UptrLess));
251 }
252 
TEST(SanitizerCommon,InternalLowerBoundVsStdLowerBound)253 TEST(SanitizerCommon, InternalLowerBoundVsStdLowerBound) {
254   std::vector<int> data;
255   auto create_item = [] (size_t i, size_t j) {
256     auto v = i * 10000 + j;
257     return ((v << 6) + (v >> 6) + 0x9e3779b9) % 100;
258   };
259   for (size_t i = 0; i < 1000; ++i) {
260     data.resize(i);
261     for (size_t j = 0; j < i; ++j) {
262       data[j] = create_item(i, j);
263     }
264 
265     std::sort(data.begin(), data.end());
266 
267     for (size_t j = 0; j < i; ++j) {
268       int val = create_item(i, j);
269       for (auto to_find : {val - 1, val, val + 1}) {
270         uptr expected =
271             std::lower_bound(data.begin(), data.end(), to_find) - data.begin();
272         EXPECT_EQ(expected, InternalLowerBound(data.data(), 0, data.size(),
273                                                to_find, std::less<int>()));
274       }
275     }
276   }
277 }
278 
279 #if SANITIZER_LINUX && !SANITIZER_ANDROID
TEST(SanitizerCommon,FindPathToBinary)280 TEST(SanitizerCommon, FindPathToBinary) {
281   char *true_path = FindPathToBinary("true");
282   EXPECT_NE((char*)0, internal_strstr(true_path, "/bin/true"));
283   InternalFree(true_path);
284   EXPECT_EQ(0, FindPathToBinary("unexisting_binary.ergjeorj"));
285 }
286 #elif SANITIZER_WINDOWS
TEST(SanitizerCommon,FindPathToBinary)287 TEST(SanitizerCommon, FindPathToBinary) {
288   // ntdll.dll should be on PATH in all supported test environments on all
289   // supported Windows versions.
290   char *ntdll_path = FindPathToBinary("ntdll.dll");
291   EXPECT_NE((char*)0, internal_strstr(ntdll_path, "ntdll.dll"));
292   InternalFree(ntdll_path);
293   EXPECT_EQ(0, FindPathToBinary("unexisting_binary.ergjeorj"));
294 }
295 #endif
296 
TEST(SanitizerCommon,StripPathPrefix)297 TEST(SanitizerCommon, StripPathPrefix) {
298   EXPECT_EQ(0, StripPathPrefix(0, "prefix"));
299   EXPECT_STREQ("foo", StripPathPrefix("foo", 0));
300   EXPECT_STREQ("dir/file.cc",
301                StripPathPrefix("/usr/lib/dir/file.cc", "/usr/lib/"));
302   EXPECT_STREQ("/file.cc", StripPathPrefix("/usr/myroot/file.cc", "/myroot"));
303   EXPECT_STREQ("file.h", StripPathPrefix("/usr/lib/./file.h", "/usr/lib/"));
304 }
305 
TEST(SanitizerCommon,RemoveANSIEscapeSequencesFromString)306 TEST(SanitizerCommon, RemoveANSIEscapeSequencesFromString) {
307   RemoveANSIEscapeSequencesFromString(nullptr);
308   const char *buffs[22] = {
309     "Default",                                "Default",
310     "\033[95mLight magenta",                  "Light magenta",
311     "\033[30mBlack\033[32mGreen\033[90mGray", "BlackGreenGray",
312     "\033[106mLight cyan \033[107mWhite ",    "Light cyan White ",
313     "\033[31mHello\033[0m World",             "Hello World",
314     "\033[38;5;82mHello \033[38;5;198mWorld", "Hello World",
315     "123[653456789012",                       "123[653456789012",
316     "Normal \033[5mBlink \033[25mNormal",     "Normal Blink Normal",
317     "\033[106m\033[107m",                     "",
318     "",                                       "",
319     " ",                                      " ",
320   };
321 
322   for (size_t i = 0; i < ARRAY_SIZE(buffs); i+=2) {
323     char *buffer_copy = internal_strdup(buffs[i]);
324     RemoveANSIEscapeSequencesFromString(buffer_copy);
325     EXPECT_STREQ(buffer_copy, buffs[i+1]);
326     InternalFree(buffer_copy);
327   }
328 }
329 
TEST(SanitizerCommon,InternalScopedString)330 TEST(SanitizerCommon, InternalScopedString) {
331   InternalScopedString str(10);
332   EXPECT_EQ(0U, str.length());
333   EXPECT_STREQ("", str.data());
334 
335   str.append("foo");
336   EXPECT_EQ(3U, str.length());
337   EXPECT_STREQ("foo", str.data());
338 
339   int x = 1234;
340   str.append("%d", x);
341   EXPECT_EQ(7U, str.length());
342   EXPECT_STREQ("foo1234", str.data());
343 
344   str.append("%d", x);
345   EXPECT_EQ(9U, str.length());
346   EXPECT_STREQ("foo123412", str.data());
347 
348   str.clear();
349   EXPECT_EQ(0U, str.length());
350   EXPECT_STREQ("", str.data());
351 
352   str.append("0123456789");
353   EXPECT_EQ(9U, str.length());
354   EXPECT_STREQ("012345678", str.data());
355 }
356 
357 #if SANITIZER_LINUX || SANITIZER_FREEBSD || \
358   SANITIZER_OPENBSD || SANITIZER_MAC || SANITIZER_IOS
TEST(SanitizerCommon,GetRandom)359 TEST(SanitizerCommon, GetRandom) {
360   u8 buffer_1[32], buffer_2[32];
361   for (bool blocking : { false, true }) {
362     EXPECT_FALSE(GetRandom(nullptr, 32, blocking));
363     EXPECT_FALSE(GetRandom(buffer_1, 0, blocking));
364     EXPECT_FALSE(GetRandom(buffer_1, 512, blocking));
365     EXPECT_EQ(ARRAY_SIZE(buffer_1), ARRAY_SIZE(buffer_2));
366     for (uptr size = 4; size <= ARRAY_SIZE(buffer_1); size += 4) {
367       for (uptr i = 0; i < 100; i++) {
368         EXPECT_TRUE(GetRandom(buffer_1, size, blocking));
369         EXPECT_TRUE(GetRandom(buffer_2, size, blocking));
370         EXPECT_NE(internal_memcmp(buffer_1, buffer_2, size), 0);
371       }
372     }
373   }
374 }
375 #endif
376 
TEST(SanitizerCommon,ReservedAddressRangeInit)377 TEST(SanitizerCommon, ReservedAddressRangeInit) {
378   uptr init_size = 0xffff;
379   ReservedAddressRange address_range;
380   uptr res = address_range.Init(init_size);
381   CHECK_NE(res, (void*)-1);
382   UnmapOrDie((void*)res, init_size);
383   // Should be able to map into the same space now.
384   ReservedAddressRange address_range2;
385   uptr res2 = address_range2.Init(init_size, nullptr, res);
386   CHECK_EQ(res, res2);
387 
388   // TODO(flowerhack): Once this is switched to the "real" implementation
389   // (rather than passing through to MmapNoAccess*), enforce and test "no
390   // double initializations allowed"
391 }
392 
TEST(SanitizerCommon,ReservedAddressRangeMap)393 TEST(SanitizerCommon, ReservedAddressRangeMap) {
394   constexpr uptr init_size = 0xffff;
395   ReservedAddressRange address_range;
396   uptr res = address_range.Init(init_size);
397   CHECK_NE(res, (void*) -1);
398 
399   // Valid mappings should succeed.
400   CHECK_EQ(res, address_range.Map(res, init_size));
401 
402   // Valid mappings should be readable.
403   unsigned char buffer[init_size];
404   memcpy(buffer, reinterpret_cast<void *>(res), init_size);
405 
406   // TODO(flowerhack): Once this is switched to the "real" implementation, make
407   // sure you can only mmap into offsets in the Init range.
408 }
409 
TEST(SanitizerCommon,ReservedAddressRangeUnmap)410 TEST(SanitizerCommon, ReservedAddressRangeUnmap) {
411   uptr PageSize = GetPageSizeCached();
412   uptr init_size = PageSize * 8;
413   ReservedAddressRange address_range;
414   uptr base_addr = address_range.Init(init_size);
415   CHECK_NE(base_addr, (void*)-1);
416   CHECK_EQ(base_addr, address_range.Map(base_addr, init_size));
417 
418   // Unmapping the entire range should succeed.
419   address_range.Unmap(base_addr, init_size);
420 
421   // Map a new range.
422   base_addr = address_range.Init(init_size);
423   CHECK_EQ(base_addr, address_range.Map(base_addr, init_size));
424 
425   // Windows doesn't allow partial unmappings.
426   #if !SANITIZER_WINDOWS
427 
428   // Unmapping at the beginning should succeed.
429   address_range.Unmap(base_addr, PageSize);
430 
431   // Unmapping at the end should succeed.
432   uptr new_start = reinterpret_cast<uptr>(address_range.base()) +
433                    address_range.size() - PageSize;
434   address_range.Unmap(new_start, PageSize);
435 
436   #endif
437 
438   // Unmapping in the middle of the ReservedAddressRange should fail.
439   EXPECT_DEATH(address_range.Unmap(base_addr + (PageSize * 2), PageSize), ".*");
440 }
441 
442 }  // namespace __sanitizer
443