brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · 5016b09 Raw
170 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// Tests for POSIX-specific code.10//11//===----------------------------------------------------------------------===//12 13#include "sanitizer_common/sanitizer_platform.h"14#if SANITIZER_POSIX15 16#  include <pthread.h>17#  include <sys/mman.h>18 19#  include <algorithm>20#  include <numeric>21 22#  include "gtest/gtest.h"23#  include "sanitizer_common/sanitizer_common.h"24 25namespace __sanitizer {26 27static pthread_key_t key;28static bool destructor_executed;29 30extern "C"31void 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;36  }37  destructor_executed = true;38}39 40extern "C"41void *thread_func(void *arg) {42  return reinterpret_cast<void*>(pthread_setspecific(key, arg));43}44 45static 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);53}54 55TEST(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_SOLARIS61  // Solaris continues calling destructors beyond PTHREAD_DESTRUCTOR_ITERATIONS.62  EXPECT_TRUE(destructor_executed);63#else64  EXPECT_FALSE(destructor_executed);65#endif66  ASSERT_EQ(0, pthread_key_delete(key));67}68 69TEST(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));84}85 86TEST(SanitizerCommon, IsAccessibleMemoryRangeLarge) {87  InternalMmapVector<char> buffer(10000 * GetPageSize());88  EXPECT_TRUE(IsAccessibleMemoryRange(reinterpret_cast<uptr>(buffer.data()),89                                      buffer.size()));90}91 92TEST(SanitizerCommon, TryMemCpy) {93  std::vector<char> src(10000000);94  std::iota(src.begin(), src.end(), 123);95  std::vector<char> dst;96 97  // Don't use ::testing::ElementsAreArray or similar, as the huge output on an98  // error is not helpful.99 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()));103 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()));107 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()));111 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()));115 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()));119 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()));123}124 125TEST(SanitizerCommon, TryMemCpyNull) {126  std::vector<char> dst(100);127  EXPECT_FALSE(TryMemCpy(dst.data(), nullptr, dst.size()));128}129 130TEST(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()};137 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);142  }143 144  dst.assign(src.size(), 0);145  EXPECT_FALSE(TryMemCpy(dst.data(), src.data(), dst.size()));146 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()));151 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));158 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));165}166 167}  // namespace __sanitizer168 169#endif  // SANITIZER_POSIX170