1326943Sdim//===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===//
2326943Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6326943Sdim//
7326943Sdim//===----------------------------------------------------------------------===//
8326943Sdim// Define the main class fuzzer::Fuzzer and most functions.
9326943Sdim//===----------------------------------------------------------------------===//
10326943Sdim
11326943Sdim#ifndef LLVM_FUZZER_INTERNAL_H
12326943Sdim#define LLVM_FUZZER_INTERNAL_H
13326943Sdim
14336817Sdim#include "FuzzerDataFlowTrace.h"
15326943Sdim#include "FuzzerDefs.h"
16326943Sdim#include "FuzzerExtFunctions.h"
17326943Sdim#include "FuzzerInterface.h"
18326943Sdim#include "FuzzerOptions.h"
19326943Sdim#include "FuzzerSHA1.h"
20326943Sdim#include "FuzzerValueBitMap.h"
21326943Sdim#include <algorithm>
22326943Sdim#include <atomic>
23326943Sdim#include <chrono>
24326943Sdim#include <climits>
25326943Sdim#include <cstdlib>
26326943Sdim#include <string.h>
27326943Sdim
28326943Sdimnamespace fuzzer {
29326943Sdim
30326943Sdimusing namespace std::chrono;
31326943Sdim
32326943Sdimclass Fuzzer {
33326943Sdimpublic:
34326943Sdim
35326943Sdim  Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
36326943Sdim         FuzzingOptions Options);
37326943Sdim  ~Fuzzer();
38353358Sdim  void Loop(Vector<SizedFile> &CorporaFiles);
39353358Sdim  void ReadAndExecuteSeedCorpora(Vector<SizedFile> &CorporaFiles);
40326943Sdim  void MinimizeCrashLoop(const Unit &U);
41326943Sdim  void RereadOutputCorpus(size_t MaxSize);
42326943Sdim
43326943Sdim  size_t secondsSinceProcessStartUp() {
44326943Sdim    return duration_cast<seconds>(system_clock::now() - ProcessStartTime)
45326943Sdim        .count();
46326943Sdim  }
47326943Sdim
48326943Sdim  bool TimedOut() {
49326943Sdim    return Options.MaxTotalTimeSec > 0 &&
50326943Sdim           secondsSinceProcessStartUp() >
51326943Sdim               static_cast<size_t>(Options.MaxTotalTimeSec);
52326943Sdim  }
53326943Sdim
54326943Sdim  size_t execPerSec() {
55326943Sdim    size_t Seconds = secondsSinceProcessStartUp();
56326943Sdim    return Seconds ? TotalNumberOfRuns / Seconds : 0;
57326943Sdim  }
58326943Sdim
59326943Sdim  size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; }
60326943Sdim
61326943Sdim  static void StaticAlarmCallback();
62326943Sdim  static void StaticCrashSignalCallback();
63326943Sdim  static void StaticExitCallback();
64326943Sdim  static void StaticInterruptCallback();
65326943Sdim  static void StaticFileSizeExceedCallback();
66326943Sdim  static void StaticGracefulExitCallback();
67326943Sdim
68326943Sdim  void ExecuteCallback(const uint8_t *Data, size_t Size);
69326943Sdim  bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,
70326943Sdim              InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr);
71326943Sdim
72326943Sdim  // Merge Corpora[1:] into Corpora[0].
73326943Sdim  void Merge(const Vector<std::string> &Corpora);
74326943Sdim  void CrashResistantMergeInternalStep(const std::string &ControlFilePath);
75326943Sdim  MutationDispatcher &GetMD() { return MD; }
76326943Sdim  void PrintFinalStats();
77326943Sdim  void SetMaxInputLen(size_t MaxInputLen);
78326943Sdim  void SetMaxMutationLen(size_t MaxMutationLen);
79326943Sdim  void RssLimitCallback();
80326943Sdim
81326943Sdim  bool InFuzzingThread() const { return IsMyThread; }
82326943Sdim  size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const;
83326943Sdim  void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
84326943Sdim                               bool DuringInitialCorpusExecution);
85326943Sdim
86326943Sdim  void HandleMalloc(size_t Size);
87353358Sdim  static void MaybeExitGracefully();
88353358Sdim  std::string WriteToOutputCorpus(const Unit &U);
89326943Sdim
90326943Sdimprivate:
91326943Sdim  void AlarmCallback();
92326943Sdim  void CrashCallback();
93326943Sdim  void ExitCallback();
94326943Sdim  void CrashOnOverwrittenData();
95326943Sdim  void InterruptCallback();
96326943Sdim  void MutateAndTestOne();
97326943Sdim  void PurgeAllocator();
98326943Sdim  void ReportNewCoverage(InputInfo *II, const Unit &U);
99326943Sdim  void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size);
100326943Sdim  void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
101360784Sdim  void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0,
102360784Sdim                  size_t Features = 0);
103326943Sdim  void PrintStatusForNewUnit(const Unit &U, const char *Text);
104326943Sdim  void CheckExitOnSrcPosOrItem();
105326943Sdim
106326943Sdim  static void StaticDeathCallback();
107326943Sdim  void DumpCurrentUnit(const char *Prefix);
108326943Sdim  void DeathCallback();
109326943Sdim
110326943Sdim  void AllocateCurrentUnitData();
111326943Sdim  uint8_t *CurrentUnitData = nullptr;
112326943Sdim  std::atomic<size_t> CurrentUnitSize;
113326943Sdim  uint8_t BaseSha1[kSHA1NumBytes];  // Checksum of the base unit.
114326943Sdim
115326943Sdim  bool GracefulExitRequested = false;
116326943Sdim
117326943Sdim  size_t TotalNumberOfRuns = 0;
118326943Sdim  size_t NumberOfNewUnitsAdded = 0;
119326943Sdim
120326943Sdim  size_t LastCorpusUpdateRun = 0;
121326943Sdim
122326943Sdim  bool HasMoreMallocsThanFrees = false;
123326943Sdim  size_t NumberOfLeakDetectionAttempts = 0;
124326943Sdim
125326943Sdim  system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now();
126326943Sdim
127326943Sdim  UserCallback CB;
128326943Sdim  InputCorpus &Corpus;
129326943Sdim  MutationDispatcher &MD;
130326943Sdim  FuzzingOptions Options;
131336817Sdim  DataFlowTrace DFT;
132326943Sdim
133326943Sdim  system_clock::time_point ProcessStartTime = system_clock::now();
134326943Sdim  system_clock::time_point UnitStartTime, UnitStopTime;
135326943Sdim  long TimeOfLongestUnitInSeconds = 0;
136326943Sdim  long EpochOfLastReadOfOutputCorpus = 0;
137326943Sdim
138326943Sdim  size_t MaxInputLen = 0;
139326943Sdim  size_t MaxMutationLen = 0;
140326943Sdim  size_t TmpMaxMutationLen = 0;
141326943Sdim
142326943Sdim  Vector<uint32_t> UniqFeatureSetTmp;
143326943Sdim
144326943Sdim  // Need to know our own thread.
145326943Sdim  static thread_local bool IsMyThread;
146326943Sdim};
147326943Sdim
148336817Sdimstruct ScopedEnableMsanInterceptorChecks {
149336817Sdim  ScopedEnableMsanInterceptorChecks() {
150336817Sdim    if (EF->__msan_scoped_enable_interceptor_checks)
151336817Sdim      EF->__msan_scoped_enable_interceptor_checks();
152336817Sdim  }
153336817Sdim  ~ScopedEnableMsanInterceptorChecks() {
154336817Sdim    if (EF->__msan_scoped_disable_interceptor_checks)
155336817Sdim      EF->__msan_scoped_disable_interceptor_checks();
156336817Sdim  }
157336817Sdim};
158336817Sdim
159336817Sdimstruct ScopedDisableMsanInterceptorChecks {
160336817Sdim  ScopedDisableMsanInterceptorChecks() {
161336817Sdim    if (EF->__msan_scoped_disable_interceptor_checks)
162336817Sdim      EF->__msan_scoped_disable_interceptor_checks();
163336817Sdim  }
164336817Sdim  ~ScopedDisableMsanInterceptorChecks() {
165336817Sdim    if (EF->__msan_scoped_enable_interceptor_checks)
166336817Sdim      EF->__msan_scoped_enable_interceptor_checks();
167336817Sdim  }
168336817Sdim};
169336817Sdim
170326943Sdim} // namespace fuzzer
171326943Sdim
172326943Sdim#endif // LLVM_FUZZER_INTERNAL_H
173