Coverage Report

Created: 2024-11-29 06:10

/src/botan/src/fuzzer/fuzzers.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* (C) 2015,2016,2017 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6
7
#ifndef BOTAN_FUZZER_DRIVER_H_
8
#define BOTAN_FUZZER_DRIVER_H_
9
10
#include <botan/chacha_rng.h>
11
#include <botan/exceptn.h>
12
#include <iostream>
13
#include <stdint.h>
14
#include <stdlib.h>  // for setenv
15
#include <vector>
16
17
static const size_t max_fuzzer_input_size = 8192;
18
19
extern void fuzz(std::span<const uint8_t> in);
20
21
extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv);
22
extern "C" int LLVMFuzzerTestOneInput(const uint8_t in[], size_t len);
23
24
68
extern "C" int LLVMFuzzerInitialize(int*, char***) {
25
   /*
26
   * This disables the mlock pool, as overwrites within the pool are
27
   * opaque to ASan or other instrumentation.
28
   */
29
68
   ::setenv("BOTAN_MLOCK_POOL_SIZE", "0", 1);
30
68
   return 0;
31
68
}
32
33
// Called by main() in libFuzzer or in main for AFL below
34
60.8k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t in[], size_t len) {
35
60.8k
   if(len <= max_fuzzer_input_size) {
36
60.5k
      fuzz(std::span<const uint8_t>(in, len));
37
60.5k
   }
38
60.8k
   return 0;
39
60.8k
}
40
41
// Some helpers for the fuzzer jigs
42
43
29.0k
inline std::shared_ptr<Botan::RandomNumberGenerator> fuzzer_rng_as_shared() {
44
29.0k
   static std::shared_ptr<Botan::ChaCha_RNG> rng =
45
29.0k
      std::make_shared<Botan::ChaCha_RNG>(Botan::secure_vector<uint8_t>(32));
46
29.0k
   return rng;
47
29.0k
}
48
49
21.2k
inline Botan::RandomNumberGenerator& fuzzer_rng() {
50
21.2k
   return *fuzzer_rng_as_shared();
51
21.2k
}
52
53
#define FUZZER_WRITE_AND_CRASH(expr)                                             \
54
0
   do {                                                                          \
55
0
      std::cerr << expr << " @ Line " << __LINE__ << " in " << __FILE__ << "\n"; \
56
0
      abort();                                                                   \
57
0
   } while(0)
58
59
#define FUZZER_ASSERT_EQUAL(x, y)                                                        \
60
35.7k
   do {                                                                                  \
61
35.7k
      if(x != y) {                                                                       \
62
0
         FUZZER_WRITE_AND_CRASH(#x << " = " << x << " != " << #y << " = " << y << "\n"); \
63
0
      }                                                                                  \
64
35.7k
   } while(0)
65
66
#define FUZZER_ASSERT_TRUE(e)                                         \
67
4.18k
   do {                                                               \
68
4.18k
      if(!(e)) {                                                      \
69
0
         FUZZER_WRITE_AND_CRASH("Expression " << #e << " was false"); \
70
0
      }                                                               \
71
4.18k
   } while(0)
72
73
#if defined(BOTAN_FUZZER_IS_AFL) || defined(BOTAN_FUZZER_IS_TEST)
74
75
   /* Stub for AFL */
76
77
   #if defined(BOTAN_FUZZER_IS_AFL) && !defined(__AFL_COMPILER)
78
      #error "Build configured for AFL but not being compiled by AFL compiler"
79
   #endif
80
81
   #if defined(BOTAN_FUZZER_IS_TEST)
82
83
      #include <fstream>
84
85
namespace {
86
87
int fuzz_files(char* files[]) {
88
   for(size_t i = 0; files[i]; ++i) {
89
      std::ifstream in(files[i]);
90
91
      if(in.good()) {
92
         std::vector<uint8_t> buf(max_fuzzer_input_size);
93
         in.read(reinterpret_cast<char*>(buf.data()), buf.size());
94
         const size_t got = in.gcount();
95
         buf.resize(got);
96
         buf.shrink_to_fit();
97
98
         LLVMFuzzerTestOneInput(buf.data(), got);
99
      }
100
   }
101
102
   return 0;
103
}
104
105
}  // namespace
106
107
   #endif
108
109
int main(int argc, char* argv[]) {
110
   LLVMFuzzerInitialize(&argc, &argv);
111
112
   #if defined(BOTAN_FUZZER_IS_TEST)
113
   if(argc > 1) {
114
      return fuzz_files(&argv[1]);
115
   }
116
   #endif
117
118
   #if defined(__AFL_LOOP)
119
   while(__AFL_LOOP(1000))
120
   #endif
121
   {
122
      std::vector<uint8_t> buf(max_fuzzer_input_size);
123
      std::cin.read(reinterpret_cast<char*>(buf.data()), buf.size());
124
      const size_t got = std::cin.gcount();
125
126
      buf.resize(got);
127
      buf.shrink_to_fit();
128
129
      LLVMFuzzerTestOneInput(buf.data(), got);
130
   }
131
}
132
133
#elif defined(BOTAN_FUZZER_IS_KLEE)
134
135
   #include <klee/klee.h>
136
137
int main(int argc, char* argv[]) {
138
   LLVMFuzzerInitialize(&argc, &argv);
139
140
   uint8_t input[max_fuzzer_input_size] = {0};
141
   klee_make_symbolic(&input, sizeof(input), "input");
142
143
   size_t input_len = klee_range(0, sizeof(input), "input_len");
144
145
   LLVMFuzzerTestOneInput(input, input_len);
146
}
147
148
#endif
149
150
#endif