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