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