13cab2bb3Spatrick //===-- harness.h -----------------------------------------------*- C++ -*-===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick 93cab2bb3Spatrick #ifndef GWP_ASAN_TESTS_HARNESS_H_ 103cab2bb3Spatrick #define GWP_ASAN_TESTS_HARNESS_H_ 113cab2bb3Spatrick 123cab2bb3Spatrick #include <stdarg.h> 133cab2bb3Spatrick 14d89ec533Spatrick #if defined(__Fuchsia__) 15d89ec533Spatrick #include <zxtest/zxtest.h> 16d89ec533Spatrick using Test = ::zxtest::Test; 17*810390e3Srobert template <typename T> using TestWithParam = ::zxtest::TestWithParam<T>; 18d89ec533Spatrick #else 193cab2bb3Spatrick #include "gtest/gtest.h" 20d89ec533Spatrick using Test = ::testing::Test; 21*810390e3Srobert template <typename T> using TestWithParam = ::testing::TestWithParam<T>; 22d89ec533Spatrick #endif 233cab2bb3Spatrick 243cab2bb3Spatrick #include "gwp_asan/guarded_pool_allocator.h" 253cab2bb3Spatrick #include "gwp_asan/optional/backtrace.h" 26d89ec533Spatrick #include "gwp_asan/optional/printf.h" 271f9cb04fSpatrick #include "gwp_asan/optional/segv_handler.h" 283cab2bb3Spatrick #include "gwp_asan/options.h" 293cab2bb3Spatrick 303cab2bb3Spatrick namespace gwp_asan { 313cab2bb3Spatrick namespace test { 323cab2bb3Spatrick // This printf-function getter allows other platforms (e.g. Android) to define 333cab2bb3Spatrick // their own signal-safe Printf function. In LLVM, we use 343cab2bb3Spatrick // `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf 353cab2bb3Spatrick // for this purpose. 36d89ec533Spatrick Printf_t getPrintfFunction(); 371f9cb04fSpatrick 381f9cb04fSpatrick // First call returns true, all the following calls return false. 391f9cb04fSpatrick bool OnlyOnce(); 401f9cb04fSpatrick 413cab2bb3Spatrick }; // namespace test 423cab2bb3Spatrick }; // namespace gwp_asan 433cab2bb3Spatrick 44*810390e3Srobert char *AllocateMemory(gwp_asan::GuardedPoolAllocator &GPA); 45*810390e3Srobert void DeallocateMemory(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr); 46*810390e3Srobert void DeallocateMemory2(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr); 47*810390e3Srobert void TouchMemory(void *Ptr); 48*810390e3Srobert 49d89ec533Spatrick class DefaultGuardedPoolAllocator : public Test { 503cab2bb3Spatrick public: SetUp()511f9cb04fSpatrick void SetUp() override { 523cab2bb3Spatrick gwp_asan::options::Options Opts; 533cab2bb3Spatrick Opts.setDefaults(); 543cab2bb3Spatrick MaxSimultaneousAllocations = Opts.MaxSimultaneousAllocations; 553cab2bb3Spatrick 561f9cb04fSpatrick Opts.InstallForkHandlers = gwp_asan::test::OnlyOnce(); 573cab2bb3Spatrick GPA.init(Opts); 583cab2bb3Spatrick } 593cab2bb3Spatrick TearDown()601f9cb04fSpatrick void TearDown() override { GPA.uninitTestOnly(); } 611f9cb04fSpatrick 623cab2bb3Spatrick protected: 633cab2bb3Spatrick gwp_asan::GuardedPoolAllocator GPA; 643cab2bb3Spatrick decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 653cab2bb3Spatrick MaxSimultaneousAllocations; 663cab2bb3Spatrick }; 673cab2bb3Spatrick 68d89ec533Spatrick class CustomGuardedPoolAllocator : public Test { 693cab2bb3Spatrick public: 703cab2bb3Spatrick void InitNumSlots(decltype (gwp_asan::options::Options::MaxSimultaneousAllocations)MaxSimultaneousAllocationsArg)713cab2bb3Spatrick InitNumSlots(decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 723cab2bb3Spatrick MaxSimultaneousAllocationsArg) { 733cab2bb3Spatrick gwp_asan::options::Options Opts; 743cab2bb3Spatrick Opts.setDefaults(); 753cab2bb3Spatrick 763cab2bb3Spatrick Opts.MaxSimultaneousAllocations = MaxSimultaneousAllocationsArg; 773cab2bb3Spatrick MaxSimultaneousAllocations = MaxSimultaneousAllocationsArg; 783cab2bb3Spatrick 791f9cb04fSpatrick Opts.InstallForkHandlers = gwp_asan::test::OnlyOnce(); 803cab2bb3Spatrick GPA.init(Opts); 813cab2bb3Spatrick } 823cab2bb3Spatrick TearDown()831f9cb04fSpatrick void TearDown() override { GPA.uninitTestOnly(); } 841f9cb04fSpatrick 853cab2bb3Spatrick protected: 863cab2bb3Spatrick gwp_asan::GuardedPoolAllocator GPA; 873cab2bb3Spatrick decltype(gwp_asan::options::Options::MaxSimultaneousAllocations) 883cab2bb3Spatrick MaxSimultaneousAllocations; 893cab2bb3Spatrick }; 903cab2bb3Spatrick 91*810390e3Srobert class BacktraceGuardedPoolAllocator 92*810390e3Srobert : public TestWithParam</* Recoverable */ bool> { 933cab2bb3Spatrick public: SetUp()941f9cb04fSpatrick void SetUp() override { 953cab2bb3Spatrick gwp_asan::options::Options Opts; 963cab2bb3Spatrick Opts.setDefaults(); 973cab2bb3Spatrick 98d89ec533Spatrick Opts.Backtrace = gwp_asan::backtrace::getBacktraceFunction(); 991f9cb04fSpatrick Opts.InstallForkHandlers = gwp_asan::test::OnlyOnce(); 1003cab2bb3Spatrick GPA.init(Opts); 1011f9cb04fSpatrick 102*810390e3Srobert // In recoverable mode, capture GWP-ASan logs to an internal buffer so that 103*810390e3Srobert // we can search it in unit tests. For non-recoverable tests, the default 104*810390e3Srobert // buffer is fine, as any tests should be EXPECT_DEATH()'d. 105*810390e3Srobert Recoverable = GetParam(); 106*810390e3Srobert gwp_asan::Printf_t PrintfFunction = PrintfToBuffer; 107*810390e3Srobert GetOutputBuffer().clear(); 108*810390e3Srobert if (!Recoverable) 109*810390e3Srobert PrintfFunction = gwp_asan::test::getPrintfFunction(); 110*810390e3Srobert 111d89ec533Spatrick gwp_asan::segv_handler::installSignalHandlers( 112*810390e3Srobert &GPA, PrintfFunction, gwp_asan::backtrace::getPrintBacktraceFunction(), 113*810390e3Srobert gwp_asan::backtrace::getSegvBacktraceFunction(), 114*810390e3Srobert /* Recoverable */ Recoverable); 1151f9cb04fSpatrick } 1161f9cb04fSpatrick TearDown()1171f9cb04fSpatrick void TearDown() override { 1181f9cb04fSpatrick GPA.uninitTestOnly(); 119d89ec533Spatrick gwp_asan::segv_handler::uninstallSignalHandlers(); 1203cab2bb3Spatrick } 1213cab2bb3Spatrick 1223cab2bb3Spatrick protected: GetOutputBuffer()123*810390e3Srobert static std::string &GetOutputBuffer() { 124*810390e3Srobert static std::string Buffer; 125*810390e3Srobert return Buffer; 126*810390e3Srobert } 127*810390e3Srobert 128*810390e3Srobert __attribute__((format(printf, 1, 2))) static void PrintfToBuffer(const char * Format,...)129*810390e3Srobert PrintfToBuffer(const char *Format, ...) { 130*810390e3Srobert va_list AP; 131*810390e3Srobert va_start(AP, Format); 132*810390e3Srobert char Buffer[8192]; 133*810390e3Srobert vsnprintf(Buffer, sizeof(Buffer), Format, AP); 134*810390e3Srobert GetOutputBuffer() += Buffer; 135*810390e3Srobert va_end(AP); 136*810390e3Srobert } 137*810390e3Srobert 1383cab2bb3Spatrick gwp_asan::GuardedPoolAllocator GPA; 139*810390e3Srobert bool Recoverable; 1403cab2bb3Spatrick }; 1413cab2bb3Spatrick 142d89ec533Spatrick // https://github.com/google/googletest/blob/master/docs/advanced.md#death-tests-and-threads 143d89ec533Spatrick using DefaultGuardedPoolAllocatorDeathTest = DefaultGuardedPoolAllocator; 144d89ec533Spatrick using CustomGuardedPoolAllocatorDeathTest = CustomGuardedPoolAllocator; 145d89ec533Spatrick using BacktraceGuardedPoolAllocatorDeathTest = BacktraceGuardedPoolAllocator; 146d89ec533Spatrick 1473cab2bb3Spatrick #endif // GWP_ASAN_TESTS_HARNESS_H_ 148