blob: c26615631ecd013856d574f7516e6f66c17d9012 [file] [log] [blame]
Aaron Ballmanef116982015-01-29 16:58:29 +00001//===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===//
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// Define the main class fuzzer::Fuzzer and most functions.
10//===----------------------------------------------------------------------===//
Yaron Keren347663b2015-08-10 16:37:40 +000011
12#ifndef LLVM_FUZZER_INTERNAL_H
13#define LLVM_FUZZER_INTERNAL_H
14
Kostya Serebryany6f5a8042016-09-21 01:50:50 +000015#include "FuzzerDefs.h"
Kostya Serebryanybceadcf2016-08-24 01:38:42 +000016#include "FuzzerExtFunctions.h"
17#include "FuzzerInterface.h"
Kostya Serebryany556894f2016-09-21 02:05:39 +000018#include "FuzzerOptions.h"
Zachary Turner24a148b2016-11-30 19:06:14 +000019#include "FuzzerSHA1.h"
Kostya Serebryanybceadcf2016-08-24 01:38:42 +000020#include "FuzzerValueBitMap.h"
Marcos Pividori178fe582016-12-13 17:46:11 +000021#include <algorithm>
22#include <atomic>
23#include <chrono>
24#include <climits>
25#include <cstdlib>
26#include <string.h>
Kostya Serebryanybceadcf2016-08-24 01:38:42 +000027
Aaron Ballmanef116982015-01-29 16:58:29 +000028namespace fuzzer {
Kostya Serebryany8b0d90a2016-05-13 18:04:35 +000029
Aaron Ballmanef116982015-01-29 16:58:29 +000030using namespace std::chrono;
Kostya Serebryany9690fcf2015-05-12 18:51:57 +000031
Aaron Ballmanef116982015-01-29 16:58:29 +000032class Fuzzer {
Ivan Krasindf919102016-01-22 22:28:27 +000033public:
Mike Aizatsky1aa501e2016-05-10 23:43:15 +000034
Kostya Serebryany29bb6642016-09-21 22:42:17 +000035 Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
36 FuzzingOptions Options);
Mike Aizatskyb4bbc3b2016-08-05 20:09:53 +000037 ~Fuzzer();
Kostya Serebryany468ed782015-09-08 17:30:35 +000038 void Loop();
Kostya Serebryanyf9b8e8b2016-10-15 01:00:24 +000039 void MinimizeCrashLoop(const Unit &U);
Kostya Serebryany09aa01a2016-09-21 01:04:43 +000040 void ShuffleAndMinimize(UnitVector *V);
Kostya Serebryany22526252015-05-11 21:16:27 +000041 void InitializeTraceState();
Kostya Serebryany64d24572016-03-12 01:57:04 +000042 void RereadOutputCorpus(size_t MaxSize);
Aaron Ballmanef116982015-01-29 16:58:29 +000043
Kostya Serebryany92e04762015-02-04 23:42:42 +000044 size_t secondsSinceProcessStartUp() {
45 return duration_cast<seconds>(system_clock::now() - ProcessStartTime)
46 .count();
47 }
Kostya Serebryanyf9b8e8b2016-10-15 01:00:24 +000048
49 bool TimedOut() {
50 return Options.MaxTotalTimeSec > 0 &&
51 secondsSinceProcessStartUp() >
52 static_cast<size_t>(Options.MaxTotalTimeSec);
53 }
54
Kostya Serebryany66ff0752016-02-26 22:42:23 +000055 size_t execPerSec() {
56 size_t Seconds = secondsSinceProcessStartUp();
57 return Seconds ? TotalNumberOfRuns / Seconds : 0;
58 }
Kostya Serebryany92e04762015-02-04 23:42:42 +000059
60 size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; }
61
Kostya Serebryany52a788e2015-03-31 20:13:20 +000062 static void StaticAlarmCallback();
Kostya Serebryany228d5b12016-03-01 22:19:21 +000063 static void StaticCrashSignalCallback();
64 static void StaticInterruptCallback();
Kostya Serebryany4aa05902017-01-05 22:05:47 +000065 static void StaticFileSizeExceedCallback();
Kostya Serebryany52a788e2015-03-31 20:13:20 +000066
Kostya Serebryany8a5bef02016-02-13 17:56:51 +000067 void ExecuteCallback(const uint8_t *Data, size_t Size);
Kostya Serebryany1c73f1b2016-10-05 22:56:21 +000068 size_t RunOne(const uint8_t *Data, size_t Size);
Aaron Ballmanef116982015-01-29 16:58:29 +000069
Kostya Serebryany9cc3b0d2015-10-24 01:16:40 +000070 // Merge Corpora[1:] into Corpora[0].
71 void Merge(const std::vector<std::string> &Corpora);
Kostya Serebryany111e1d62016-12-09 01:17:24 +000072 void CrashResistantMerge(const std::vector<std::string> &Args,
Kostya Serebryany4fc6dd72017-03-22 20:32:44 +000073 const std::vector<std::string> &Corpora,
74 const char *CoverageSummaryInputPathOrNull,
75 const char *CoverageSummaryOutputPathOrNull);
Kostya Serebryany111e1d62016-12-09 01:17:24 +000076 void CrashResistantMergeInternalStep(const std::string &ControlFilePath);
Kostya Serebryany1deb0492016-02-13 06:24:18 +000077 MutationDispatcher &GetMD() { return MD; }
Kostya Serebryany66ff0752016-02-26 22:42:23 +000078 void PrintFinalStats();
Kostya Serebryanybe0ed592016-09-22 23:16:36 +000079 void SetMaxInputLen(size_t MaxInputLen);
80 void SetMaxMutationLen(size_t MaxMutationLen);
Kostya Serebryany8b8f7a32016-05-06 23:38:07 +000081 void RssLimitCallback();
Kostya Serebryany9cc3b0d2015-10-24 01:16:40 +000082
Kostya Serebryanyf26017b2016-05-26 21:32:30 +000083 bool InFuzzingThread() const { return IsMyThread; }
Kostya Serebryanyd8384122016-05-26 22:17:32 +000084 size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const;
Kostya Serebryanybb59ef72016-10-18 18:38:08 +000085 void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
86 bool DuringInitialCorpusExecution);
Kostya Serebryanyf26017b2016-05-26 21:32:30 +000087
Kostya Serebryany05f77912016-11-30 22:39:35 +000088 void HandleMalloc(size_t Size);
Kostya Serebryany98d592c2017-01-20 20:57:07 +000089 void AnnounceOutput(const uint8_t *Data, size_t Size);
Kostya Serebryany05f77912016-11-30 22:39:35 +000090
Ivan Krasindf919102016-01-22 22:28:27 +000091private:
Kostya Serebryany52a788e2015-03-31 20:13:20 +000092 void AlarmCallback();
Kostya Serebryany228d5b12016-03-01 22:19:21 +000093 void CrashCallback();
94 void InterruptCallback();
Kostya Serebryany27ab2d72015-12-19 02:49:09 +000095 void MutateAndTestOne();
Kostya Serebryany29bb6642016-09-21 22:42:17 +000096 void ReportNewCoverage(InputInfo *II, const Unit &U);
Kostya Serebryany1c73f1b2016-10-05 22:56:21 +000097 size_t RunOne(const Unit &U) { return RunOne(U.data(), U.size()); }
Aaron Ballmanef116982015-01-29 16:58:29 +000098 void WriteToOutputCorpus(const Unit &U);
Kostya Serebryany2b7d2e92015-07-23 18:37:22 +000099 void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
Kostya Serebryany16a145f2016-09-23 01:58:51 +0000100 void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0);
Kostya Serebryanydc3135d2015-11-12 01:02:01 +0000101 void PrintStatusForNewUnit(const Unit &U);
Kostya Serebryany945761b2016-03-18 00:23:29 +0000102 void ShuffleCorpus(UnitVector *V);
Kostya Serebryany90f8f362016-09-30 23:29:27 +0000103 void AddToCorpus(const Unit &U);
Kostya Serebryany8dfed452016-10-18 18:06:05 +0000104 void CheckExitOnSrcPosOrItem();
Kostya Serebryany945761b2016-03-18 00:23:29 +0000105
Kostya Serebryanybeb24c32015-05-07 21:02:11 +0000106 // Trace-based fuzzing: we run a unit with some kind of tracing
107 // enabled and record potentially useful mutations. Then
108 // We apply these mutations one by one to the unit and run it again.
109
110 // Start tracing; forget all previously proposed mutations.
111 void StartTraceRecording();
Kostya Serebryanyb65805a2016-01-09 03:08:58 +0000112 // Stop tracing.
113 void StopTraceRecording();
Kostya Serebryanybeb24c32015-05-07 21:02:11 +0000114
Kostya Serebryany52a788e2015-03-31 20:13:20 +0000115 static void StaticDeathCallback();
Kostya Serebryany228d5b12016-03-01 22:19:21 +0000116 void DumpCurrentUnit(const char *Prefix);
Kostya Serebryany52a788e2015-03-31 20:13:20 +0000117 void DeathCallback();
Kostya Serebryany98abb2c2016-01-13 23:46:01 +0000118
Kostya Serebryanybe0ed592016-09-22 23:16:36 +0000119 void AllocateCurrentUnitData();
Kostya Serebryany8fc3a272016-05-27 00:21:33 +0000120 uint8_t *CurrentUnitData = nullptr;
Kostya Serebryany0edb5632016-05-27 00:54:15 +0000121 std::atomic<size_t> CurrentUnitSize;
Kostya Serebryanya9a54802016-08-17 20:45:23 +0000122 uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit.
Marcos Pividori64d41472016-12-13 17:46:25 +0000123 bool RunningCB = false;
Aaron Ballmanef116982015-01-29 16:58:29 +0000124
125 size_t TotalNumberOfRuns = 0;
Kostya Serebryany66ff0752016-02-26 22:42:23 +0000126 size_t NumberOfNewUnitsAdded = 0;
Aaron Ballmanef116982015-01-29 16:58:29 +0000127
Kostya Serebryany1bfd5832016-04-20 00:24:21 +0000128 bool HasMoreMallocsThanFrees = false;
Kostya Serebryany7018a1a2016-04-27 19:52:34 +0000129 size_t NumberOfLeakDetectionAttempts = 0;
Kostya Serebryany1bfd5832016-04-20 00:24:21 +0000130
Kostya Serebryany7ec0c562016-02-13 03:25:16 +0000131 UserCallback CB;
Kostya Serebryany29bb6642016-09-21 22:42:17 +0000132 InputCorpus &Corpus;
Kostya Serebryany7ec0c562016-02-13 03:25:16 +0000133 MutationDispatcher &MD;
Aaron Ballmanef116982015-01-29 16:58:29 +0000134 FuzzingOptions Options;
Kostya Serebryany29bb6642016-09-21 22:42:17 +0000135
Aaron Ballmanef116982015-01-29 16:58:29 +0000136 system_clock::time_point ProcessStartTime = system_clock::now();
Kostya Serebryany624f59f2016-09-22 01:34:58 +0000137 system_clock::time_point UnitStartTime, UnitStopTime;
Kostya Serebryany16901a92015-03-30 23:04:35 +0000138 long TimeOfLongestUnitInSeconds = 0;
Kostya Serebryany1ac80552015-05-08 21:30:55 +0000139 long EpochOfLastReadOfOutputCorpus = 0;
Mike Aizatsky1aa501e2016-05-10 23:43:15 +0000140
Kostya Serebryanybe0ed592016-09-22 23:16:36 +0000141 size_t MaxInputLen = 0;
142 size_t MaxMutationLen = 0;
143
Kostya Serebryanyf26017b2016-05-26 21:32:30 +0000144 // Need to know our own thread.
145 static thread_local bool IsMyThread;
Aaron Ballmanef116982015-01-29 16:58:29 +0000146};
147
Ivan Krasindf919102016-01-22 22:28:27 +0000148}; // namespace fuzzer
Yaron Keren347663b2015-08-10 16:37:40 +0000149
150#endif // LLVM_FUZZER_INTERNAL_H