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>
16using Test = ::zxtest::Test;
17template <typename T> using TestWithParam = ::zxtest::TestWithParam<T>;
18#else
19#include "gtest/gtest.h"
20using Test = ::testing::Test;
21template <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
30namespace gwp_asan {
31namespace 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.
36Printf_t getPrintfFunction();
37
38// First call returns true, all the following calls return false.
39bool OnlyOnce();
40
41}; // namespace test
42}; // namespace gwp_asan
43
44char *AllocateMemory(gwp_asan::GuardedPoolAllocator &GPA);
45void DeallocateMemory(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr);
46void DeallocateMemory2(gwp_asan::GuardedPoolAllocator &GPA, void *Ptr);
47void TouchMemory(void *Ptr);
48
49class DefaultGuardedPoolAllocator : public Test {
50public:
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
62protected:
63  gwp_asan::GuardedPoolAllocator GPA;
64  decltype(gwp_asan::options::Options::MaxSimultaneousAllocations)
65      MaxSimultaneousAllocations;
66};
67
68class CustomGuardedPoolAllocator : public Test {
69public:
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
85protected:
86  gwp_asan::GuardedPoolAllocator GPA;
87  decltype(gwp_asan::options::Options::MaxSimultaneousAllocations)
88      MaxSimultaneousAllocations;
89};
90
91class BacktraceGuardedPoolAllocator
92    : public TestWithParam</* Recoverable */ bool> {
93public:
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
122protected:
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
143using DefaultGuardedPoolAllocatorDeathTest = DefaultGuardedPoolAllocator;
144using CustomGuardedPoolAllocatorDeathTest = CustomGuardedPoolAllocator;
145using BacktraceGuardedPoolAllocatorDeathTest = BacktraceGuardedPoolAllocator;
146
147#endif // GWP_ASAN_TESTS_HARNESS_H_
148