Bug Summary

File:projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp
Warning:line 37, column 5
Null pointer passed as an argument to a 'nonnull' parameter

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name FuzzerDriver.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/projects/compiler-rt/lib/fuzzer -I /build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer -I /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn326551/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -Wno-unused-parameter -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -Wno-unused-parameter -Wno-variadic-macros -Wno-non-virtual-dtor -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/projects/compiler-rt/lib/fuzzer -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -fvisibility-inlines-hidden -fno-builtin -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-03-02-155150-1477-1 -x c++ /build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp

/build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp

1//===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9// FuzzerDriver and flag parsing.
10//===----------------------------------------------------------------------===//
11
12#include "FuzzerCommand.h"
13#include "FuzzerCorpus.h"
14#include "FuzzerIO.h"
15#include "FuzzerInterface.h"
16#include "FuzzerInternal.h"
17#include "FuzzerMutate.h"
18#include "FuzzerRandom.h"
19#include "FuzzerShmem.h"
20#include "FuzzerTracePC.h"
21#include <algorithm>
22#include <atomic>
23#include <chrono>
24#include <cstdlib>
25#include <cstring>
26#include <mutex>
27#include <string>
28#include <thread>
29
30// This function should be present in the libFuzzer so that the client
31// binary can test for its existence.
32extern "C" __attribute__((used)) void __libfuzzer_is_present() {}
33
34namespace fuzzer {
35
36// Program arguments.
37struct FlagDescription {
38 const char *Name;
39 const char *Description;
40 int Default;
41 int *IntFlag;
42 const char **StrFlag;
43 unsigned int *UIntFlag;
44};
45
46struct {
47#define FUZZER_DEPRECATED_FLAG(Name)
48#define FUZZER_FLAG_INT(Name, Default, Description) int Name;
49#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) unsigned int Name;
50#define FUZZER_FLAG_STRING(Name, Description) const char *Name;
51#include "FuzzerFlags.def"
52#undef FUZZER_DEPRECATED_FLAG
53#undef FUZZER_FLAG_INT
54#undef FUZZER_FLAG_UNSIGNED
55#undef FUZZER_FLAG_STRING
56} Flags;
57
58static const FlagDescription FlagDescriptions [] {
59#define FUZZER_DEPRECATED_FLAG(Name) \
60 {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr},
61#define FUZZER_FLAG_INT(Name, Default, Description) \
62 {#Name, Description, Default, &Flags.Name, nullptr, nullptr},
63#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) \
64 {#Name, Description, static_cast<int>(Default), \
65 nullptr, nullptr, &Flags.Name},
66#define FUZZER_FLAG_STRING(Name, Description) \
67 {#Name, Description, 0, nullptr, &Flags.Name, nullptr},
68#include "FuzzerFlags.def"
69#undef FUZZER_DEPRECATED_FLAG
70#undef FUZZER_FLAG_INT
71#undef FUZZER_FLAG_UNSIGNED
72#undef FUZZER_FLAG_STRING
73};
74
75static const size_t kNumFlags =
76 sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]);
77
78static Vector<std::string> *Inputs;
79static std::string *ProgName;
80
81static void PrintHelp() {
82 Printf("Usage:\n");
83 auto Prog = ProgName->c_str();
84 Printf("\nTo run fuzzing pass 0 or more directories.\n");
85 Printf("%s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n", Prog);
86
87 Printf("\nTo run individual tests without fuzzing pass 1 or more files:\n");
88 Printf("%s [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]\n", Prog);
89
90 Printf("\nFlags: (strictly in form -flag=value)\n");
91 size_t MaxFlagLen = 0;
92 for (size_t F = 0; F < kNumFlags; F++)
93 MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen);
94
95 for (size_t F = 0; F < kNumFlags; F++) {
96 const auto &D = FlagDescriptions[F];
97 if (strstr(D.Description, "internal flag") == D.Description) continue;
98 Printf(" %s", D.Name);
99 for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++)
100 Printf(" ");
101 Printf("\t");
102 Printf("%d\t%s\n", D.Default, D.Description);
103 }
104 Printf("\nFlags starting with '--' will be ignored and "
105 "will be passed verbatim to subprocesses.\n");
106}
107
108static const char *FlagValue(const char *Param, const char *Name) {
109 size_t Len = strlen(Name);
110 if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 &&
111 Param[Len + 1] == '=')
112 return &Param[Len + 2];
113 return nullptr;
114}
115
116// Avoid calling stol as it triggers a bug in clang/glibc build.
117static long MyStol(const char *Str) {
118 long Res = 0;
119 long Sign = 1;
120 if (*Str == '-') {
121 Str++;
122 Sign = -1;
123 }
124 for (size_t i = 0; Str[i]; i++) {
125 char Ch = Str[i];
126 if (Ch < '0' || Ch > '9')
127 return Res;
128 Res = Res * 10 + (Ch - '0');
129 }
130 return Res * Sign;
131}
132
133static bool ParseOneFlag(const char *Param) {
134 if (Param[0] != '-') return false;
135 if (Param[1] == '-') {
136 static bool PrintedWarning = false;
137 if (!PrintedWarning) {
138 PrintedWarning = true;
139 Printf("INFO: libFuzzer ignores flags that start with '--'\n");
140 }
141 for (size_t F = 0; F < kNumFlags; F++)
142 if (FlagValue(Param + 1, FlagDescriptions[F].Name))
143 Printf("WARNING: did you mean '%s' (single dash)?\n", Param + 1);
144 return true;
145 }
146 for (size_t F = 0; F < kNumFlags; F++) {
147 const char *Name = FlagDescriptions[F].Name;
148 const char *Str = FlagValue(Param, Name);
149 if (Str) {
150 if (FlagDescriptions[F].IntFlag) {
151 int Val = MyStol(Str);
152 *FlagDescriptions[F].IntFlag = Val;
153 if (Flags.verbosity >= 2)
154 Printf("Flag: %s %d\n", Name, Val);
155 return true;
156 } else if (FlagDescriptions[F].UIntFlag) {
157 unsigned int Val = std::stoul(Str);
158 *FlagDescriptions[F].UIntFlag = Val;
159 if (Flags.verbosity >= 2)
160 Printf("Flag: %s %u\n", Name, Val);
161 return true;
162 } else if (FlagDescriptions[F].StrFlag) {
163 *FlagDescriptions[F].StrFlag = Str;
164 if (Flags.verbosity >= 2)
165 Printf("Flag: %s %s\n", Name, Str);
166 return true;
167 } else { // Deprecated flag.
168 Printf("Flag: %s: deprecated, don't use\n", Name);
169 return true;
170 }
171 }
172 }
173 Printf("\n\nWARNING: unrecognized flag '%s'; "
174 "use -help=1 to list all flags\n\n", Param);
175 return true;
176}
177
178// We don't use any library to minimize dependencies.
179static void ParseFlags(const Vector<std::string> &Args) {
180 for (size_t F = 0; F < kNumFlags; F++) {
181 if (FlagDescriptions[F].IntFlag)
182 *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default;
183 if (FlagDescriptions[F].UIntFlag)
184 *FlagDescriptions[F].UIntFlag =
185 static_cast<unsigned int>(FlagDescriptions[F].Default);
186 if (FlagDescriptions[F].StrFlag)
187 *FlagDescriptions[F].StrFlag = nullptr;
188 }
189 Inputs = new Vector<std::string>;
190 for (size_t A = 1; A < Args.size(); A++) {
191 if (ParseOneFlag(Args[A].c_str())) {
192 if (Flags.ignore_remaining_args)
193 break;
194 continue;
195 }
196 Inputs->push_back(Args[A]);
197 }
198}
199
200static std::mutex Mu;
201
202static void PulseThread() {
203 while (true) {
204 SleepSeconds(600);
205 std::lock_guard<std::mutex> Lock(Mu);
206 Printf("pulse...\n");
207 }
208}
209
210static void WorkerThread(const Command &BaseCmd, std::atomic<unsigned> *Counter,
211 unsigned NumJobs, std::atomic<bool> *HasErrors) {
212 while (true) {
213 unsigned C = (*Counter)++;
214 if (C >= NumJobs) break;
215 std::string Log = "fuzz-" + std::to_string(C) + ".log";
216 Command Cmd(BaseCmd);
217 Cmd.setOutputFile(Log);
218 Cmd.combineOutAndErr();
219 if (Flags.verbosity) {
220 std::string CommandLine = Cmd.toString();
221 Printf("%s\n", CommandLine.c_str());
222 }
223 int ExitCode = ExecuteCommand(Cmd);
224 if (ExitCode != 0)
225 *HasErrors = true;
226 std::lock_guard<std::mutex> Lock(Mu);
227 Printf("================== Job %u exited with exit code %d ============\n",
228 C, ExitCode);
229 fuzzer::CopyFileToErr(Log);
230 }
231}
232
233std::string CloneArgsWithoutX(const Vector<std::string> &Args,
234 const char *X1, const char *X2) {
235 std::string Cmd;
236 for (auto &S : Args) {
237 if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2))
238 continue;
239 Cmd += S + " ";
240 }
241 return Cmd;
242}
243
244static int RunInMultipleProcesses(const Vector<std::string> &Args,
245 unsigned NumWorkers, unsigned NumJobs) {
246 std::atomic<unsigned> Counter(0);
247 std::atomic<bool> HasErrors(false);
248 Command Cmd(Args);
249 Cmd.removeFlag("jobs");
250 Cmd.removeFlag("workers");
251 Vector<std::thread> V;
252 std::thread Pulse(PulseThread);
253 Pulse.detach();
254 for (unsigned i = 0; i < NumWorkers; i++)
255 V.push_back(std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs, &HasErrors));
256 for (auto &T : V)
257 T.join();
258 return HasErrors ? 1 : 0;
259}
260
261static void RssThread(Fuzzer *F, size_t RssLimitMb) {
262 while (true) {
263 SleepSeconds(1);
264 size_t Peak = GetPeakRSSMb();
265 if (Peak > RssLimitMb)
266 F->RssLimitCallback();
267 }
268}
269
270static void StartRssThread(Fuzzer *F, size_t RssLimitMb) {
271 if (!RssLimitMb) return;
272 std::thread T(RssThread, F, RssLimitMb);
273 T.detach();
274}
275
276int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) {
277 Unit U = FileToVector(InputFilePath);
278 if (MaxLen && MaxLen < U.size())
279 U.resize(MaxLen);
280 F->ExecuteCallback(U.data(), U.size());
281 F->TryDetectingAMemoryLeak(U.data(), U.size(), true);
282 return 0;
283}
284
285static bool AllInputsAreFiles() {
286 if (Inputs->empty()) return false;
287 for (auto &Path : *Inputs)
288 if (!IsFile(Path))
289 return false;
290 return true;
291}
292
293static std::string GetDedupTokenFromFile(const std::string &Path) {
294 auto S = FileToString(Path);
295 auto Beg = S.find("DEDUP_TOKEN:");
296 if (Beg == std::string::npos)
297 return "";
298 auto End = S.find('\n', Beg);
299 if (End == std::string::npos)
300 return "";
301 return S.substr(Beg, End - Beg);
302}
303
304int CleanseCrashInput(const Vector<std::string> &Args,
305 const FuzzingOptions &Options) {
306 if (Inputs->size() != 1 || !Flags.exact_artifact_path) {
307 Printf("ERROR: -cleanse_crash should be given one input file and"
308 " -exact_artifact_path\n");
309 exit(1);
310 }
311 std::string InputFilePath = Inputs->at(0);
312 std::string OutputFilePath = Flags.exact_artifact_path;
313 Command Cmd(Args);
314 Cmd.removeFlag("cleanse_crash");
315
316 assert(Cmd.hasArgument(InputFilePath))(static_cast <bool> (Cmd.hasArgument(InputFilePath)) ? void
(0) : __assert_fail ("Cmd.hasArgument(InputFilePath)", "/build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp"
, 316, __extension__ __PRETTY_FUNCTION__))
;
317 Cmd.removeArgument(InputFilePath);
318
319 auto LogFilePath = DirPlusFile(
320 TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".txt");
321 auto TmpFilePath = DirPlusFile(
322 TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".repro");
323 Cmd.addArgument(TmpFilePath);
324 Cmd.setOutputFile(LogFilePath);
325 Cmd.combineOutAndErr();
326
327 std::string CurrentFilePath = InputFilePath;
328 auto U = FileToVector(CurrentFilePath);
329 size_t Size = U.size();
330
331 const Vector<uint8_t> ReplacementBytes = {' ', 0xff};
332 for (int NumAttempts = 0; NumAttempts < 5; NumAttempts++) {
333 bool Changed = false;
334 for (size_t Idx = 0; Idx < Size; Idx++) {
335 Printf("CLEANSE[%d]: Trying to replace byte %zd of %zd\n", NumAttempts,
336 Idx, Size);
337 uint8_t OriginalByte = U[Idx];
338 if (ReplacementBytes.end() != std::find(ReplacementBytes.begin(),
339 ReplacementBytes.end(),
340 OriginalByte))
341 continue;
342 for (auto NewByte : ReplacementBytes) {
343 U[Idx] = NewByte;
344 WriteToFile(U, TmpFilePath);
345 auto ExitCode = ExecuteCommand(Cmd);
346 RemoveFile(TmpFilePath);
347 if (!ExitCode) {
348 U[Idx] = OriginalByte;
349 } else {
350 Changed = true;
351 Printf("CLEANSE: Replaced byte %zd with 0x%x\n", Idx, NewByte);
352 WriteToFile(U, OutputFilePath);
353 break;
354 }
355 }
356 }
357 if (!Changed) break;
358 }
359 RemoveFile(LogFilePath);
360 return 0;
361}
362
363int MinimizeCrashInput(const Vector<std::string> &Args,
364 const FuzzingOptions &Options) {
365 if (Inputs->size() != 1) {
366 Printf("ERROR: -minimize_crash should be given one input file\n");
367 exit(1);
368 }
369 std::string InputFilePath = Inputs->at(0);
370 Command BaseCmd(Args);
371 BaseCmd.removeFlag("minimize_crash");
372 BaseCmd.removeFlag("exact_artifact_path");
373 assert(BaseCmd.hasArgument(InputFilePath))(static_cast <bool> (BaseCmd.hasArgument(InputFilePath)
) ? void (0) : __assert_fail ("BaseCmd.hasArgument(InputFilePath)"
, "/build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp"
, 373, __extension__ __PRETTY_FUNCTION__))
;
374 BaseCmd.removeArgument(InputFilePath);
375 if (Flags.runs <= 0 && Flags.max_total_time == 0) {
376 Printf("INFO: you need to specify -runs=N or "
377 "-max_total_time=N with -minimize_crash=1\n"
378 "INFO: defaulting to -max_total_time=600\n");
379 BaseCmd.addFlag("max_total_time", "600");
380 }
381
382 auto LogFilePath = DirPlusFile(
383 TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".txt");
384 BaseCmd.setOutputFile(LogFilePath);
385 BaseCmd.combineOutAndErr();
386
387 std::string CurrentFilePath = InputFilePath;
388 while (true) {
389 Unit U = FileToVector(CurrentFilePath);
390 Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n",
391 CurrentFilePath.c_str(), U.size());
392
393 Command Cmd(BaseCmd);
394 Cmd.addArgument(CurrentFilePath);
395
396 std::string CommandLine = Cmd.toString();
397 Printf("CRASH_MIN: executing: %s\n", CommandLine.c_str());
398 int ExitCode = ExecuteCommand(Cmd);
399 if (ExitCode == 0) {
400 Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str());
401 exit(1);
402 }
403 Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize "
404 "it further\n",
405 CurrentFilePath.c_str(), U.size());
406 auto DedupToken1 = GetDedupTokenFromFile(LogFilePath);
407 if (!DedupToken1.empty())
408 Printf("CRASH_MIN: DedupToken1: %s\n", DedupToken1.c_str());
409
410 std::string ArtifactPath =
411 Flags.exact_artifact_path
412 ? Flags.exact_artifact_path
413 : Options.ArtifactPrefix + "minimized-from-" + Hash(U);
414 Cmd.addFlag("minimize_crash_internal_step", "1");
415 Cmd.addFlag("exact_artifact_path", ArtifactPath);
416 CommandLine = Cmd.toString();
417 Printf("CRASH_MIN: executing: %s\n", CommandLine.c_str());
418 ExitCode = ExecuteCommand(Cmd);
419 CopyFileToErr(LogFilePath);
420 if (ExitCode == 0) {
421 if (Flags.exact_artifact_path) {
422 CurrentFilePath = Flags.exact_artifact_path;
423 WriteToFile(U, CurrentFilePath);
424 }
425 Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n",
426 CurrentFilePath.c_str(), U.size());
427 break;
428 }
429 auto DedupToken2 = GetDedupTokenFromFile(LogFilePath);
430 if (!DedupToken2.empty())
431 Printf("CRASH_MIN: DedupToken2: %s\n", DedupToken2.c_str());
432
433 if (DedupToken1 != DedupToken2) {
434 if (Flags.exact_artifact_path) {
435 CurrentFilePath = Flags.exact_artifact_path;
436 WriteToFile(U, CurrentFilePath);
437 }
438 Printf("CRASH_MIN: mismatch in dedup tokens"
439 " (looks like a different bug). Won't minimize further\n");
440 break;
441 }
442
443 CurrentFilePath = ArtifactPath;
444 Printf("*********************************\n");
445 }
446 RemoveFile(LogFilePath);
447 return 0;
448}
449
450int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
451 assert(Inputs->size() == 1)(static_cast <bool> (Inputs->size() == 1) ? void (0)
: __assert_fail ("Inputs->size() == 1", "/build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp"
, 451, __extension__ __PRETTY_FUNCTION__))
;
452 std::string InputFilePath = Inputs->at(0);
453 Unit U = FileToVector(InputFilePath);
454 Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size());
455 if (U.size() < 2) {
456 Printf("INFO: The input is small enough, exiting\n");
457 exit(0);
458 }
459 F->SetMaxInputLen(U.size());
460 F->SetMaxMutationLen(U.size() - 1);
461 F->MinimizeCrashLoop(U);
462 Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n");
463 exit(0);
464 return 0;
465}
466
467int AnalyzeDictionary(Fuzzer *F, const Vector<Unit>& Dict,
468 UnitVector& Corpus) {
469 Printf("Started dictionary minimization (up to %d tests)\n",
470 Dict.size() * Corpus.size() * 2);
471
472 // Scores and usage count for each dictionary unit.
473 Vector<int> Scores(Dict.size());
474 Vector<int> Usages(Dict.size());
475
476 Vector<size_t> InitialFeatures;
477 Vector<size_t> ModifiedFeatures;
478 for (auto &C : Corpus) {
479 // Get coverage for the testcase without modifications.
480 F->ExecuteCallback(C.data(), C.size());
481 InitialFeatures.clear();
482 TPC.CollectFeatures([&](size_t Feature) {
483 InitialFeatures.push_back(Feature);
484 });
485
486 for (size_t i = 0; i < Dict.size(); ++i) {
487 Vector<uint8_t> Data = C;
488 auto StartPos = std::search(Data.begin(), Data.end(),
489 Dict[i].begin(), Dict[i].end());
490 // Skip dictionary unit, if the testcase does not contain it.
491 if (StartPos == Data.end())
492 continue;
493
494 ++Usages[i];
495 while (StartPos != Data.end()) {
496 // Replace all occurrences of dictionary unit in the testcase.
497 auto EndPos = StartPos + Dict[i].size();
498 for (auto It = StartPos; It != EndPos; ++It)
499 *It ^= 0xFF;
500
501 StartPos = std::search(EndPos, Data.end(),
502 Dict[i].begin(), Dict[i].end());
503 }
504
505 // Get coverage for testcase with masked occurrences of dictionary unit.
506 F->ExecuteCallback(Data.data(), Data.size());
507 ModifiedFeatures.clear();
508 TPC.CollectFeatures([&](size_t Feature) {
509 ModifiedFeatures.push_back(Feature);
510 });
511
512 if (InitialFeatures == ModifiedFeatures)
513 --Scores[i];
514 else
515 Scores[i] += 2;
516 }
517 }
518
519 Printf("###### Useless dictionary elements. ######\n");
520 for (size_t i = 0; i < Dict.size(); ++i) {
521 // Dictionary units with positive score are treated as useful ones.
522 if (Scores[i] > 0)
523 continue;
524
525 Printf("\"");
526 PrintASCII(Dict[i].data(), Dict[i].size(), "\"");
527 Printf(" # Score: %d, Used: %d\n", Scores[i], Usages[i]);
528 }
529 Printf("###### End of useless dictionary elements. ######\n");
530 return 0;
531}
532
533int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
534 using namespace fuzzer;
535 assert(argc && argv && "Argument pointers cannot be nullptr")(static_cast <bool> (argc && argv && "Argument pointers cannot be nullptr"
) ? void (0) : __assert_fail ("argc && argv && \"Argument pointers cannot be nullptr\""
, "/build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp"
, 535, __extension__ __PRETTY_FUNCTION__))
;
536 std::string Argv0((*argv)[0]);
537 EF = new ExternalFunctions();
538 if (EF->LLVMFuzzerInitialize)
1
Assuming the condition is false
2
Taking false branch
539 EF->LLVMFuzzerInitialize(argc, argv);
540 const Vector<std::string> Args(*argv, *argv + *argc);
541 assert(!Args.empty())(static_cast <bool> (!Args.empty()) ? void (0) : __assert_fail
("!Args.empty()", "/build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp"
, 541, __extension__ __PRETTY_FUNCTION__))
;
542 ProgName = new std::string(Args[0]);
543 if (Argv0 != *ProgName) {
3
Taking false branch
544 Printf("ERROR: argv[0] has been modified in LLVMFuzzerInitialize\n");
545 exit(1);
546 }
547 ParseFlags(Args);
548 if (Flags.help) {
4
Assuming the condition is false
5
Taking false branch
549 PrintHelp();
550 return 0;
551 }
552
553 if (Flags.close_fd_mask & 2)
6
Assuming the condition is false
7
Taking false branch
554 DupAndCloseStderr();
555 if (Flags.close_fd_mask & 1)
8
Assuming the condition is false
9
Taking false branch
556 CloseStdout();
557
558 if (Flags.jobs > 0 && Flags.workers == 0) {
10
Assuming the condition is false
559 Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs);
560 if (Flags.workers > 1)
561 Printf("Running %u workers\n", Flags.workers);
562 }
563
564 if (Flags.workers > 0 && Flags.jobs > 0)
11
Assuming the condition is false
565 return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs);
566
567 FuzzingOptions Options;
568 Options.Verbosity = Flags.verbosity;
569 Options.MaxLen = Flags.max_len;
570 Options.LenControl = Flags.len_control;
571 Options.UnitTimeoutSec = Flags.timeout;
572 Options.ErrorExitCode = Flags.error_exitcode;
573 Options.TimeoutExitCode = Flags.timeout_exitcode;
574 Options.MaxTotalTimeSec = Flags.max_total_time;
575 Options.DoCrossOver = Flags.cross_over;
576 Options.MutateDepth = Flags.mutate_depth;
577 Options.ReduceDepth = Flags.reduce_depth;
578 Options.UseCounters = Flags.use_counters;
579 Options.UseMemmem = Flags.use_memmem;
580 Options.UseCmp = Flags.use_cmp;
581 Options.UseValueProfile = Flags.use_value_profile;
582 Options.Shrink = Flags.shrink;
583 Options.ReduceInputs = Flags.reduce_inputs;
584 Options.ShuffleAtStartUp = Flags.shuffle;
585 Options.PreferSmall = Flags.prefer_small;
586 Options.ReloadIntervalSec = Flags.reload;
587 Options.OnlyASCII = Flags.only_ascii;
588 Options.DetectLeaks = Flags.detect_leaks;
589 Options.PurgeAllocatorIntervalSec = Flags.purge_allocator_interval;
590 Options.TraceMalloc = Flags.trace_malloc;
591 Options.RssLimitMb = Flags.rss_limit_mb;
592 Options.MallocLimitMb = Flags.malloc_limit_mb;
593 if (!Options.MallocLimitMb)
12
Assuming the condition is false
13
Taking false branch
594 Options.MallocLimitMb = Options.RssLimitMb;
595 if (Flags.runs >= 0)
14
Assuming the condition is false
15
Taking false branch
596 Options.MaxNumberOfRuns = Flags.runs;
597 if (!Inputs->empty() && !Flags.minimize_crash_internal_step)
16
Assuming the condition is false
598 Options.OutputCorpus = (*Inputs)[0];
599 Options.ReportSlowUnits = Flags.report_slow_units;
600 if (Flags.artifact_prefix)
17
Assuming the condition is false
18
Taking false branch
601 Options.ArtifactPrefix = Flags.artifact_prefix;
602 if (Flags.exact_artifact_path)
19
Assuming the condition is false
20
Taking false branch
603 Options.ExactArtifactPath = Flags.exact_artifact_path;
604 Vector<Unit> Dictionary;
605 if (Flags.dict)
21
Assuming the condition is false
22
Taking false branch
606 if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary))
607 return 1;
608 if (Flags.verbosity > 0 && !Dictionary.empty())
23
Assuming the condition is false
609 Printf("Dictionary: %zd entries\n", Dictionary.size());
610 bool DoPlainRun = AllInputsAreFiles();
611 Options.SaveArtifacts =
612 !DoPlainRun || Flags.minimize_crash_internal_step;
613 Options.PrintNewCovPcs = Flags.print_pcs;
614 Options.PrintNewCovFuncs = Flags.print_funcs;
615 Options.PrintFinalStats = Flags.print_final_stats;
616 Options.PrintCorpusStats = Flags.print_corpus_stats;
617 Options.PrintCoverage = Flags.print_coverage;
618 Options.DumpCoverage = Flags.dump_coverage;
619 Options.UseClangCoverage = Flags.use_clang_coverage;
620 Options.UseFeatureFrequency = Flags.use_feature_frequency;
621 if (Flags.exit_on_src_pos)
24
Assuming the condition is false
25
Taking false branch
622 Options.ExitOnSrcPos = Flags.exit_on_src_pos;
623 if (Flags.exit_on_item)
26
Assuming the condition is false
27
Taking false branch
624 Options.ExitOnItem = Flags.exit_on_item;
625
626 unsigned Seed = Flags.seed;
627 // Initialize Seed.
628 if (Seed == 0)
28
Assuming 'Seed' is not equal to 0
29
Taking false branch
629 Seed =
630 std::chrono::system_clock::now().time_since_epoch().count() + GetPid();
631 if (Flags.verbosity)
30
Assuming the condition is false
31
Taking false branch
632 Printf("INFO: Seed: %u\n", Seed);
633
634 Random Rand(Seed);
635 auto *MD = new MutationDispatcher(Rand, Options);
636 auto *Corpus = new InputCorpus(Options.OutputCorpus);
637 auto *F = new Fuzzer(Callback, *Corpus, *MD, Options);
638
639 for (auto &U: Dictionary)
640 if (U.size() <= Word::GetMaxSize())
641 MD->AddWordToManualDictionary(Word(U.data(), U.size()));
642
643 StartRssThread(F, Flags.rss_limit_mb);
644
645 Options.HandleAbrt = Flags.handle_abrt;
646 Options.HandleBus = Flags.handle_bus;
647 Options.HandleFpe = Flags.handle_fpe;
648 Options.HandleIll = Flags.handle_ill;
649 Options.HandleInt = Flags.handle_int;
650 Options.HandleSegv = Flags.handle_segv;
651 Options.HandleTerm = Flags.handle_term;
652 Options.HandleXfsz = Flags.handle_xfsz;
653 Options.HandleUsr1 = Flags.handle_usr1;
654 Options.HandleUsr2 = Flags.handle_usr2;
655 SetSignalHandler(Options);
656
657 std::atexit(Fuzzer::StaticExitCallback);
658
659 if (Flags.minimize_crash)
32
Assuming the condition is false
33
Taking false branch
660 return MinimizeCrashInput(Args, Options);
661
662 if (Flags.minimize_crash_internal_step)
34
Assuming the condition is false
35
Taking false branch
663 return MinimizeCrashInputInternalStep(F, Corpus);
664
665 if (Flags.cleanse_crash)
36
Assuming the condition is false
37
Taking false branch
666 return CleanseCrashInput(Args, Options);
667
668 if (auto Name = Flags.run_equivalence_server) {
38
Assuming 'Name' is non-null
39
Taking true branch
669 SMR.Destroy(Name);
670 if (!SMR.Create(Name)) {
40
Assuming the condition is false
41
Taking false branch
671 Printf("ERROR: can't create shared memory region\n");
672 return 1;
673 }
674 Printf("INFO: EQUIVALENCE SERVER UP\n");
675 while (true) {
42
Loop condition is true. Entering loop body
676 SMR.WaitClient();
677 size_t Size = SMR.ReadByteArraySize();
678 SMR.WriteByteArray(nullptr, 0);
43
Passing null pointer value via 1st parameter 'Bytes'
44
Calling 'SharedMemoryRegion::WriteByteArray'
679 const Unit tmp(SMR.GetByteArray(), SMR.GetByteArray() + Size);
680 F->ExecuteCallback(tmp.data(), tmp.size());
681 SMR.PostServer();
682 }
683 return 0;
684 }
685
686 if (auto Name = Flags.use_equivalence_server) {
687 if (!SMR.Open(Name)) {
688 Printf("ERROR: can't open shared memory region\n");
689 return 1;
690 }
691 Printf("INFO: EQUIVALENCE CLIENT UP\n");
692 }
693
694 if (DoPlainRun) {
695 Options.SaveArtifacts = false;
696 int Runs = std::max(1, Flags.runs);
697 Printf("%s: Running %zd inputs %d time(s) each.\n", ProgName->c_str(),
698 Inputs->size(), Runs);
699 for (auto &Path : *Inputs) {
700 auto StartTime = system_clock::now();
701 Printf("Running: %s\n", Path.c_str());
702 for (int Iter = 0; Iter < Runs; Iter++)
703 RunOneTest(F, Path.c_str(), Options.MaxLen);
704 auto StopTime = system_clock::now();
705 auto MS = duration_cast<milliseconds>(StopTime - StartTime).count();
706 Printf("Executed %s in %zd ms\n", Path.c_str(), (long)MS);
707 }
708 Printf("***\n"
709 "*** NOTE: fuzzing was not performed, you have only\n"
710 "*** executed the target code on a fixed set of inputs.\n"
711 "***\n");
712 F->PrintFinalStats();
713 exit(0);
714 }
715
716 if (Flags.merge) {
717 F->CrashResistantMerge(Args, *Inputs,
718 Flags.load_coverage_summary,
719 Flags.save_coverage_summary,
720 Flags.merge_control_file);
721 exit(0);
722 }
723
724 if (Flags.merge_inner) {
725 const size_t kDefaultMaxMergeLen = 1 << 20;
726 if (Options.MaxLen == 0)
727 F->SetMaxInputLen(kDefaultMaxMergeLen);
728 assert(Flags.merge_control_file)(static_cast <bool> (Flags.merge_control_file) ? void (
0) : __assert_fail ("Flags.merge_control_file", "/build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp"
, 728, __extension__ __PRETTY_FUNCTION__))
;
729 F->CrashResistantMergeInternalStep(Flags.merge_control_file);
730 exit(0);
731 }
732
733 if (Flags.analyze_dict) {
734 size_t MaxLen = INT_MAX2147483647; // Large max length.
735 UnitVector InitialCorpus;
736 for (auto &Inp : *Inputs) {
737 Printf("Loading corpus dir: %s\n", Inp.c_str());
738 ReadDirToVectorOfUnits(Inp.c_str(), &InitialCorpus, nullptr,
739 MaxLen, /*ExitOnError=*/false);
740 }
741
742 if (Dictionary.empty() || Inputs->empty()) {
743 Printf("ERROR: can't analyze dict without dict and corpus provided\n");
744 return 1;
745 }
746 if (AnalyzeDictionary(F, Dictionary, InitialCorpus)) {
747 Printf("Dictionary analysis failed\n");
748 exit(1);
749 }
750 Printf("Dictionary analysis suceeded\n");
751 exit(0);
752 }
753
754 F->Loop(*Inputs);
755
756 if (Flags.verbosity)
757 Printf("Done %zd runs in %zd second(s)\n", F->getTotalNumberOfRuns(),
758 F->secondsSinceProcessStartUp());
759 F->PrintFinalStats();
760
761 exit(0); // Don't let F destroy itself.
762}
763
764// Storage for global ExternalFunctions object.
765ExternalFunctions *EF = nullptr;
766
767} // namespace fuzzer

/build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerShmem.h

1//===- FuzzerShmem.h - shared memory interface ------------------*- C++ -* ===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9// SharedMemoryRegion
10//===----------------------------------------------------------------------===//
11
12#ifndef LLVM_FUZZER_SHMEM_H
13#define LLVM_FUZZER_SHMEM_H
14
15#include <algorithm>
16#include <cstring>
17#include <string>
18
19#include "FuzzerDefs.h"
20
21namespace fuzzer {
22
23class SharedMemoryRegion {
24 public:
25 bool Create(const char *Name);
26 bool Open(const char *Name);
27 bool Destroy(const char *Name);
28 uint8_t *GetData() { return Data; }
29 void PostServer() {Post(0);}
30 void WaitServer() {Wait(0);}
31 void PostClient() {Post(1);}
32 void WaitClient() {Wait(1);}
33
34 size_t WriteByteArray(const uint8_t *Bytes, size_t N) {
35 assert(N <= kShmemSize - sizeof(N))(static_cast <bool> (N <= kShmemSize - sizeof(N)) ? void
(0) : __assert_fail ("N <= kShmemSize - sizeof(N)", "/build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerShmem.h"
, 35, __extension__ __PRETTY_FUNCTION__))
;
36 memcpy(GetData(), &N, sizeof(N));
37 memcpy(GetData() + sizeof(N), Bytes, N);
45
Null pointer passed as an argument to a 'nonnull' parameter
38 assert(N == ReadByteArraySize())(static_cast <bool> (N == ReadByteArraySize()) ? void (
0) : __assert_fail ("N == ReadByteArraySize()", "/build/llvm-toolchain-snapshot-7~svn326551/projects/compiler-rt/lib/fuzzer/FuzzerShmem.h"
, 38, __extension__ __PRETTY_FUNCTION__))
;
39 return N;
40 }
41 size_t ReadByteArraySize() {
42 size_t Res;
43 memcpy(&Res, GetData(), sizeof(Res));
44 return Res;
45 }
46 uint8_t *GetByteArray() { return GetData() + sizeof(size_t); }
47
48 bool IsServer() const { return Data && IAmServer; }
49 bool IsClient() const { return Data && !IAmServer; }
50
51private:
52
53 static const size_t kShmemSize = 1 << 22;
54 bool IAmServer;
55 std::string Path(const char *Name);
56 std::string SemName(const char *Name, int Idx);
57 void Post(int Idx);
58 void Wait(int Idx);
59
60 bool Map(int fd);
61 uint8_t *Data = nullptr;
62 void *Semaphore[2];
63};
64
65extern SharedMemoryRegion SMR;
66
67} // namespace fuzzer
68
69#endif // LLVM_FUZZER_SHMEM_H