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