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
22namespace __sanitizer {
23
24static pthread_key_t key;
25static bool destructor_executed;
26
27extern "C"
28void destructor(void *arg) {
29 uptr iter = reinterpret_cast<uptr>(arg);
30 if (iter > 1) {
31 ASSERT_EQ(0, pthread_setspecific(key: key, pointer: reinterpret_cast<void *>(iter - 1)));
32 return;
33 }
34 destructor_executed = true;
35}
36
37extern "C"
38void *thread_func(void *arg) {
39 return reinterpret_cast<void*>(pthread_setspecific(key: key, pointer: arg));
40}
41
42static void SpawnThread(uptr iteration) {
43 destructor_executed = false;
44 pthread_t tid;
45 ASSERT_EQ(0, pthread_create(newthread: &tid, attr: 0, start_routine: &thread_func,
46 arg: reinterpret_cast<void *>(iteration)));
47 void *retval;
48 ASSERT_EQ(0, pthread_join(th: tid, thread_return: &retval));
49 ASSERT_EQ(0, retval);
50}
51
52TEST(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
66TEST(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

source code of compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp