xref: /openbsd-src/gnu/llvm/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp (revision 3cab2bb3f667058bece8e38b12449a63a9d73c4b)
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.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "sanitizer_common/sanitizer_platform.h"
14 #if SANITIZER_POSIX
15 
16 #include "sanitizer_common/sanitizer_common.h"
17 #include "gtest/gtest.h"
18 
19 #include <pthread.h>
20 #include <sys/mman.h>
21 
22 namespace __sanitizer {
23 
24 static pthread_key_t key;
25 static bool destructor_executed;
26 
27 extern "C"
destructor(void * arg)28 void destructor(void *arg) {
29   uptr iter = reinterpret_cast<uptr>(arg);
30   if (iter > 1) {
31     ASSERT_EQ(0, pthread_setspecific(key, reinterpret_cast<void *>(iter - 1)));
32     return;
33   }
34   destructor_executed = true;
35 }
36 
37 extern "C"
thread_func(void * arg)38 void *thread_func(void *arg) {
39   return reinterpret_cast<void*>(pthread_setspecific(key, arg));
40 }
41 
SpawnThread(uptr iteration)42 static void SpawnThread(uptr iteration) {
43   destructor_executed = false;
44   pthread_t tid;
45   ASSERT_EQ(0, pthread_create(&tid, 0, &thread_func,
46                               reinterpret_cast<void *>(iteration)));
47   void *retval;
48   ASSERT_EQ(0, pthread_join(tid, &retval));
49   ASSERT_EQ(0, retval);
50 }
51 
TEST(SanitizerCommon,PthreadDestructorIterations)52 TEST(SanitizerCommon, PthreadDestructorIterations) {
53   ASSERT_EQ(0, pthread_key_create(&key, &destructor));
54   SpawnThread(GetPthreadDestructorIterations());
55   EXPECT_TRUE(destructor_executed);
56   SpawnThread(GetPthreadDestructorIterations() + 1);
57 #if SANITIZER_SOLARIS
58   // Solaris continues calling destructors beyond PTHREAD_DESTRUCTOR_ITERATIONS.
59   EXPECT_TRUE(destructor_executed);
60 #else
61   EXPECT_FALSE(destructor_executed);
62 #endif
63   ASSERT_EQ(0, pthread_key_delete(key));
64 }
65 
TEST(SanitizerCommon,IsAccessibleMemoryRange)66 TEST(SanitizerCommon, IsAccessibleMemoryRange) {
67   const int page_size = GetPageSize();
68   uptr mem = (uptr)mmap(0, 3 * page_size, PROT_READ | PROT_WRITE,
69                         MAP_PRIVATE | MAP_ANON, -1, 0);
70   // Protect the middle page.
71   mprotect((void *)(mem + page_size), page_size, PROT_NONE);
72   EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size - 1));
73   EXPECT_TRUE(IsAccessibleMemoryRange(mem, page_size));
74   EXPECT_FALSE(IsAccessibleMemoryRange(mem, page_size + 1));
75   EXPECT_TRUE(IsAccessibleMemoryRange(mem + page_size - 1, 1));
76   EXPECT_FALSE(IsAccessibleMemoryRange(mem + page_size - 1, 2));
77   EXPECT_FALSE(IsAccessibleMemoryRange(mem + 2 * page_size - 1, 1));
78   EXPECT_TRUE(IsAccessibleMemoryRange(mem + 2 * page_size, page_size));
79   EXPECT_FALSE(IsAccessibleMemoryRange(mem, 3 * page_size));
80   EXPECT_FALSE(IsAccessibleMemoryRange(0x0, 2));
81 }
82 
83 }  // namespace __sanitizer
84 
85 #endif  // SANITIZER_POSIX
86