llvm.org GIT mirror llvm / 9906eef
[libFuzzer] make LLVMFuzzerTestOneInput (the fuzzer target function) return int instead of void. The actual return value is not *yet* used (and expected to be 0). This change is API breaking, so the fuzzers will need to be updated. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249214 91177308-0d34-0410-b5e6-96231b3b80d8 Kostya Serebryany 5 years ago
23 changed file(s) with 78 addition(s) and 43 deletion(s). Raw diff Collapse all Expand all
2020 optimizations options (e.g. -O0, -O1, -O2) to diversify testing.
2121 * Build a test driver using the same options as the library.
2222 The test driver is a C/C++ file containing interesting calls to the library
23 inside a single function ``extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);``
23 inside a single function ``extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);``.
24 Currently, the only expected return value is 0, others are reserved for future.
2425 * Link the Fuzzer, the library and the driver together into an executable
2526 using the same sanitizer options as for the library.
2627 * Collect the initial corpus of inputs for the
8283 A simple function that does something interesting if it receives the input "HI!"::
8384
8485 cat << EOF >> test_fuzzer.cc
85 extern "C" void LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size) {
86 extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size) {
8687 if (size > 0 && data[0] == 'H')
8788 if (size > 1 && data[1] == 'I')
8889 if (size > 2 && data[2] == '!')
8990 __builtin_trap();
91 return 0;
9092 }
9193 EOF
9294 # Get lib/Fuzzer. Assuming that you already have fresh clang in PATH.
118120 cat << EOF > pcre_fuzzer.cc
119121 #include
120122 #include "pcre2posix.h"
121 extern "C" void LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
122 if (size < 1) return;
123 extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
124 if (size < 1) return 0;
123125 char *str = new char[size+1];
124126 memcpy(str, data, size);
125127 str[size] = 0;
129131 regfree(&preg);
130132 }
131133 delete [] str;
134 return 0;
132135 }
133136 EOF
134137 clang++ -g -fsanitize=address $COV_FLAGS -c -std=c++11 -I inst/include/ pcre_fuzzer.cc
226229 assert (SSL_CTX_use_PrivateKey_file(sctx, "server.key", SSL_FILETYPE_PEM));
227230 return 0;
228231 }
229 extern "C" void LLVMFuzzerTestOneInput(unsigned char *Data, size_t Size) {
232 extern "C" int LLVMFuzzerTestOneInput(unsigned char *Data, size_t Size) {
230233 static int unused = Init();
231234 SSL *server = SSL_new(sctx);
232235 BIO *sinbio = BIO_new(BIO_s_mem());
236239 BIO_write(sinbio, Data, Size);
237240 SSL_do_handshake(server);
238241 SSL_free(server);
242 return 0;
239243 }
240244 EOF
241245 # Build the fuzzer.
2222
2323 namespace fuzzer {
2424
25 typedef void (*UserCallback)(const uint8_t *Data, size_t Size);
25 typedef void (*DeprecatedUserCallback)(const uint8_t *Data, size_t Size);
26 /// Returns an int 0. Values other than zero are reserved for future.
27 typedef int (*UserCallback)(const uint8_t *Data, size_t Size);
2628 /** Simple C-like interface with a single user-supplied callback.
2729
2830 Usage:
3032 #\code
3133 #include "FuzzerInterface.h"
3234
33 void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
35 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
3436 DoStuffWithData(Data, Size);
37 return 0;
3538 }
3639
3740 // Implement your own main() or use the one from FuzzerMain.cpp.
4245 #\endcode
4346 */
4447 int FuzzerDriver(int argc, char **argv, UserCallback Callback);
48 int FuzzerDriver(int argc, char **argv, DeprecatedUserCallback Callback);
4549
4650 class FuzzerRandomBase {
4751 public:
117121 public:
118122 MyFuzzer(fuzzer::FuzzerRandomBase *Rand);
119123 // Must define the target function.
120 void TargetFunction(...) { ... }
124 int TargetFunction(...) { ...; return 0; }
121125 // Optionally define the mutator.
122126 size_t Mutate(...) { ... }
123127 // Optionally define the CrossOver method.
135139 UserSuppliedFuzzer(); // Deprecated, don't use.
136140 UserSuppliedFuzzer(FuzzerRandomBase *Rand);
137141 /// Executes the target function on 'Size' bytes of 'Data'.
138 virtual void TargetFunction(const uint8_t *Data, size_t Size) = 0;
142 virtual int TargetFunction(const uint8_t *Data, size_t Size) = 0;
139143 /// Mutates 'Size' bytes of data in 'Data' inplace into up to 'MaxSize' bytes,
140144 /// returns the new size of the data, which should be positive.
141145 virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
175175 public:
176176 SimpleUserSuppliedFuzzer(FuzzerRandomBase *Rand, UserCallback Callback)
177177 : UserSuppliedFuzzer(Rand), Callback(Callback) {}
178 virtual void TargetFunction(const uint8_t *Data, size_t Size) {
179 return Callback(Data, Size);
178
179 SimpleUserSuppliedFuzzer(FuzzerRandomBase *Rand, DeprecatedUserCallback Callback)
180 : UserSuppliedFuzzer(Rand), DeprecatedCallback(Callback) {}
181
182 virtual int TargetFunction(const uint8_t *Data, size_t Size) override {
183 if (Callback) return Callback(Data, Size);
184 DeprecatedCallback(Data, Size);
185 return 0;
180186 }
181187
182188 private:
183 UserCallback Callback;
189 DeprecatedUserCallback DeprecatedCallback = nullptr;
190 UserCallback Callback = nullptr;
184191 };
185192
186193 }; // namespace fuzzer
193193 }
194194
195195 void Fuzzer::ExecuteCallback(const Unit &U) {
196 int Res = 0;
196197 if (Options.Tokens.empty()) {
197 USF.TargetFunction(U.data(), U.size());
198 Res = USF.TargetFunction(U.data(), U.size());
198199 } else {
199200 auto T = SubstituteTokens(U);
200 USF.TargetFunction(T.data(), T.size());
201 }
201 Res = USF.TargetFunction(T.data(), T.size());
202 }
203 assert(Res == 0);
202204 }
203205
204206 size_t Fuzzer::RunOneMaximizeTotalCoverage(const Unit &U) {
1212 #include "FuzzerInternal.h"
1313
1414 // This function should be defined by the user.
15 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
15 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
1616
1717 int main(int argc, char **argv) {
1818 return fuzzer::FuzzerDriver(argc, argv, LLVMFuzzerTestOneInput);
11 // executed many times.
22 #include
33
4 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
4 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
55 int Num = 0;
66 for (size_t i = 0; i < Size; i++)
77 if (Data[i] == 'A' + i)
1010 std::cerr << "BINGO!\n";
1111 exit(1);
1212 }
13 return 0;
1314 }
99 exit(1);
1010 }
1111
12 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
12 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
1313 // looking for "thread_local unsigned A;"
14 if (Size < 24) return;
14 if (Size < 24) return 0;
1515 if (0 == memcmp(&Data[0], "thread_local", 12))
1616 if (Data[12] == ' ')
1717 if (0 == memcmp(&Data[13], "unsigned", 8))
1919 if (Data[22] == 'A')
2020 if (Data[23] == ';')
2121 Found();
22 return 0;
2223 }
2324
33 #include
44 #include
55
6 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
6 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
77 int bits = 0;
88 if (Size > 0 && Data[0] == 'F') bits |= 1;
99 if (Size > 1 && Data[1] == 'U') bits |= 2;
1313 std::cerr << "BINGO!\n";
1414 exit(1);
1515 }
16 return 0;
1617 }
1718
33 #include
44 #include
55
6 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
6 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
77 int bits = 0;
88 if (Size > 0 && Data[0] == 'F') bits |= 1;
99 if (Size > 1 && Data[1] == 'U') bits |= 2;
1515 std::cerr << "BINGO!\n";
1616 exit(1);
1717 }
18 return 0;
1819 }
1920
77
88 static volatile int One = 1;
99
10 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
10 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
1111 if (Size > 0 && Data[0] == 'H') {
1212 Sink = 1;
1313 if (Size > 1 && Data[1] == 'i') {
1919 }
2020 }
2121 }
22 return 0;
2223 }
2324
33 #include
44 #include
55
6 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
6 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
77 // TODO: check other sizes.
88 if (Size >= 8 && memcmp(Data, "01234567", 8) == 0) {
99 if (Size >= 12 && memcmp(Data + 8, "ABCD", 4) == 0) {
1515 }
1616 }
1717 }
18 return 0;
1819 }
66 static volatile int Sink;
77 static volatile int *Null = 0;
88
9 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
9 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
1010 if (Size > 0 && Data[0] == 'H') {
1111 Sink = 1;
1212 if (Size > 1 && Data[1] == 'i') {
1717 }
1818 }
1919 }
20 return 0;
2021 }
2122
33 #include
44 #include
55
6 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
7 if (Size < 14) return;
6 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
7 if (Size < 14) return 0;
88 uint64_t x = 0;
99 int64_t y = 0;
1010 int z = 0;
2626 Size, x, y, z, a);
2727 exit(1);
2828 }
29 return 0;
2930 }
99
1010 static volatile int Zero = 0;
1111
12 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
12 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
1313 const char *Expected = "ElvisPresley";
14 if (Size < strlen(Expected)) return;
14 if (Size < strlen(Expected)) return 0;
1515 size_t Match = 0;
1616 for (size_t i = 0; Expected[i]; i++)
1717 if (Expected[i] + Zero == Data[i])
2020 std::cout << "BINGO; Found the target, exiting\n";
2121 exit(1);
2222 }
23 return 0;
2324 }
2425
2121 return Hash;
2222 }
2323
24 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
24 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
2525 if (Size < 14)
26 return;
26 return 0;
2727
2828 uint32_t Hash = simple_hash(&Data[0], Size - 4);
2929 uint32_t Want = reinterpret_cast(&Data[Size - 4])[0];
3030 if (Hash != Want)
31 return;
31 return 0;
3232 fprintf(stderr, "BINGO; simple_hash defeated: %x == %x\n", (unsigned int)Hash,
3333 (unsigned int)Want);
3434 exit(1);
35 return 0;
3536 }
55
66 static volatile int Sink;
77
8 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
8 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
99 if (Size > 0 && Data[0] == 'H') {
1010 Sink = 1;
1111 if (Size > 1 && Data[1] == 'i') {
1616 }
1717 }
1818 }
19 return 0;
1920 }
2021
1515 return res == 0;
1616 }
1717
18 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
18 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
1919 if (Eq(Data, Size, "AAA") &&
2020 Size >= 3 && Eq(Data + 3, Size - 3, "BBBB") &&
2121 Size >= 7 && Eq(Data + 7, Size - 7, "CCCCCC") &&
2424 fprintf(stderr, "BINGO\n");
2525 exit(1);
2626 }
27 return 0;
2728 }
55
66 static volatile int sink;
77
8 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
8 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
99 // TODO: check other sizes.
1010 char *S = (char*)Data;
1111 if (Size >= 8 && strncmp(S, "123", 8))
2020 }
2121 }
2222 }
23 return 0;
2324 }
4141 return false;
4242 }
4343
44 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
44 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
4545 if (Size >= 4 && Switch(Data, Size) &&
4646 Size >= 12 && Switch(Data + 4, Size - 4) &&
4747 Size >= 14 && ShortSwitch(Data + 12, 2)
4949 fprintf(stderr, "BINGO; Found the target, exiting\n");
5050 exit(1);
5151 }
52 return 0;
5253 }
5354
55
66 static volatile int Sink;
77
8 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
8 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
99 if (Size > 0 && Data[0] == 'H') {
1010 Sink = 1;
1111 if (Size > 1 && Data[1] == 'i') {
1717 }
1818 }
1919 }
20 return 0;
2021 }
2122
1515 public:
1616 MyFuzzer(fuzzer::FuzzerRandomBase *Rand)
1717 : fuzzer::UserSuppliedFuzzer(Rand) {}
18 void TargetFunction(const uint8_t *Data, size_t Size) {
19 if (Size <= 10) return;
20 if (memcmp(Data, &kMagic, sizeof(kMagic))) return;
18 int TargetFunction(const uint8_t *Data, size_t Size) {
19 if (Size <= 10) return 0;
20 if (memcmp(Data, &kMagic, sizeof(kMagic))) return 0;
2121 // It's hard to get here w/o advanced fuzzing techniques (e.g. cmp tracing).
2222 // So, we simply 'fix' the data in the custom mutator.
2323 if (Data[8] == 'H') {
2828 }
2929 }
3030 }
31 return 0;
3132 }
3233 // Custom mutator.
3334 virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
4242
4343 } // end of anonymous namespace
4444
45 extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
45 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
4646
4747 // Allocate space for locals before setjmp so that memory can be collected
4848 // if parse exits prematurely (via longjmp).
5757
5858 if (setjmp(JmpBuf))
5959 // If reached, we have returned with non-zero status, so exit.
60 return;
60 return 0;
6161
6262 // TODO(kschimpf) Write a main to do this initialization.
6363 if (!InstalledHandler) {
6868 M = parseAssembly(MemBuf->getMemBufferRef(), Err, Context);
6969
7070 if (!M.get())
71 return;
71 return 0;
7272
7373 verifyModule(*M.get());
74 return 0;
7475 }
6161 cl::desc("Options to pass to the fuzzer"), cl::ZeroOrMore,
6262 cl::PositionalEatsArgs);
6363
64 void DisassembleOneInput(const uint8_t *Data, size_t Size) {
64 int DisassembleOneInput(const uint8_t *Data, size_t Size) {
6565 char AssemblyText[AssemblyTextBufSize];
6666
6767 std::vector DataCopy(Data, Data + Size);
8484 break;
8585 } while (Consumed != 0);
8686 LLVMDisasmDispose(Ctx);
87 return 0;
8788 }
8889
8990 int main(int argc, char **argv) {