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