[libFuzzer] experimental flag -drill (another search heuristic; Mike Aizatsky's idea)
[oota-llvm.git] / lib / Fuzzer / FuzzerLoop.cpp
1 //===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===//
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 // Fuzzer's main loop.
10 //===----------------------------------------------------------------------===//
11
12 #include "FuzzerInternal.h"
13 #include <sanitizer/coverage_interface.h>
14 #include <algorithm>
15
16 extern "C" {
17 // Re-declare some of the sanitizer functions as "weak" so that
18 // libFuzzer can be linked w/o the sanitizers and sanitizer-coveragte
19 // (in which case it will complain at start-up time).
20 __attribute__((weak)) void __sanitizer_print_stack_trace();
21 __attribute__((weak)) void __sanitizer_reset_coverage();
22 __attribute__((weak)) size_t __sanitizer_get_total_unique_caller_callee_pairs();
23 __attribute__((weak)) size_t __sanitizer_get_total_unique_coverage();
24 __attribute__((weak))
25 void __sanitizer_set_death_callback(void (*callback)(void));
26 __attribute__((weak)) size_t __sanitizer_get_number_of_counters();
27 __attribute__((weak))
28 uintptr_t __sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset);
29 }
30
31 namespace fuzzer {
32 static const size_t kMaxUnitSizeToPrint = 256;
33
34 static void MissingWeakApiFunction(const char *FnName) {
35   Printf("ERROR: %s is not defined. Exiting.\n"
36          "Did you use -fsanitize-coverage=... to build your code?\n", FnName);
37   exit(1);
38 }
39
40 #define CHECK_WEAK_API_FUNCTION(fn)                                            \
41   do {                                                                         \
42     if (!fn)                                                                   \
43       MissingWeakApiFunction(#fn);                                             \
44   } while (false)
45
46 // Only one Fuzzer per process.
47 static Fuzzer *F;
48
49 Fuzzer::Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options)
50     : USF(USF), Options(Options) {
51   SetDeathCallback();
52   InitializeTraceState();
53   assert(!F);
54   F = this;
55 }
56
57 void Fuzzer::SetDeathCallback() {
58   CHECK_WEAK_API_FUNCTION(__sanitizer_set_death_callback);
59   __sanitizer_set_death_callback(StaticDeathCallback);
60 }
61
62 void Fuzzer::PrintUnitInASCII(const Unit &U, const char *PrintAfter) {
63   PrintASCII(U, PrintAfter);
64 }
65
66 void Fuzzer::StaticDeathCallback() {
67   assert(F);
68   F->DeathCallback();
69 }
70
71 void Fuzzer::DeathCallback() {
72   Printf("DEATH:\n");
73   if (CurrentUnit.size() <= kMaxUnitSizeToPrint) {
74     Print(CurrentUnit, "\n");
75     PrintUnitInASCII(CurrentUnit, "\n");
76   }
77   WriteUnitToFileWithPrefix(CurrentUnit, "crash-");
78 }
79
80 void Fuzzer::StaticAlarmCallback() {
81   assert(F);
82   F->AlarmCallback();
83 }
84
85 void Fuzzer::AlarmCallback() {
86   assert(Options.UnitTimeoutSec > 0);
87   size_t Seconds =
88       duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
89   if (Seconds == 0) return;
90   if (Options.Verbosity >= 2)
91     Printf("AlarmCallback %zd\n", Seconds);
92   if (Seconds >= (size_t)Options.UnitTimeoutSec) {
93     Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
94     Printf("       and the timeout value is %d (use -timeout=N to change)\n",
95            Options.UnitTimeoutSec);
96     if (CurrentUnit.size() <= kMaxUnitSizeToPrint) {
97       Print(CurrentUnit, "\n");
98       PrintUnitInASCII(CurrentUnit, "\n");
99     }
100     WriteUnitToFileWithPrefix(CurrentUnit, "timeout-");
101     Printf("==%d== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
102            Seconds);
103     if (__sanitizer_print_stack_trace)
104       __sanitizer_print_stack_trace();
105     Printf("SUMMARY: libFuzzer: timeout\n");
106     exit(1);
107   }
108 }
109
110 void Fuzzer::PrintStats(const char *Where, const char *End) {
111   if (!Options.Verbosity) return;
112   size_t Seconds = secondsSinceProcessStartUp();
113   size_t ExecPerSec = (Seconds ? TotalNumberOfRuns / Seconds : 0);
114   Printf("#%zd\t%s", TotalNumberOfRuns, Where);
115   if (LastRecordedBlockCoverage)
116     Printf(" cov: %zd", LastRecordedBlockCoverage);
117   if (auto TB = TotalBits())
118     Printf(" bits: %zd", TB);
119   if (LastRecordedCallerCalleeCoverage)
120     Printf(" indir: %zd", LastRecordedCallerCalleeCoverage);
121   Printf(" units: %zd exec/s: %zd", Corpus.size(), ExecPerSec);
122   if (TotalNumberOfExecutedTraceBasedMutations)
123     Printf(" tbm: %zd", TotalNumberOfExecutedTraceBasedMutations);
124   Printf("%s", End);
125 }
126
127 void Fuzzer::RereadOutputCorpus() {
128   if (Options.OutputCorpus.empty()) return;
129   std::vector<Unit> AdditionalCorpus;
130   ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus,
131                          &EpochOfLastReadOfOutputCorpus);
132   if (Corpus.empty()) {
133     Corpus = AdditionalCorpus;
134     return;
135   }
136   if (!Options.Reload) return;
137   if (Options.Verbosity >= 2)
138     Printf("Reload: read %zd new units.\n",  AdditionalCorpus.size());
139   for (auto &X : AdditionalCorpus) {
140     if (X.size() > (size_t)Options.MaxLen)
141       X.resize(Options.MaxLen);
142     if (UnitHashesAddedToCorpus.insert(Hash(X)).second) {
143       CurrentUnit.clear();
144       CurrentUnit.insert(CurrentUnit.begin(), X.begin(), X.end());
145       if (RunOne(CurrentUnit)) {
146         Corpus.push_back(X);
147         if (Options.Verbosity >= 1)
148           PrintStats("RELOAD");
149       }
150     }
151   }
152 }
153
154 void Fuzzer::ShuffleAndMinimize() {
155   bool PreferSmall = (Options.PreferSmallDuringInitialShuffle == 1 ||
156                       (Options.PreferSmallDuringInitialShuffle == -1 &&
157                        USF.GetRand().RandBool()));
158   if (Options.Verbosity)
159     Printf("PreferSmall: %d\n", PreferSmall);
160   PrintStats("READ  ");
161   std::vector<Unit> NewCorpus;
162   if (Options.ShuffleAtStartUp) {
163     std::random_shuffle(Corpus.begin(), Corpus.end(), USF.GetRand());
164     if (PreferSmall)
165       std::stable_sort(
166           Corpus.begin(), Corpus.end(),
167           [](const Unit &A, const Unit &B) { return A.size() < B.size(); });
168   }
169   Unit &U = CurrentUnit;
170   for (const auto &C : Corpus) {
171     for (size_t First = 0; First < 1; First++) {
172       U.clear();
173       size_t Last = std::min(First + Options.MaxLen, C.size());
174       U.insert(U.begin(), C.begin() + First, C.begin() + Last);
175       if (Options.OnlyASCII)
176         ToASCII(U);
177       if (RunOne(U)) {
178         NewCorpus.push_back(U);
179         if (Options.Verbosity >= 2)
180           Printf("NEW0: %zd L %zd\n", LastRecordedBlockCoverage, U.size());
181       }
182     }
183   }
184   Corpus = NewCorpus;
185   for (auto &X : Corpus)
186     UnitHashesAddedToCorpus.insert(Hash(X));
187   PrintStats("INITED");
188 }
189
190 bool Fuzzer::RunOne(const Unit &U) {
191   UnitStartTime = system_clock::now();
192   TotalNumberOfRuns++;
193
194   PrepareCoverageBeforeRun();
195   ExecuteCallback(U);
196   bool Res = CheckCoverageAfterRun();
197
198   auto UnitStopTime = system_clock::now();
199   auto TimeOfUnit =
200       duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
201   if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1))
202       && secondsSinceProcessStartUp() >= 2
203       && Options.Verbosity)
204     PrintStats("pulse ");
205   if (TimeOfUnit > TimeOfLongestUnitInSeconds &&
206       TimeOfUnit >= Options.ReportSlowUnits) {
207     TimeOfLongestUnitInSeconds = TimeOfUnit;
208     Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
209     WriteUnitToFileWithPrefix(U, "slow-unit-");
210   }
211   return Res;
212 }
213
214 void Fuzzer::RunOneAndUpdateCorpus(Unit &U) {
215   if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
216     return;
217   if (Options.OnlyASCII)
218     ToASCII(U);
219   if (RunOne(U))
220     ReportNewCoverage(U);
221 }
222
223 void Fuzzer::ExecuteCallback(const Unit &U) {
224   int Res = USF.TargetFunction(U.data(), U.size());
225   (void)Res;
226   assert(Res == 0);
227 }
228
229 size_t Fuzzer::RecordBlockCoverage() {
230   CHECK_WEAK_API_FUNCTION(__sanitizer_get_total_unique_coverage);
231   return LastRecordedBlockCoverage = __sanitizer_get_total_unique_coverage();
232 }
233
234 size_t Fuzzer::RecordCallerCalleeCoverage() {
235   if (!Options.UseIndirCalls)
236     return 0;
237   if (!__sanitizer_get_total_unique_caller_callee_pairs)
238     return 0;
239   return LastRecordedCallerCalleeCoverage =
240              __sanitizer_get_total_unique_caller_callee_pairs();
241 }
242
243 void Fuzzer::PrepareCoverageBeforeRun() {
244   if (Options.UseCounters) {
245     size_t NumCounters = __sanitizer_get_number_of_counters();
246     CounterBitmap.resize(NumCounters);
247     __sanitizer_update_counter_bitset_and_clear_counters(0);
248   }
249   RecordBlockCoverage();
250   RecordCallerCalleeCoverage();
251 }
252
253 bool Fuzzer::CheckCoverageAfterRun() {
254   size_t OldCoverage = LastRecordedBlockCoverage;
255   size_t NewCoverage = RecordBlockCoverage();
256   size_t OldCallerCalleeCoverage = LastRecordedCallerCalleeCoverage;
257   size_t NewCallerCalleeCoverage = RecordCallerCalleeCoverage();
258   size_t NumNewBits = 0;
259   if (Options.UseCounters)
260     NumNewBits = __sanitizer_update_counter_bitset_and_clear_counters(
261         CounterBitmap.data());
262   return NewCoverage > OldCoverage ||
263          NewCallerCalleeCoverage > OldCallerCalleeCoverage || NumNewBits;
264 }
265
266 void Fuzzer::WriteToOutputCorpus(const Unit &U) {
267   if (Options.OutputCorpus.empty()) return;
268   std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
269   WriteToFile(U, Path);
270   if (Options.Verbosity >= 2)
271     Printf("Written to %s\n", Path.c_str());
272   assert(!Options.OnlyASCII || IsASCII(U));
273 }
274
275 void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
276   if (!Options.SaveArtifacts)
277     return;
278   std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
279   WriteToFile(U, Path);
280   Printf("artifact_prefix='%s'; Test unit written to %s\n",
281          Options.ArtifactPrefix.c_str(), Path.c_str());
282   if (U.size() <= kMaxUnitSizeToPrint) {
283     Printf("Base64: ");
284     PrintFileAsBase64(Path);
285   }
286 }
287
288 void Fuzzer::SaveCorpus() {
289   if (Options.OutputCorpus.empty()) return;
290   for (const auto &U : Corpus)
291     WriteToFile(U, DirPlusFile(Options.OutputCorpus, Hash(U)));
292   if (Options.Verbosity)
293     Printf("Written corpus of %zd files to %s\n", Corpus.size(),
294            Options.OutputCorpus.c_str());
295 }
296
297 void Fuzzer::PrintStatusForNewUnit(const Unit &U) {
298   if (!Options.PrintNEW)
299     return;
300   PrintStats("NEW   ", "");
301   if (Options.Verbosity) {
302     Printf(" L: %zd", U.size());
303     if (U.size() < 30) {
304       Printf(" ");
305       PrintUnitInASCII(U, "\t");
306       Print(U);
307     }
308     Printf("\n");
309   }
310 }
311
312 void Fuzzer::ReportNewCoverage(const Unit &U) {
313   Corpus.push_back(U);
314   UnitHashesAddedToCorpus.insert(Hash(U));
315   PrintStatusForNewUnit(U);
316   WriteToOutputCorpus(U);
317   if (Options.ExitOnFirst)
318     exit(0);
319 }
320
321 void Fuzzer::Merge(const std::vector<std::string> &Corpora) {
322   if (Corpora.size() <= 1) {
323     Printf("Merge requires two or more corpus dirs\n");
324     return;
325   }
326   auto InitialCorpusDir = Corpora[0];
327   ReadDir(InitialCorpusDir, nullptr);
328   Printf("Merge: running the initial corpus '%s' of %d units\n",
329          InitialCorpusDir.c_str(), Corpus.size());
330   for (auto &U : Corpus)
331     RunOne(U);
332
333   std::vector<std::string> ExtraCorpora(Corpora.begin() + 1, Corpora.end());
334
335   size_t NumTried = 0;
336   size_t NumMerged = 0;
337   for (auto &C : ExtraCorpora) {
338     Corpus.clear();
339     ReadDir(C, nullptr);
340     Printf("Merge: merging the extra corpus '%s' of %zd units\n", C.c_str(),
341            Corpus.size());
342     for (auto &U : Corpus) {
343       NumTried++;
344       if (RunOne(U)) {
345         WriteToOutputCorpus(U);
346         NumMerged++;
347       }
348     }
349   }
350   Printf("Merge: written %zd out of %zd units\n", NumMerged, NumTried);
351 }
352
353 void Fuzzer::MutateAndTestOne(Unit *U) {
354   for (int i = 0; i < Options.MutateDepth; i++) {
355     StartTraceRecording();
356     size_t Size = U->size();
357     U->resize(Options.MaxLen);
358     size_t NewSize = USF.Mutate(U->data(), Size, U->size());
359     assert(NewSize > 0 && "Mutator returned empty unit");
360     assert(NewSize <= (size_t)Options.MaxLen &&
361            "Mutator return overisized unit");
362     U->resize(NewSize);
363     RunOneAndUpdateCorpus(*U);
364     size_t NumTraceBasedMutations = StopTraceRecording();
365     size_t TBMWidth =
366         std::min((size_t)Options.TBMWidth, NumTraceBasedMutations);
367     size_t TBMDepth =
368         std::min((size_t)Options.TBMDepth, NumTraceBasedMutations);
369     Unit BackUp = *U;
370     for (size_t w = 0; w < TBMWidth; w++) {
371       *U = BackUp;
372       for (size_t d = 0; d < TBMDepth; d++) {
373         TotalNumberOfExecutedTraceBasedMutations++;
374         ApplyTraceBasedMutation(USF.GetRand()(NumTraceBasedMutations), U);
375         RunOneAndUpdateCorpus(*U);
376       }
377     }
378   }
379 }
380
381 // Returns an index of random unit from the corpus to mutate.
382 // Hypothesis: units added to the corpus last are more likely to be interesting.
383 // This function gives more wieght to the more recent units.
384 size_t Fuzzer::ChooseUnitIdxToMutate() {
385     size_t N = Corpus.size();
386     size_t Total = (N + 1) * N / 2;
387     size_t R = USF.GetRand()(Total);
388     size_t IdxBeg = 0, IdxEnd = N;
389     // Binary search.
390     while (IdxEnd - IdxBeg >= 2) {
391       size_t Idx = IdxBeg + (IdxEnd - IdxBeg) / 2;
392       if (R > (Idx + 1) * Idx / 2)
393         IdxBeg = Idx;
394       else
395         IdxEnd = Idx;
396     }
397     assert(IdxBeg < N);
398     return IdxBeg;
399 }
400
401 // Experimental search heuristic: drilling.
402 // - Read, shuffle, execute and minimize the corpus.
403 // - Choose one random unit.
404 // - Reset the coverage.
405 // - Start fuzzing as if the chosen unit was the only element of the corpus.
406 // - When done, reset the coverage again.
407 // - Merge the newly created corpus into the original one.
408 void Fuzzer::Drill() {
409   // The corpus is already read, shuffled, and minimized.
410   assert(!Corpus.empty());
411   Options.PrintNEW = false;  // Don't print NEW status lines when drilling.
412
413   Unit U = ChooseUnitToMutate();
414
415   CHECK_WEAK_API_FUNCTION(__sanitizer_reset_coverage);
416   __sanitizer_reset_coverage();
417
418   std::vector<Unit> SavedCorpus;
419   SavedCorpus.swap(Corpus);
420   Corpus.push_back(U);
421   assert(Corpus.size() == 1);
422   RunOne(U);
423   PrintStats("DRILL ");
424   std::string SavedOutputCorpusPath; // Don't write new units while drilling.
425   SavedOutputCorpusPath.swap(Options.OutputCorpus);
426   Loop();
427
428   __sanitizer_reset_coverage();
429
430   PrintStats("REINIT");
431   SavedOutputCorpusPath.swap(Options.OutputCorpus);
432   for (auto &U : SavedCorpus)
433     RunOne(U);
434   PrintStats("MERGE ");
435   Options.PrintNEW = true;
436   size_t NumMerged = 0;
437   for (auto &U : Corpus) {
438     if (RunOne(U)) {
439       PrintStatusForNewUnit(U);
440       NumMerged++;
441       WriteToOutputCorpus(U);
442     }
443   }
444   PrintStats("MERGED");
445   if (NumMerged && Options.Verbosity)
446     Printf("Drilling discovered %zd new units\n", NumMerged);
447 }
448
449 void Fuzzer::Loop() {
450   while (true) {
451     size_t J1 = ChooseUnitIdxToMutate();;
452     SyncCorpus();
453     RereadOutputCorpus();
454     if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
455       return;
456     if (Options.MaxTotalTimeSec > 0 &&
457         secondsSinceProcessStartUp() >
458         static_cast<size_t>(Options.MaxTotalTimeSec))
459       return;
460     CurrentUnit = Corpus[J1];
461     // Optionally, cross with another unit.
462     if (Options.DoCrossOver && USF.GetRand().RandBool()) {
463       size_t J2 = ChooseUnitIdxToMutate();
464       if (!Corpus[J1].empty() && !Corpus[J2].empty()) {
465         assert(!Corpus[J2].empty());
466         CurrentUnit.resize(Options.MaxLen);
467         size_t NewSize = USF.CrossOver(
468             Corpus[J1].data(), Corpus[J1].size(), Corpus[J2].data(),
469             Corpus[J2].size(), CurrentUnit.data(), CurrentUnit.size());
470         assert(NewSize > 0 && "CrossOver returned empty unit");
471         assert(NewSize <= (size_t)Options.MaxLen &&
472                "CrossOver returned overisized unit");
473         CurrentUnit.resize(NewSize);
474       }
475     }
476     // Perform several mutations and runs.
477     MutateAndTestOne(&CurrentUnit);
478   }
479 }
480
481 void Fuzzer::SyncCorpus() {
482   if (Options.SyncCommand.empty() || Options.OutputCorpus.empty()) return;
483   auto Now = system_clock::now();
484   if (duration_cast<seconds>(Now - LastExternalSync).count() <
485       Options.SyncTimeout)
486     return;
487   LastExternalSync = Now;
488   ExecuteCommand(Options.SyncCommand + " " + Options.OutputCorpus);
489 }
490
491 }  // namespace fuzzer