38 #define FUZZER_FLAG_INT(Name, Default, Description) int Name;
39 #define FUZZER_FLAG_STRING(Name, Description) const char *Name;
40 #include "FuzzerFlags.def"
41 #undef FUZZER_FLAG_INT
42 #undef FUZZER_FLAG_STRING
46 #define FUZZER_FLAG_INT(Name, Default, Description) \
47 { #Name, Description, Default, &Flags.Name, nullptr},
48 #define FUZZER_FLAG_STRING(Name, Description) \
49 { #Name, Description, 0, nullptr, &Flags.Name },
50 #include "FuzzerFlags.def"
51 #undef FUZZER_FLAG_INT
52 #undef FUZZER_FLAG_STRING
56 sizeof(FlagDescriptions) /
sizeof(FlagDescriptions[0]);
58 static std::vector<std::string>
inputs;
62 Printf(
"Usage: %s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n",
64 Printf(
"\nFlags: (strictly in form -flag=value)\n");
65 size_t MaxFlagLen = 0;
67 MaxFlagLen = std::max(strlen(FlagDescriptions[
F].
Name), MaxFlagLen);
70 const auto &D = FlagDescriptions[
F];
72 for (
size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++)
75 Printf(
"%d\t%s\n", D.Default, D.Description);
77 Printf(
"\nFlags starting with '--' will be ignored and "
78 "will be passed verbatim to subprocesses.\n");
81 static const char *
FlagValue(
const char *Param,
const char *Name) {
82 size_t Len = strlen(Name);
83 if (Param[0] ==
'-' && strstr(Param + 1, Name) == Param + 1 &&
84 Param[Len + 1] ==
'=')
85 return &Param[Len + 2];
90 if (Param[0] !=
'-')
return false;
91 if (Param[1] ==
'-') {
92 static bool PrintedWarning =
false;
93 if (!PrintedWarning) {
94 PrintedWarning =
true;
95 Printf(
"WARNING: libFuzzer ignores flags that start with '--'\n");
100 const char *Name = FlagDescriptions[
F].Name;
103 if (FlagDescriptions[
F].IntFlag) {
104 int Val = std::stol(Str);
105 *FlagDescriptions[
F].IntFlag = Val;
106 if (
Flags.verbosity >= 2)
107 Printf(
"Flag: %s %d\n", Name, Val);;
109 }
else if (FlagDescriptions[
F].StrFlag) {
110 *FlagDescriptions[
F].StrFlag = Str;
111 if (
Flags.verbosity >= 2)
112 Printf(
"Flag: %s %s\n", Name, Str);
122 static void ParseFlags(
int argc,
char **argv) {
124 if (FlagDescriptions[
F].IntFlag)
125 *FlagDescriptions[
F].IntFlag = FlagDescriptions[
F].Default;
126 if (FlagDescriptions[
F].StrFlag)
127 *FlagDescriptions[
F].StrFlag =
nullptr;
129 for (
int A = 1;
A < argc;
A++) {
131 inputs.push_back(argv[A]);
135 static std::mutex
Mu;
139 std::this_thread::sleep_for(std::chrono::seconds(600));
140 std::lock_guard<std::mutex>
Lock(
Mu);
145 static void WorkerThread(
const std::string &Cmd, std::atomic<int> *Counter,
146 int NumJobs, std::atomic<bool> *HasErrors) {
148 int C = (*Counter)++;
149 if (C >= NumJobs)
break;
150 std::string Log =
"fuzz-" + std::to_string(C) +
".log";
151 std::string ToRun = Cmd +
" > " + Log +
" 2>&1\n";
153 Printf(
"%s", ToRun.c_str());
154 int ExitCode = system(ToRun.c_str());
158 Printf(
"================== Job %d exited with exit code %d ============\n",
166 std::atomic<int> Counter(0);
167 std::atomic<bool> HasErrors(
false);
169 for (
int i = 0; i < argc; i++) {
174 std::vector<std::thread> V;
177 for (
int i = 0; i < NumWorkers; i++)
178 V.push_back(std::thread(
WorkerThread, Cmd, &Counter, NumJobs, &HasErrors));
181 return HasErrors ? 1 : 0;
184 std::vector<std::string>
ReadTokensFile(
const char *TokensFilePath) {
185 if (!TokensFilePath)
return {};
186 std::string TokensFileContents =
FileToString(TokensFilePath);
187 std::istringstream ISS(TokensFileContents);
188 std::vector<std::string> Res = {std::istream_iterator<std::string>{ISS},
189 std::istream_iterator<std::string>{}};
205 SimpleUserSuppliedFuzzer SUSF(Callback);
210 using namespace fuzzer;
230 Options.MaxLen =
Flags.max_len;
231 Options.UnitTimeoutSec =
Flags.timeout;
232 Options.DoCrossOver =
Flags.cross_over;
233 Options.MutateDepth =
Flags.mutate_depth;
234 Options.ExitOnFirst =
Flags.exit_on_first;
235 Options.UseCounters =
Flags.use_counters;
236 Options.UseTraces =
Flags.use_traces;
237 Options.UseFullCoverageSet =
Flags.use_full_coverage_set;
238 Options.PreferSmallDuringInitialShuffle =
239 Flags.prefer_small_during_initial_shuffle;
241 Options.Reload =
Flags.reload;
243 Options.MaxNumberOfRuns =
Flags.runs;
245 Options.OutputCorpus =
inputs[0];
247 Options.SyncCommand =
Flags.sync_command;
248 Options.SyncTimeout =
Flags.sync_timeout;
251 if (
Flags.apply_tokens)
257 Seed = time(0) * 10000 + getpid();
263 if (
Flags.timeout > 0)
266 if (
Flags.verbosity >= 2) {
268 for (
auto &
T : Options.Tokens)
275 if (inp != Options.OutputCorpus)
281 if (
Flags.save_minimized_corpus)
int FuzzerDriver(int argc, char **argv, UserCallback Callback)
Simple C-like interface with a single user-supplied callback.
void RereadOutputCorpus()
size_t getTotalNumberOfRuns()
static cl::opt< unsigned long long > Seed("rng-seed", cl::value_desc("seed"), cl::desc("Seed for the random number generator"), cl::init(0))
void ReadDir(const std::string &Path, long *Epoch)
void ShuffleAndMinimize()
void SetTimer(int Seconds)
static const char * ProgName
Unit SubstituteTokens(const Unit &U) const
void Loop(size_t NumIterations)
void(* UserCallback)(const uint8_t *Data, size_t Size)
size_t secondsSinceProcessStartUp()
std::string FileToString(const std::string &Path)
Number of individual test Apply this number of consecutive mutations to each input exit after the first new interesting input is found the minimized corpus is saved into the first input directory Number of jobs to run If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
size_t CorpusSize() const
static std::vector< std::string > inputs
static void ParseFlags(int argc, char **argv)
std::vector< std::string > ReadTokensFile(const char *TokensFilePath)
void Printf(const char *Fmt,...)
static const size_t kNumFlags
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
void AddToCorpus(const Unit &U)
static void WorkerThread(const std::string &Cmd, std::atomic< int > *Counter, int NumJobs, std::atomic< bool > *HasErrors)
An abstract class that allows to use user-supplied mutators with libFuzzer.
void CopyFileToErr(const std::string &Path)
struct fuzzer::@216 Flags
static void PulseThread()
Unit FileToVector(const std::string &Path)
int ApplyTokens(const Fuzzer &F, const char *InputFilePath)
std::vector< uint8_t > Unit
static bool ParseOneFlag(const char *Param)
static int RunInMultipleProcesses(int argc, char **argv, int NumWorkers, int NumJobs)
static const char * FlagValue(const char *Param, const char *Name)