[libFuzzer] remove the deprecated 'tokens' feature
[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 __attribute__((weak)) void __sanitizer_print_stack_trace();
18 }
19
20 namespace fuzzer {
21 static const size_t kMaxUnitSizeToPrint = 256;
22
23 // Only one Fuzzer per process.
24 static Fuzzer *F;
25
26 Fuzzer::Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options)
27     : USF(USF), Options(Options) {
28   SetDeathCallback();
29   InitializeTraceState();
30   assert(!F);
31   F = this;
32 }
33
34 void Fuzzer::SetDeathCallback() {
35   __sanitizer_set_death_callback(StaticDeathCallback);
36 }
37
38 void Fuzzer::PrintUnitInASCII(const Unit &U, const char *PrintAfter) {
39   PrintASCII(U, PrintAfter);
40 }
41
42 void Fuzzer::StaticDeathCallback() {
43   assert(F);
44   F->DeathCallback();
45 }
46
47 void Fuzzer::DeathCallback() {
48   Printf("DEATH:\n");
49   if (CurrentUnit.size() <= kMaxUnitSizeToPrint) {
50     Print(CurrentUnit, "\n");
51     PrintUnitInASCII(CurrentUnit, "\n");
52   }
53   WriteUnitToFileWithPrefix(CurrentUnit, "crash-");
54 }
55
56 void Fuzzer::StaticAlarmCallback() {
57   assert(F);
58   F->AlarmCallback();
59 }
60
61 void Fuzzer::AlarmCallback() {
62   assert(Options.UnitTimeoutSec > 0);
63   size_t Seconds =
64       duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
65   if (Seconds == 0) return;
66   if (Options.Verbosity >= 2)
67     Printf("AlarmCallback %zd\n", Seconds);
68   if (Seconds >= (size_t)Options.UnitTimeoutSec) {
69     Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
70     Printf("       and the timeout value is %d (use -timeout=N to change)\n",
71            Options.UnitTimeoutSec);
72     if (CurrentUnit.size() <= kMaxUnitSizeToPrint) {
73       Print(CurrentUnit, "\n");
74       PrintUnitInASCII(CurrentUnit, "\n");
75     }
76     WriteUnitToFileWithPrefix(CurrentUnit, "timeout-");
77     Printf("==%d== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(),
78            Seconds);
79     if (__sanitizer_print_stack_trace)
80       __sanitizer_print_stack_trace();
81     Printf("SUMMARY: libFuzzer: timeout\n");
82     exit(1);
83   }
84 }
85
86 void Fuzzer::PrintStats(const char *Where, size_t Cov, const char *End) {
87   if (!Options.Verbosity) return;
88   size_t Seconds = secondsSinceProcessStartUp();
89   size_t ExecPerSec = (Seconds ? TotalNumberOfRuns / Seconds : 0);
90   Printf("#%zd\t%s cov: %zd bits: %zd units: %zd exec/s: %zd",
91          TotalNumberOfRuns, Where, Cov, TotalBits(), Corpus.size(), ExecPerSec);
92   if (TotalNumberOfExecutedTraceBasedMutations)
93     Printf(" tbm: %zd", TotalNumberOfExecutedTraceBasedMutations);
94   Printf("%s", End);
95 }
96
97 void Fuzzer::RereadOutputCorpus() {
98   if (Options.OutputCorpus.empty()) return;
99   std::vector<Unit> AdditionalCorpus;
100   ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus,
101                          &EpochOfLastReadOfOutputCorpus);
102   if (Corpus.empty()) {
103     Corpus = AdditionalCorpus;
104     return;
105   }
106   if (!Options.Reload) return;
107   if (Options.Verbosity >= 2)
108     Printf("Reload: read %zd new units.\n",  AdditionalCorpus.size());
109   for (auto &X : AdditionalCorpus) {
110     if (X.size() > (size_t)Options.MaxLen)
111       X.resize(Options.MaxLen);
112     if (UnitHashesAddedToCorpus.insert(Hash(X)).second) {
113       CurrentUnit.clear();
114       CurrentUnit.insert(CurrentUnit.begin(), X.begin(), X.end());
115       size_t NewCoverage = RunOne(CurrentUnit);
116       if (NewCoverage) {
117         Corpus.push_back(X);
118         if (Options.Verbosity >= 1)
119           PrintStats("RELOAD", NewCoverage);
120       }
121     }
122   }
123 }
124
125 void Fuzzer::ShuffleAndMinimize() {
126   size_t MaxCov = 0;
127   bool PreferSmall = (Options.PreferSmallDuringInitialShuffle == 1 ||
128                       (Options.PreferSmallDuringInitialShuffle == -1 &&
129                        USF.GetRand().RandBool()));
130   if (Options.Verbosity)
131     Printf("PreferSmall: %d\n", PreferSmall);
132   PrintStats("READ  ", 0);
133   std::vector<Unit> NewCorpus;
134   if (Options.ShuffleAtStartUp) {
135     std::random_shuffle(Corpus.begin(), Corpus.end(), USF.GetRand());
136     if (PreferSmall)
137       std::stable_sort(
138           Corpus.begin(), Corpus.end(),
139           [](const Unit &A, const Unit &B) { return A.size() < B.size(); });
140   }
141   Unit &U = CurrentUnit;
142   for (const auto &C : Corpus) {
143     for (size_t First = 0; First < 1; First++) {
144       U.clear();
145       size_t Last = std::min(First + Options.MaxLen, C.size());
146       U.insert(U.begin(), C.begin() + First, C.begin() + Last);
147       if (Options.OnlyASCII)
148         ToASCII(U);
149       size_t NewCoverage = RunOne(U);
150       if (NewCoverage) {
151         MaxCov = NewCoverage;
152         NewCorpus.push_back(U);
153         if (Options.Verbosity >= 2)
154           Printf("NEW0: %zd L %zd\n", NewCoverage, U.size());
155       }
156     }
157   }
158   Corpus = NewCorpus;
159   for (auto &X : Corpus)
160     UnitHashesAddedToCorpus.insert(Hash(X));
161   PrintStats("INITED", MaxCov);
162 }
163
164 size_t Fuzzer::RunOne(const Unit &U) {
165   UnitStartTime = system_clock::now();
166   TotalNumberOfRuns++;
167   size_t Res = RunOneMaximizeTotalCoverage(U);
168   auto UnitStopTime = system_clock::now();
169   auto TimeOfUnit =
170       duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
171   if (TimeOfUnit > TimeOfLongestUnitInSeconds &&
172       TimeOfUnit >= Options.ReportSlowUnits) {
173     TimeOfLongestUnitInSeconds = TimeOfUnit;
174     Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
175     WriteUnitToFileWithPrefix(U, "slow-unit-");
176   }
177   return Res;
178 }
179
180 void Fuzzer::RunOneAndUpdateCorpus(Unit &U) {
181   if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
182     return;
183   if (Options.OnlyASCII)
184     ToASCII(U);
185   ReportNewCoverage(RunOne(U), U);
186 }
187
188 void Fuzzer::ExecuteCallback(const Unit &U) {
189   int Res = USF.TargetFunction(U.data(), U.size());
190   (void)Res;
191   assert(Res == 0);
192 }
193
194 size_t Fuzzer::RunOneMaximizeTotalCoverage(const Unit &U) {
195   size_t NumCounters = __sanitizer_get_number_of_counters();
196   if (Options.UseCounters) {
197     CounterBitmap.resize(NumCounters);
198     __sanitizer_update_counter_bitset_and_clear_counters(0);
199   }
200   size_t OldCoverage = __sanitizer_get_total_unique_coverage();
201   ExecuteCallback(U);
202   size_t NewCoverage = __sanitizer_get_total_unique_coverage();
203   size_t NumNewBits = 0;
204   if (Options.UseCounters)
205     NumNewBits = __sanitizer_update_counter_bitset_and_clear_counters(
206         CounterBitmap.data());
207
208   if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && Options.Verbosity)
209     PrintStats("pulse ", NewCoverage);
210
211   if (NewCoverage > OldCoverage || NumNewBits)
212     return NewCoverage;
213   return 0;
214 }
215
216 void Fuzzer::WriteToOutputCorpus(const Unit &U) {
217   if (Options.OutputCorpus.empty()) return;
218   std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
219   WriteToFile(U, Path);
220   if (Options.Verbosity >= 2)
221     Printf("Written to %s\n", Path.c_str());
222   assert(!Options.OnlyASCII || IsASCII(U));
223 }
224
225 void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
226   if (!Options.SaveArtifacts)
227     return;
228   std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
229   WriteToFile(U, Path);
230   Printf("artifact_prefix='%s'; Test unit written to %s\n",
231          Options.ArtifactPrefix.c_str(), Path.c_str());
232   if (U.size() <= kMaxUnitSizeToPrint) {
233     Printf("Base64: ");
234     PrintFileAsBase64(Path);
235   }
236 }
237
238 void Fuzzer::SaveCorpus() {
239   if (Options.OutputCorpus.empty()) return;
240   for (const auto &U : Corpus)
241     WriteToFile(U, DirPlusFile(Options.OutputCorpus, Hash(U)));
242   if (Options.Verbosity)
243     Printf("Written corpus of %zd files to %s\n", Corpus.size(),
244            Options.OutputCorpus.c_str());
245 }
246
247 void Fuzzer::ReportNewCoverage(size_t NewCoverage, const Unit &U) {
248   if (!NewCoverage) return;
249   Corpus.push_back(U);
250   UnitHashesAddedToCorpus.insert(Hash(U));
251   PrintStats("NEW   ", NewCoverage, "");
252   if (Options.Verbosity) {
253     Printf(" L: %zd", U.size());
254     if (U.size() < 30) {
255       Printf(" ");
256       PrintUnitInASCII(U, "\t");
257       Print(U);
258     }
259     Printf("\n");
260   }
261   WriteToOutputCorpus(U);
262   if (Options.ExitOnFirst)
263     exit(0);
264 }
265
266 void Fuzzer::MutateAndTestOne(Unit *U) {
267   for (int i = 0; i < Options.MutateDepth; i++) {
268     StartTraceRecording();
269     size_t Size = U->size();
270     U->resize(Options.MaxLen);
271     size_t NewSize = USF.Mutate(U->data(), Size, U->size());
272     assert(NewSize > 0 && "Mutator returned empty unit");
273     assert(NewSize <= (size_t)Options.MaxLen &&
274            "Mutator return overisized unit");
275     U->resize(NewSize);
276     RunOneAndUpdateCorpus(*U);
277     size_t NumTraceBasedMutations = StopTraceRecording();
278     size_t TBMWidth =
279         std::min((size_t)Options.TBMWidth, NumTraceBasedMutations);
280     size_t TBMDepth =
281         std::min((size_t)Options.TBMDepth, NumTraceBasedMutations);
282     Unit BackUp = *U;
283     for (size_t w = 0; w < TBMWidth; w++) {
284       *U = BackUp;
285       for (size_t d = 0; d < TBMDepth; d++) {
286         TotalNumberOfExecutedTraceBasedMutations++;
287         ApplyTraceBasedMutation(USF.GetRand()(NumTraceBasedMutations), U);
288         RunOneAndUpdateCorpus(*U);
289       }
290     }
291   }
292 }
293
294 void Fuzzer::Loop() {
295   for (auto &U: Options.Dictionary)
296     USF.GetMD().AddWordToDictionary(U.data(), U.size());
297
298   while (true) {
299     for (size_t J1 = 0; J1 < Corpus.size(); J1++) {
300       SyncCorpus();
301       RereadOutputCorpus();
302       if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
303         return;
304       if (Options.MaxTotalTimeSec > 0 &&
305           secondsSinceProcessStartUp() >
306               static_cast<size_t>(Options.MaxTotalTimeSec))
307         return;
308       CurrentUnit = Corpus[J1];
309       // Optionally, cross with another unit.
310       if (Options.DoCrossOver && USF.GetRand().RandBool()) {
311         size_t J2 = USF.GetRand()(Corpus.size());
312         if (!Corpus[J1].empty() && !Corpus[J2].empty()) {
313           assert(!Corpus[J2].empty());
314           CurrentUnit.resize(Options.MaxLen);
315           size_t NewSize = USF.CrossOver(
316               Corpus[J1].data(), Corpus[J1].size(), Corpus[J2].data(),
317               Corpus[J2].size(), CurrentUnit.data(), CurrentUnit.size());
318           assert(NewSize > 0 && "CrossOver returned empty unit");
319           assert(NewSize <= (size_t)Options.MaxLen &&
320                  "CrossOver returned overisized unit");
321           CurrentUnit.resize(NewSize);
322         }
323       }
324       // Perform several mutations and runs.
325       MutateAndTestOne(&CurrentUnit);
326     }
327   }
328 }
329
330 void Fuzzer::SyncCorpus() {
331   if (Options.SyncCommand.empty() || Options.OutputCorpus.empty()) return;
332   auto Now = system_clock::now();
333   if (duration_cast<seconds>(Now - LastExternalSync).count() <
334       Options.SyncTimeout)
335     return;
336   LastExternalSync = Now;
337   ExecuteCommand(Options.SyncCommand + " " + Options.OutputCorpus);
338 }
339
340 }  // namespace fuzzer