• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SetUp()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 
TearDown()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
InitNumSlots(decltype (gwp_asan::options::Options::MaxSimultaneousAllocations)MaxSimultaneousAllocationsArg)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 
TearDown()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:
SetUp()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, PrintfFunction, gwp_asan::backtrace::getPrintBacktraceFunction(),
120         gwp_asan::backtrace::getSegvBacktraceFunction(),
121         /* Recoverable */ Recoverable);
122   }
123 
TearDown()124   void TearDown() override {
125     GPA.uninitTestOnly();
126     gwp_asan::segv_handler::uninstallSignalHandlers();
127   }
128 
129 protected:
GetOutputBuffer()130   static std::string &GetOutputBuffer() {
131     static std::string Buffer;
132     return Buffer;
133   }
134 
135   __attribute__((format(printf, 1, 2))) static void
PrintfToBuffer(const char * Format,...)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