FuzzerLoop.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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. #include "FuzzerInternal.h"
  12. #include <sanitizer/coverage_interface.h>
  13. #include <algorithm>
  14. namespace fuzzer {
  15. // Only one Fuzzer per process.
  16. static Fuzzer *F;
  17. Fuzzer::Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options)
  18. : USF(USF), Options(Options) {
  19. SetDeathCallback();
  20. InitializeTraceState();
  21. assert(!F);
  22. F = this;
  23. }
  24. void Fuzzer::SetDeathCallback() {
  25. __sanitizer_set_death_callback(StaticDeathCallback);
  26. }
  27. void Fuzzer::PrintUnitInASCIIOrTokens(const Unit &U, const char *PrintAfter) {
  28. if (Options.Tokens.empty()) {
  29. PrintASCII(U, PrintAfter);
  30. } else {
  31. auto T = SubstituteTokens(U);
  32. T.push_back(0);
  33. Printf("%s%s", T.data(), PrintAfter);
  34. }
  35. }
  36. void Fuzzer::StaticDeathCallback() {
  37. assert(F);
  38. F->DeathCallback();
  39. }
  40. void Fuzzer::DeathCallback() {
  41. Printf("DEATH:\n");
  42. Print(CurrentUnit, "\n");
  43. PrintUnitInASCIIOrTokens(CurrentUnit, "\n");
  44. WriteToCrash(CurrentUnit, "crash-");
  45. }
  46. void Fuzzer::StaticAlarmCallback() {
  47. assert(F);
  48. F->AlarmCallback();
  49. }
  50. void Fuzzer::AlarmCallback() {
  51. assert(Options.UnitTimeoutSec > 0);
  52. size_t Seconds =
  53. duration_cast<seconds>(system_clock::now() - UnitStartTime).count();
  54. if (Seconds == 0) return;
  55. if (Options.Verbosity >= 2)
  56. Printf("AlarmCallback %zd\n", Seconds);
  57. if (Seconds >= (size_t)Options.UnitTimeoutSec) {
  58. Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds);
  59. Printf(" and the timeout value is %d (use -timeout=N to change)\n",
  60. Options.UnitTimeoutSec);
  61. Print(CurrentUnit, "\n");
  62. PrintUnitInASCIIOrTokens(CurrentUnit, "\n");
  63. WriteToCrash(CurrentUnit, "timeout-");
  64. exit(1);
  65. }
  66. }
  67. void Fuzzer::PrintStats(const char *Where, size_t Cov, const char *End) {
  68. if (!Options.Verbosity) return;
  69. size_t Seconds = secondsSinceProcessStartUp();
  70. size_t ExecPerSec = (Seconds ? TotalNumberOfRuns / Seconds : 0);
  71. Printf("#%zd\t%s cov %zd bits %zd units %zd exec/s %zd %s", TotalNumberOfRuns,
  72. Where, Cov, TotalBits(), Corpus.size(), ExecPerSec, End);
  73. }
  74. void Fuzzer::RereadOutputCorpus() {
  75. if (Options.OutputCorpus.empty()) return;
  76. std::vector<Unit> AdditionalCorpus;
  77. ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus,
  78. &EpochOfLastReadOfOutputCorpus);
  79. if (Corpus.empty()) {
  80. Corpus = AdditionalCorpus;
  81. return;
  82. }
  83. if (!Options.Reload) return;
  84. if (Options.Verbosity >= 2)
  85. Printf("Reload: read %zd new units.\n", AdditionalCorpus.size());
  86. for (auto &X : AdditionalCorpus) {
  87. if (X.size() > (size_t)Options.MaxLen)
  88. X.resize(Options.MaxLen);
  89. if (UnitHashesAddedToCorpus.insert(Hash(X)).second) {
  90. CurrentUnit.clear();
  91. CurrentUnit.insert(CurrentUnit.begin(), X.begin(), X.end());
  92. size_t NewCoverage = RunOne(CurrentUnit);
  93. if (NewCoverage) {
  94. Corpus.push_back(X);
  95. if (Options.Verbosity >= 1)
  96. PrintStats("RELOAD", NewCoverage);
  97. }
  98. }
  99. }
  100. }
  101. void Fuzzer::ShuffleAndMinimize() {
  102. size_t MaxCov = 0;
  103. bool PreferSmall =
  104. (Options.PreferSmallDuringInitialShuffle == 1 ||
  105. (Options.PreferSmallDuringInitialShuffle == -1 && rand() % 2));
  106. if (Options.Verbosity)
  107. Printf("PreferSmall: %d\n", PreferSmall);
  108. PrintStats("READ ", 0);
  109. std::vector<Unit> NewCorpus;
  110. std::random_shuffle(Corpus.begin(), Corpus.end());
  111. if (PreferSmall)
  112. std::stable_sort(
  113. Corpus.begin(), Corpus.end(),
  114. [](const Unit &A, const Unit &B) { return A.size() < B.size(); });
  115. Unit &U = CurrentUnit;
  116. for (const auto &C : Corpus) {
  117. for (size_t First = 0; First < 1; First++) {
  118. U.clear();
  119. size_t Last = std::min(First + Options.MaxLen, C.size());
  120. U.insert(U.begin(), C.begin() + First, C.begin() + Last);
  121. size_t NewCoverage = RunOne(U);
  122. if (NewCoverage) {
  123. MaxCov = NewCoverage;
  124. NewCorpus.push_back(U);
  125. if (Options.Verbosity >= 2)
  126. Printf("NEW0: %zd L %zd\n", NewCoverage, U.size());
  127. }
  128. }
  129. }
  130. Corpus = NewCorpus;
  131. for (auto &X : Corpus)
  132. UnitHashesAddedToCorpus.insert(Hash(X));
  133. PrintStats("INITED", MaxCov);
  134. }
  135. size_t Fuzzer::RunOne(const Unit &U) {
  136. UnitStartTime = system_clock::now();
  137. TotalNumberOfRuns++;
  138. size_t Res = 0;
  139. if (Options.UseFullCoverageSet)
  140. Res = RunOneMaximizeFullCoverageSet(U);
  141. else
  142. Res = RunOneMaximizeTotalCoverage(U);
  143. auto UnitStopTime = system_clock::now();
  144. auto TimeOfUnit =
  145. duration_cast<seconds>(UnitStopTime - UnitStartTime).count();
  146. if (TimeOfUnit > TimeOfLongestUnitInSeconds) {
  147. TimeOfLongestUnitInSeconds = TimeOfUnit;
  148. Printf("Longest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
  149. Print(U, "\n");
  150. }
  151. return Res;
  152. }
  153. void Fuzzer::RunOneAndUpdateCorpus(const Unit &U) {
  154. if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
  155. return;
  156. ReportNewCoverage(RunOne(U), U);
  157. }
  158. static uintptr_t HashOfArrayOfPCs(uintptr_t *PCs, uintptr_t NumPCs) {
  159. uintptr_t Res = 0;
  160. for (uintptr_t i = 0; i < NumPCs; i++) {
  161. Res = (Res + PCs[i]) * 7;
  162. }
  163. return Res;
  164. }
  165. Unit Fuzzer::SubstituteTokens(const Unit &U) const {
  166. Unit Res;
  167. for (auto Idx : U) {
  168. if (Idx < Options.Tokens.size()) {
  169. std::string Token = Options.Tokens[Idx];
  170. Res.insert(Res.end(), Token.begin(), Token.end());
  171. } else {
  172. Res.push_back(' ');
  173. }
  174. }
  175. // FIXME: Apply DFSan labels.
  176. return Res;
  177. }
  178. void Fuzzer::ExecuteCallback(const Unit &U) {
  179. if (Options.Tokens.empty()) {
  180. USF.TargetFunction(U.data(), U.size());
  181. } else {
  182. auto T = SubstituteTokens(U);
  183. USF.TargetFunction(T.data(), T.size());
  184. }
  185. }
  186. // Experimental.
  187. // Fuly reset the current coverage state, run a single unit,
  188. // compute a hash function from the full coverage set,
  189. // return non-zero if the hash value is new.
  190. // This produces tons of new units and as is it's only suitable for small tests,
  191. // e.g. test/FullCoverageSetTest.cpp. FIXME: make it scale.
  192. size_t Fuzzer::RunOneMaximizeFullCoverageSet(const Unit &U) {
  193. __sanitizer_reset_coverage();
  194. ExecuteCallback(U);
  195. uintptr_t *PCs;
  196. uintptr_t NumPCs =__sanitizer_get_coverage_guards(&PCs);
  197. if (FullCoverageSets.insert(HashOfArrayOfPCs(PCs, NumPCs)).second)
  198. return FullCoverageSets.size();
  199. return 0;
  200. }
  201. size_t Fuzzer::RunOneMaximizeTotalCoverage(const Unit &U) {
  202. size_t NumCounters = __sanitizer_get_number_of_counters();
  203. if (Options.UseCounters) {
  204. CounterBitmap.resize(NumCounters);
  205. __sanitizer_update_counter_bitset_and_clear_counters(0);
  206. }
  207. size_t OldCoverage = __sanitizer_get_total_unique_coverage();
  208. ExecuteCallback(U);
  209. size_t NewCoverage = __sanitizer_get_total_unique_coverage();
  210. size_t NumNewBits = 0;
  211. if (Options.UseCounters)
  212. NumNewBits = __sanitizer_update_counter_bitset_and_clear_counters(
  213. CounterBitmap.data());
  214. if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && Options.Verbosity)
  215. PrintStats("pulse ", NewCoverage);
  216. if (NewCoverage > OldCoverage || NumNewBits)
  217. return NewCoverage;
  218. return 0;
  219. }
  220. void Fuzzer::WriteToOutputCorpus(const Unit &U) {
  221. if (Options.OutputCorpus.empty()) return;
  222. std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
  223. WriteToFile(U, Path);
  224. if (Options.Verbosity >= 2)
  225. Printf("Written to %s\n", Path.c_str());
  226. }
  227. void Fuzzer::WriteToCrash(const Unit &U, const char *Prefix) {
  228. std::string Path = Prefix + Hash(U);
  229. WriteToFile(U, Path);
  230. Printf("CRASHED; file written to %s\nBase64: ", Path.c_str());
  231. PrintFileAsBase64(Path);
  232. }
  233. void Fuzzer::SaveCorpus() {
  234. if (Options.OutputCorpus.empty()) return;
  235. for (const auto &U : Corpus)
  236. WriteToFile(U, DirPlusFile(Options.OutputCorpus, Hash(U)));
  237. if (Options.Verbosity)
  238. Printf("Written corpus of %zd files to %s\n", Corpus.size(),
  239. Options.OutputCorpus.c_str());
  240. }
  241. void Fuzzer::ReportNewCoverage(size_t NewCoverage, const Unit &U) {
  242. if (!NewCoverage) return;
  243. Corpus.push_back(U);
  244. UnitHashesAddedToCorpus.insert(Hash(U));
  245. PrintStats("NEW ", NewCoverage, "");
  246. if (Options.Verbosity) {
  247. Printf(" L: %zd", U.size());
  248. if (U.size() < 30) {
  249. Printf(" ");
  250. PrintUnitInASCIIOrTokens(U, "\t");
  251. Print(U);
  252. }
  253. Printf("\n");
  254. }
  255. WriteToOutputCorpus(U);
  256. if (Options.ExitOnFirst)
  257. exit(0);
  258. }
  259. void Fuzzer::MutateAndTestOne(Unit *U) {
  260. for (int i = 0; i < Options.MutateDepth; i++) {
  261. StartTraceRecording();
  262. size_t Size = U->size();
  263. U->resize(Options.MaxLen);
  264. size_t NewSize = USF.Mutate(U->data(), Size, U->size());
  265. assert(NewSize > 0 && "Mutator returned empty unit");
  266. assert(NewSize <= (size_t)Options.MaxLen &&
  267. "Mutator return overisized unit");
  268. U->resize(NewSize);
  269. RunOneAndUpdateCorpus(*U);
  270. size_t NumTraceBasedMutations = StopTraceRecording();
  271. for (size_t j = 0; j < NumTraceBasedMutations; j++) {
  272. ApplyTraceBasedMutation(j, U);
  273. RunOneAndUpdateCorpus(*U);
  274. }
  275. }
  276. }
  277. void Fuzzer::Loop(size_t NumIterations) {
  278. for (size_t i = 1; i <= NumIterations; i++) {
  279. for (size_t J1 = 0; J1 < Corpus.size(); J1++) {
  280. SyncCorpus();
  281. RereadOutputCorpus();
  282. if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
  283. return;
  284. // First, simply mutate the unit w/o doing crosses.
  285. CurrentUnit = Corpus[J1];
  286. MutateAndTestOne(&CurrentUnit);
  287. // Now, cross with others.
  288. if (Options.DoCrossOver && !Corpus[J1].empty()) {
  289. for (size_t J2 = 0; J2 < Corpus.size(); J2++) {
  290. CurrentUnit.resize(Options.MaxLen);
  291. size_t NewSize = USF.CrossOver(
  292. Corpus[J1].data(), Corpus[J1].size(), Corpus[J2].data(),
  293. Corpus[J2].size(), CurrentUnit.data(), CurrentUnit.size());
  294. assert(NewSize > 0 && "CrossOver returned empty unit");
  295. assert(NewSize <= (size_t)Options.MaxLen &&
  296. "CrossOver return overisized unit");
  297. CurrentUnit.resize(NewSize);
  298. MutateAndTestOne(&CurrentUnit);
  299. }
  300. }
  301. }
  302. }
  303. }
  304. void Fuzzer::SyncCorpus() {
  305. if (Options.SyncCommand.empty() || Options.OutputCorpus.empty()) return;
  306. auto Now = system_clock::now();
  307. if (duration_cast<seconds>(Now - LastExternalSync).count() <
  308. Options.SyncTimeout)
  309. return;
  310. LastExternalSync = Now;
  311. ExecuteCommand(Options.SyncCommand + " " + Options.OutputCorpus);
  312. }
  313. } // namespace fuzzer