/proc/self/cwd/test/fuzz/fuzz_runner.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include <cstdint> |
4 | | #include <cwchar> |
5 | | |
6 | | // Bring in DEFINE_PROTO_FUZZER definition as per |
7 | | // https://github.com/google/libprotobuf-mutator#integrating-with-libfuzzer. |
8 | | #include "libprotobuf_mutator/src/libfuzzer/libfuzzer_macro.h" |
9 | | // Bring in FuzzedDataProvider, see |
10 | | // https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider |
11 | | #include "fuzzer/FuzzedDataProvider.h" |
12 | | #include "spdlog/spdlog.h" |
13 | | |
14 | | namespace Envoy { |
15 | | namespace Fuzz { |
16 | | |
17 | | // Each test may need a sub-environment of that provided by //test/test_common:environment_lib, |
18 | | // since each fuzz invocation runs in the same process, but might want a distinct tmp sandbox for |
19 | | // example. |
20 | | class PerTestEnvironment { |
21 | | public: |
22 | | PerTestEnvironment(); |
23 | | ~PerTestEnvironment(); |
24 | | |
25 | 2.84k | std::string temporaryPath(const std::string& path) const { return test_tmpdir_ + "/" + path; } |
26 | 3.09k | const std::string& testId() const { return test_id_; } |
27 | | |
28 | | private: |
29 | | static uint32_t test_num_; |
30 | | const uint32_t per_test_num_; |
31 | | const std::string test_tmpdir_; |
32 | | const std::string test_id_; |
33 | | }; |
34 | | |
35 | | class Runner { |
36 | | public: |
37 | | /** |
38 | | * Setup the environment for fuzz testing. Multiple execute() runs may be |
39 | | * invoked in this environment. |
40 | | * @param argc number of command-line args. |
41 | | * @param argv array of command-line args. |
42 | | * @param default_loglevel default log level (overridable with -l). |
43 | | */ |
44 | | static void setupEnvironment(int argc, char** argv, spdlog::level::level_enum default_log_level); |
45 | | |
46 | | /** |
47 | | * @return spdlog::level::level_enum the log level for the fuzzer. |
48 | | */ |
49 | 9.52k | static spdlog::level::level_enum logLevel() { return log_level_; } |
50 | | |
51 | | private: |
52 | | static spdlog::level::level_enum log_level_; |
53 | | }; |
54 | | |
55 | | /** |
56 | | * Establishes a function to run before the test process exits. This enables |
57 | | * threads, mocks, and other objects that are expensive to create to be shared |
58 | | * between test methods. |
59 | | */ |
60 | | void addCleanupHook(std::function<void()>); |
61 | | |
62 | | /** |
63 | | * Runs all cleanup hooks. |
64 | | */ |
65 | | void runCleanupHooks(); |
66 | | |
67 | | } // namespace Fuzz |
68 | | } // namespace Envoy |
69 | | |
70 | | // Fuzz test startup hook, see |
71 | | // https://llvm.org/docs/LibFuzzer.html#startup-initialization. |
72 | | extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv); |
73 | | |
74 | | // See https://llvm.org/docs/LibFuzzer.html#fuzz-target. |
75 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); |
76 | | |
77 | | #ifdef PERSISTENT_FUZZER |
78 | 8 | template <typename T> T& initFuzzVar(T* ptr) { |
79 | 8 | Envoy::Fuzz::addCleanupHook([ptr]() { delete ptr; }); initFuzzVar<Envoy::H1FuzzIntegrationTest>(Envoy::H1FuzzIntegrationTest*)::{lambda()#1}::operator()() const Line | Count | Source | 79 | 2 | Envoy::Fuzz::addCleanupHook([ptr]() { delete ptr; }); |
h1_fuzz.cc:initFuzzVar<Envoy::H1FuzzIntegrationTest::replay(test::integration::CaptureFuzzTestCase const&, bool)::Init>(Envoy::H1FuzzIntegrationTest::replay(test::integration::CaptureFuzzTestCase const&, bool)::Init*)::{lambda()#1}::operator()() const Line | Count | Source | 79 | 2 | Envoy::Fuzz::addCleanupHook([ptr]() { delete ptr; }); |
initFuzzVar<Envoy::H2FuzzIntegrationTest>(Envoy::H2FuzzIntegrationTest*)::{lambda()#1}::operator()() const Line | Count | Source | 79 | 2 | Envoy::Fuzz::addCleanupHook([ptr]() { delete ptr; }); |
h2_fuzz.cc:initFuzzVar<Envoy::H2FuzzIntegrationTest::replay(test::integration::H2CaptureFuzzTestCase const&, bool)::Init>(Envoy::H2FuzzIntegrationTest::replay(test::integration::H2CaptureFuzzTestCase const&, bool)::Init*)::{lambda()#1}::operator()() const Line | Count | Source | 79 | 2 | Envoy::Fuzz::addCleanupHook([ptr]() { delete ptr; }); |
|
80 | 8 | return *ptr; |
81 | 8 | } Envoy::H1FuzzIntegrationTest& initFuzzVar<Envoy::H1FuzzIntegrationTest>(Envoy::H1FuzzIntegrationTest*) Line | Count | Source | 78 | 2 | template <typename T> T& initFuzzVar(T* ptr) { | 79 | 2 | Envoy::Fuzz::addCleanupHook([ptr]() { delete ptr; }); | 80 | 2 | return *ptr; | 81 | 2 | } |
h1_fuzz.cc:Envoy::H1FuzzIntegrationTest::replay(test::integration::CaptureFuzzTestCase const&, bool)::Init& initFuzzVar<Envoy::H1FuzzIntegrationTest::replay(test::integration::CaptureFuzzTestCase const&, bool)::Init>(Envoy::H1FuzzIntegrationTest::replay(test::integration::CaptureFuzzTestCase const&, bool)::Init*) Line | Count | Source | 78 | 2 | template <typename T> T& initFuzzVar(T* ptr) { | 79 | 2 | Envoy::Fuzz::addCleanupHook([ptr]() { delete ptr; }); | 80 | 2 | return *ptr; | 81 | 2 | } |
Envoy::H2FuzzIntegrationTest& initFuzzVar<Envoy::H2FuzzIntegrationTest>(Envoy::H2FuzzIntegrationTest*) Line | Count | Source | 78 | 2 | template <typename T> T& initFuzzVar(T* ptr) { | 79 | 2 | Envoy::Fuzz::addCleanupHook([ptr]() { delete ptr; }); | 80 | 2 | return *ptr; | 81 | 2 | } |
h2_fuzz.cc:Envoy::H2FuzzIntegrationTest::replay(test::integration::H2CaptureFuzzTestCase const&, bool)::Init& initFuzzVar<Envoy::H2FuzzIntegrationTest::replay(test::integration::H2CaptureFuzzTestCase const&, bool)::Init>(Envoy::H2FuzzIntegrationTest::replay(test::integration::H2CaptureFuzzTestCase const&, bool)::Init*) Line | Count | Source | 78 | 2 | template <typename T> T& initFuzzVar(T* ptr) { | 79 | 2 | Envoy::Fuzz::addCleanupHook([ptr]() { delete ptr; }); | 80 | 2 | return *ptr; | 81 | 2 | } |
|
82 | 5.04k | #define PERSISTENT_FUZZ_VAR(type, var, args) static type& var = initFuzzVar(new type(args)) |
83 | | #else |
84 | | #define PERSISTENT_FUZZ_VAR(type, var, args) type var args |
85 | | #endif |
86 | | |
87 | | #define DEFINE_TEST_ONE_INPUT_IMPL \ |
88 | 32.6k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { \ |
89 | 32.6k | EnvoyTestOneInput(data, size); \ |
90 | 32.6k | return 0; \ |
91 | 32.6k | } |
92 | | |
93 | | /** |
94 | | * Define a fuzz test. This should be used to define a fuzz_cc_fuzz_test_target with: |
95 | | * |
96 | | * DEFINE_FUZZER(const uint8_t* buf, size_t len) { |
97 | | * // Do some test stuff with buf/len. |
98 | | * return 0; |
99 | | * } |
100 | | */ |
101 | | #define DEFINE_FUZZER \ |
102 | | static void EnvoyTestOneInput(const uint8_t* buf, size_t len); \ |
103 | | DEFINE_TEST_ONE_INPUT_IMPL \ |
104 | | static void EnvoyTestOneInput |