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> 16using Test = ::zxtest::Test; 17template <typename T> using TestWithParam = ::zxtest::TestWithParam<T>; 18#else 19#include "gtest/gtest.h" 20using Test = ::testing::Test; 21template <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 30namespace gwp_asan { 31namespace 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. 36Printf_t getPrintfFunction(); 37 38// First call returns true, all the following calls return false. 39bool OnlyOnce(); 40 41}; // namespace test 42}; // namespace gwp_asan 43 44char *AllocateMemory(gwp_asan::GuardedPoolAllocator &GPA); 45void DeallocateMemory(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr); 46void DeallocateMemory2(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr); 47void TouchMemory(void *Ptr); 48 49class DefaultGuardedPoolAllocator : public Test { 50public: 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 62protected: 63 gwp_asan::GuardedPoolAllocator GPA; 64 decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 65 MaxSimultaneousAllocations; 66}; 67 68class CustomGuardedPoolAllocator : public Test { 69public: 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 85protected: 86 gwp_asan::GuardedPoolAllocator GPA; 87 decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 88 MaxSimultaneousAllocations; 89}; 90 91class BacktraceGuardedPoolAllocator 92 : public TestWithParam</* Recoverable */ bool> { 93public: 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 122protected: 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 143using DefaultGuardedPoolAllocatorDeathTest = DefaultGuardedPoolAllocator; 144using CustomGuardedPoolAllocatorDeathTest = CustomGuardedPoolAllocator; 145using BacktraceGuardedPoolAllocatorDeathTest = BacktraceGuardedPoolAllocator; 146 147#endif // GWP_ASAN_TESTS_HARNESS_H_ 148