reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
//===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Define the main class fuzzer::Fuzzer and most functions.
//===----------------------------------------------------------------------===//

#ifndef LLVM_FUZZER_INTERNAL_H
#define LLVM_FUZZER_INTERNAL_H

#include "FuzzerDataFlowTrace.h"
#include "FuzzerDefs.h"
#include "FuzzerExtFunctions.h"
#include "FuzzerInterface.h"
#include "FuzzerOptions.h"
#include "FuzzerSHA1.h"
#include "FuzzerValueBitMap.h"
#include <algorithm>
#include <atomic>
#include <chrono>
#include <climits>
#include <cstdlib>
#include <string.h>

namespace fuzzer {

using namespace std::chrono;

class Fuzzer {
public:

  Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
         FuzzingOptions Options);
  ~Fuzzer();
  void Loop(Vector<SizedFile> &CorporaFiles);
  void ReadAndExecuteSeedCorpora(Vector<SizedFile> &CorporaFiles);
  void MinimizeCrashLoop(const Unit &U);
  void RereadOutputCorpus(size_t MaxSize);

  size_t secondsSinceProcessStartUp() {
    return duration_cast<seconds>(system_clock::now() - ProcessStartTime)
        .count();
  }

  bool TimedOut() {
    return Options.MaxTotalTimeSec > 0 &&
           secondsSinceProcessStartUp() >
               static_cast<size_t>(Options.MaxTotalTimeSec);
  }

  size_t execPerSec() {
    size_t Seconds = secondsSinceProcessStartUp();
    return Seconds ? TotalNumberOfRuns / Seconds : 0;
  }

  size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; }

  static void StaticAlarmCallback();
  static void StaticCrashSignalCallback();
  static void StaticExitCallback();
  static void StaticInterruptCallback();
  static void StaticFileSizeExceedCallback();
  static void StaticGracefulExitCallback();

  void ExecuteCallback(const uint8_t *Data, size_t Size);
  bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false,
              InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr);

  // Merge Corpora[1:] into Corpora[0].
  void Merge(const Vector<std::string> &Corpora);
  void CrashResistantMergeInternalStep(const std::string &ControlFilePath);
  MutationDispatcher &GetMD() { return MD; }
  void PrintFinalStats();
  void SetMaxInputLen(size_t MaxInputLen);
  void SetMaxMutationLen(size_t MaxMutationLen);
  void RssLimitCallback();

  bool InFuzzingThread() const { return IsMyThread; }
  size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const;
  void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size,
                               bool DuringInitialCorpusExecution);

  void HandleMalloc(size_t Size);
  static void MaybeExitGracefully();
  std::string WriteToOutputCorpus(const Unit &U);

private:
  void AlarmCallback();
  void CrashCallback();
  void ExitCallback();
  void CrashOnOverwrittenData();
  void InterruptCallback();
  void MutateAndTestOne();
  void PurgeAllocator();
  void ReportNewCoverage(InputInfo *II, const Unit &U);
  void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size);
  void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
  void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0,
                  size_t Features = 0);
  void PrintStatusForNewUnit(const Unit &U, const char *Text);
  void CheckExitOnSrcPosOrItem();

  static void StaticDeathCallback();
  void DumpCurrentUnit(const char *Prefix);
  void DeathCallback();

  void AllocateCurrentUnitData();
  uint8_t *CurrentUnitData = nullptr;
  std::atomic<size_t> CurrentUnitSize;
  uint8_t BaseSha1[kSHA1NumBytes];  // Checksum of the base unit.

  bool GracefulExitRequested = false;

  size_t TotalNumberOfRuns = 0;
  size_t NumberOfNewUnitsAdded = 0;

  size_t LastCorpusUpdateRun = 0;

  bool HasMoreMallocsThanFrees = false;
  size_t NumberOfLeakDetectionAttempts = 0;

  system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now();

  UserCallback CB;
  InputCorpus &Corpus;
  MutationDispatcher &MD;
  FuzzingOptions Options;
  DataFlowTrace DFT;

  system_clock::time_point ProcessStartTime = system_clock::now();
  system_clock::time_point UnitStartTime, UnitStopTime;
  long TimeOfLongestUnitInSeconds = 0;
  long EpochOfLastReadOfOutputCorpus = 0;

  size_t MaxInputLen = 0;
  size_t MaxMutationLen = 0;
  size_t TmpMaxMutationLen = 0;

  Vector<uint32_t> UniqFeatureSetTmp;

  // Need to know our own thread.
  static thread_local bool IsMyThread;
};

struct ScopedEnableMsanInterceptorChecks {
  ScopedEnableMsanInterceptorChecks() {
    if (EF->__msan_scoped_enable_interceptor_checks)
      EF->__msan_scoped_enable_interceptor_checks();
  }
  ~ScopedEnableMsanInterceptorChecks() {
    if (EF->__msan_scoped_disable_interceptor_checks)
      EF->__msan_scoped_disable_interceptor_checks();
  }
};

struct ScopedDisableMsanInterceptorChecks {
  ScopedDisableMsanInterceptorChecks() {
    if (EF->__msan_scoped_disable_interceptor_checks)
      EF->__msan_scoped_disable_interceptor_checks();
  }
  ~ScopedDisableMsanInterceptorChecks() {
    if (EF->__msan_scoped_enable_interceptor_checks)
      EF->__msan_scoped_enable_interceptor_checks();
  }
};

} // namespace fuzzer

#endif // LLVM_FUZZER_INTERNAL_H