xref: /openbsd-src/gnu/llvm/compiler-rt/lib/gwp_asan/tests/harness.h (revision 810390e339a5425391477d5d41c78d7cab2424ac)
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