13 #include <sanitizer/coverage_interface.h>
22 : USF(USF), Options(Options) {
29 void Fuzzer::SetDeathCallback() {
30 __sanitizer_set_death_callback(StaticDeathCallback);
33 void Fuzzer::PrintUnitInASCIIOrTokens(
const Unit &U,
const char *
PrintAfter) {
34 if (Options.
Tokens.empty()) {
43 void Fuzzer::StaticDeathCallback() {
48 void Fuzzer::DeathCallback() {
50 Print(CurrentUnit,
"\n");
51 PrintUnitInASCIIOrTokens(CurrentUnit,
"\n");
52 WriteToCrash(CurrentUnit,
"crash-");
60 void Fuzzer::AlarmCallback() {
64 if (Seconds == 0)
return;
66 Printf(
"AlarmCallback %zd\n", Seconds);
68 Printf(
"ALARM: working on the last Unit for %zd seconds\n", Seconds);
69 Printf(
" and the timeout value is %d (use -timeout=N to change)\n",
71 Print(CurrentUnit,
"\n");
72 PrintUnitInASCIIOrTokens(CurrentUnit,
"\n");
73 WriteToCrash(CurrentUnit,
"timeout-");
78 void Fuzzer::PrintStats(
const char *Where,
size_t Cov,
const char *End) {
81 size_t ExecPerSec = (Seconds ? TotalNumberOfRuns / Seconds : 0);
82 Printf(
"#%zd\t%s cov %zd bits %zd units %zd exec/s %zd %s", TotalNumberOfRuns,
83 Where, Cov, TotalBits(), Corpus.size(), ExecPerSec, End);
88 std::vector<Unit> AdditionalCorpus;
90 &EpochOfLastReadOfOutputCorpus);
92 Corpus = AdditionalCorpus;
95 if (!Options.
Reload)
return;
97 Printf(
"Reload: read %zd new units.\n", AdditionalCorpus.size());
98 for (
auto &
X : AdditionalCorpus) {
99 if (
X.size() > (size_t)Options.
MaxLen)
101 if (UnitHashesAddedToCorpus.insert(
Hash(
X)).second) {
103 CurrentUnit.insert(CurrentUnit.begin(),
X.begin(),
X.end());
104 size_t NewCoverage = RunOne(CurrentUnit);
108 PrintStats(
"RELOAD", NewCoverage);
120 Printf(
"PreferSmall: %d\n", PreferSmall);
121 PrintStats(
"READ ", 0);
122 std::vector<Unit> NewCorpus;
123 std::random_shuffle(Corpus.begin(), Corpus.end());
126 Corpus.begin(), Corpus.end(),
127 [](
const Unit &
A,
const Unit &B) {
return A.size() < B.size(); });
128 Unit &U = CurrentUnit;
129 for (
const auto &C : Corpus) {
130 for (
size_t First = 0; First < 1; First++) {
133 U.insert(U.begin(), C.begin() + First, C.begin() + Last);
134 size_t NewCoverage = RunOne(U);
136 MaxCov = NewCoverage;
137 NewCorpus.push_back(U);
139 Printf(
"NEW0: %zd L %zd\n", NewCoverage, U.size());
144 for (
auto &
X : Corpus)
145 UnitHashesAddedToCorpus.insert(
Hash(
X));
146 PrintStats(
"INITED", MaxCov);
149 size_t Fuzzer::RunOne(
const Unit &U) {
154 Res = RunOneMaximizeFullCoverageSet(U);
156 Res = RunOneMaximizeTotalCoverage(U);
159 duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
160 if (TimeOfUnit > TimeOfLongestUnitInSeconds) {
161 TimeOfLongestUnitInSeconds = TimeOfUnit;
162 Printf(
"Longest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
168 void Fuzzer::RunOneAndUpdateCorpus(
const Unit &U) {
171 ReportNewCoverage(RunOne(U), U);
176 for (uintptr_t i = 0; i < NumPCs; i++) {
177 Res = (Res + PCs[i]) * 7;
185 if (Idx < Options.
Tokens.size()) {
186 std::string Token = Options.
Tokens[Idx];
187 Res.insert(Res.end(), Token.begin(), Token.end());
196 void Fuzzer::ExecuteCallback(
const Unit &U) {
197 if (Options.
Tokens.empty()) {
211 size_t Fuzzer::RunOneMaximizeFullCoverageSet(
const Unit &U) {
212 __sanitizer_reset_coverage();
215 uintptr_t NumPCs =__sanitizer_get_coverage_guards(&PCs);
217 return FullCoverageSets.size();
221 size_t Fuzzer::RunOneMaximizeTotalCoverage(
const Unit &U) {
222 size_t NumCounters = __sanitizer_get_number_of_counters();
224 CounterBitmap.resize(NumCounters);
225 __sanitizer_update_counter_bitset_and_clear_counters(0);
227 size_t OldCoverage = __sanitizer_get_total_unique_coverage();
229 size_t NewCoverage = __sanitizer_get_total_unique_coverage();
230 size_t NumNewBits = 0;
232 NumNewBits = __sanitizer_update_counter_bitset_and_clear_counters(
233 CounterBitmap.data());
235 if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && Options.
Verbosity)
236 PrintStats(
"pulse ", NewCoverage);
238 if (NewCoverage > OldCoverage || NumNewBits)
243 void Fuzzer::WriteToOutputCorpus(
const Unit &U) {
248 Printf(
"Written to %s\n", Path.c_str());
251 void Fuzzer::WriteToCrash(
const Unit &U,
const char *
Prefix) {
252 std::string Path = Prefix +
Hash(U);
254 Printf(
"CRASHED; file written to %s\nBase64: ", Path.c_str());
260 for (
const auto &U : Corpus)
263 Printf(
"Written corpus of %zd files to %s\n", Corpus.size(),
267 void Fuzzer::ReportNewCoverage(
size_t NewCoverage,
const Unit &U) {
268 if (!NewCoverage)
return;
270 UnitHashesAddedToCorpus.insert(
Hash(U));
271 PrintStats(
"NEW ", NewCoverage,
"");
273 Printf(
" L: %zd", U.size());
276 PrintUnitInASCIIOrTokens(U,
"\t");
281 WriteToOutputCorpus(U);
286 void Fuzzer::MutateAndTestOne(
Unit *U) {
288 StartTraceRecording();
289 size_t Size = U->size();
290 U->resize(Options.
MaxLen);
291 size_t NewSize = USF.
Mutate(U->data(), Size, U->size());
292 assert(NewSize > 0 &&
"Mutator returned empty unit");
293 assert(NewSize <= (
size_t)Options.
MaxLen &&
294 "Mutator return overisized unit");
296 RunOneAndUpdateCorpus(*U);
297 size_t NumTraceBasedMutations = StopTraceRecording();
298 for (
size_t j = 0; j < NumTraceBasedMutations; j++) {
299 ApplyTraceBasedMutation(j, U);
300 RunOneAndUpdateCorpus(*U);
306 for (
size_t i = 1; i <= NumIterations; i++) {
307 for (
size_t J1 = 0; J1 < Corpus.size(); J1++) {
313 CurrentUnit = Corpus[J1];
314 MutateAndTestOne(&CurrentUnit);
317 for (
size_t J2 = 0; J2 < Corpus.size(); J2++) {
318 CurrentUnit.resize(Options.
MaxLen);
320 Corpus[J1].data(), Corpus[J1].
size(), Corpus[J2].data(),
321 Corpus[J2].
size(), CurrentUnit.data(), CurrentUnit.size());
322 assert(NewSize > 0 &&
"CrossOver returned empty unit");
323 assert(NewSize <= (
size_t)Options.
MaxLen &&
324 "CrossOver return overisized unit");
325 CurrentUnit.resize(NewSize);
326 MutateAndTestOne(&CurrentUnit);
333 void Fuzzer::SyncCorpus() {
336 if (duration_cast<seconds>(Now - LastExternalSync).count() <
339 LastExternalSync = Now;
void RereadOutputCorpus()
void PrintASCII(const Unit &U, const char *PrintAfter="")
void InitializeTraceState()
void ShuffleAndMinimize()
void Print(const Unit &U, const char *PrintAfter="")
Unit SubstituteTokens(const Unit &U) const
void Loop(size_t NumIterations)
std::vector< std::string > Tokens
size_t secondsSinceProcessStartUp()
void ExecuteCommand(const std::string &Command)
void PrintFileAsBase64(const std::string &Path)
virtual size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, size_t Size2, uint8_t *Out, size_t MaxOutSize)
Crosses 'Data1' and 'Data2', writes up to 'MaxOutSize' bytes into Out, returns the number of bytes wr...
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
void Printf(const char *Fmt,...)
static PassOptionList PrintAfter("print-after", llvm::cl::desc("Print IR after specified passes"), cl::Hidden)
static uintptr_t HashOfArrayOfPCs(uintptr_t *PCs, uintptr_t NumPCs)
std::string DirPlusFile(const std::string &DirPath, const std::string &FileName)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
An abstract class that allows to use user-supplied mutators with libFuzzer.
Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options)
void WriteToFile(const Unit &U, const std::string &Path)
int PreferSmallDuringInitialShuffle
static void StaticAlarmCallback()
std::vector< uint8_t > Unit
void ReadDirToVectorOfUnits(const char *Path, std::vector< Unit > *V, long *Epoch)
std::string Hash(const Unit &U)
static sys::TimeValue now(bool Deterministic)
virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize)
Mutates 'Size' bytes of data in 'Data' inplace into up to 'MaxSize' bytes, returns the new size of th...
virtual void TargetFunction(const uint8_t *Data, size_t Size)=0
Executes the target function on 'Size' bytes of 'Data'.