1 //===-- harness.h -----------------------------------------------*- C++ -*-===// 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 #ifndef GWP_ASAN_TESTS_HARNESS_H_ 10 #define GWP_ASAN_TESTS_HARNESS_H_ 11 12 #include <stdarg.h> 13 14 #if defined(__Fuchsia__) 15 #include <zxtest/zxtest.h> 16 using Test = ::zxtest::Test; 17 template <typename T> using TestWithParam = ::zxtest::TestWithParam<T>; 18 #else 19 #include "gtest/gtest.h" 20 using Test = ::testing::Test; 21 template <typename T> using TestWithParam = ::testing::TestWithParam<T>; 22 #endif 23 24 #include "gwp_asan/guarded_pool_allocator.h" 25 #include "gwp_asan/optional/backtrace.h" 26 #include "gwp_asan/optional/printf.h" 27 #include "gwp_asan/optional/segv_handler.h" 28 #include "gwp_asan/options.h" 29 30 namespace gwp_asan { 31 namespace test { 32 // This printf-function getter allows other platforms (e.g. Android) to define 33 // their own signal-safe Printf function. In LLVM, we use 34 // `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf 35 // for this purpose. 36 Printf_t getPrintfFunction(); 37 38 // First call returns true, all the following calls return false. 39 bool OnlyOnce(); 40 41 }; // namespace test 42 }; // namespace gwp_asan 43 44 char *AllocateMemory(gwp_asan::GuardedPoolAllocator &GPA); 45 void DeallocateMemory(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr); 46 void DeallocateMemory2(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr); 47 void TouchMemory(void *Ptr); 48 49 class DefaultGuardedPoolAllocator : public Test { 50 public: 51 void SetUp() override { 52 gwp_asan::options::Options Opts; 53 Opts.setDefaults(); 54 MaxSimultaneousAllocations = Opts.MaxSimultaneousAllocations; 55 56 Opts.InstallForkHandlers = gwp_asan::test::OnlyOnce(); 57 GPA.init(Opts); 58 } 59 60 void TearDown() override { GPA.uninitTestOnly(); } 61 62 protected: 63 gwp_asan::GuardedPoolAllocator GPA; 64 decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 65 MaxSimultaneousAllocations; 66 }; 67 68 class CustomGuardedPoolAllocator : public Test { 69 public: 70 void 71 InitNumSlots(decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 72 MaxSimultaneousAllocationsArg) { 73 gwp_asan::options::Options Opts; 74 Opts.setDefaults(); 75 76 Opts.MaxSimultaneousAllocations = MaxSimultaneousAllocationsArg; 77 MaxSimultaneousAllocations = MaxSimultaneousAllocationsArg; 78 79 Opts.InstallForkHandlers = gwp_asan::test::OnlyOnce(); 80 GPA.init(Opts); 81 } 82 83 void TearDown() override { GPA.uninitTestOnly(); } 84 85 protected: 86 gwp_asan::GuardedPoolAllocator GPA; 87 decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 88 MaxSimultaneousAllocations; 89 }; 90 91 class BacktraceGuardedPoolAllocator 92 : public TestWithParam</* Recoverable */ bool> { 93 public: 94 void SetUp() override { 95 gwp_asan::options::Options Opts; 96 Opts.setDefaults(); 97 98 Opts.Backtrace = gwp_asan::backtrace::getBacktraceFunction(); 99 Opts.InstallForkHandlers = gwp_asan::test::OnlyOnce(); 100 GPA.init(Opts); 101 102 // In recoverable mode, capture GWP-ASan logs to an internal buffer so that 103 // we can search it in unit tests. For non-recoverable tests, the default 104 // buffer is fine, as any tests should be EXPECT_DEATH()'d. 105 Recoverable = GetParam(); 106 gwp_asan::Printf_t PrintfFunction = PrintfToBuffer; 107 GetOutputBuffer().clear(); 108 if (!Recoverable) 109 PrintfFunction = gwp_asan::test::getPrintfFunction(); 110 111 gwp_asan::segv_handler::installSignalHandlers( 112 &GPA, PrintfFunction, gwp_asan::backtrace::getPrintBacktraceFunction(), 113 gwp_asan::backtrace::getSegvBacktraceFunction(), 114 /* Recoverable */ Recoverable); 115 } 116 117 void TearDown() override { 118 GPA.uninitTestOnly(); 119 gwp_asan::segv_handler::uninstallSignalHandlers(); 120 } 121 122 protected: 123 static std::string &GetOutputBuffer() { 124 static std::string Buffer; 125 return Buffer; 126 } 127 128 __attribute__((format(printf, 1, 2))) static void 129 PrintfToBuffer(const char *Format, ...) { 130 va_list AP; 131 va_start(AP, Format); 132 char Buffer[8192]; 133 vsnprintf(Buffer, sizeof(Buffer), Format, AP); 134 GetOutputBuffer() += Buffer; 135 va_end(AP); 136 } 137 138 gwp_asan::GuardedPoolAllocator GPA; 139 bool Recoverable; 140 }; 141 142 // https://github.com/google/googletest/blob/master/docs/advanced.md#death-tests-and-threads 143 using DefaultGuardedPoolAllocatorDeathTest = DefaultGuardedPoolAllocator; 144 using CustomGuardedPoolAllocatorDeathTest = CustomGuardedPoolAllocator; 145 using BacktraceGuardedPoolAllocatorDeathTest = BacktraceGuardedPoolAllocator; 146 147 #endif // GWP_ASAN_TESTS_HARNESS_H_ 148