Coverage Report

Created: 2025-03-13 06:40

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