Home | History | Annotate | Download | only in Fuzzer
      1 //===- FuzzerInterface.h - Interface 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 interface between the Fuzzer and the library being tested.
     10 //===----------------------------------------------------------------------===//
     11 
     12 // WARNING: keep the interface free of STL or any other header-based C++ lib,
     13 // to avoid bad interactions between the code used in the fuzzer and
     14 // the code used in the target function.
     15 
     16 #ifndef LLVM_FUZZER_INTERFACE_H
     17 #define LLVM_FUZZER_INTERFACE_H
     18 
     19 #include <cstddef>
     20 #include <cstdint>
     21 #include <vector>
     22 #include <string>
     23 
     24 namespace fuzzer {
     25 typedef std::vector<uint8_t> Unit;
     26 
     27 /// Returns an int 0. Values other than zero are reserved for future.
     28 typedef int (*UserCallback)(const uint8_t *Data, size_t Size);
     29 /** Simple C-like interface with a single user-supplied callback.
     30 
     31 Usage:
     32 
     33 #\code
     34 #include "FuzzerInterface.h"
     35 
     36 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
     37   DoStuffWithData(Data, Size);
     38   return 0;
     39 }
     40 
     41 // Implement your own main() or use the one from FuzzerMain.cpp.
     42 int main(int argc, char **argv) {
     43   InitializeMeIfNeeded();
     44   return fuzzer::FuzzerDriver(argc, argv, LLVMFuzzerTestOneInput);
     45 }
     46 #\endcode
     47 */
     48 int FuzzerDriver(int argc, char **argv, UserCallback Callback);
     49 
     50 class FuzzerRandomBase {
     51  public:
     52   FuzzerRandomBase(){}
     53   virtual ~FuzzerRandomBase(){};
     54   virtual void ResetSeed(unsigned int seed) = 0;
     55   // Return a random number.
     56   virtual size_t Rand() = 0;
     57   // Return a random number in range [0,n).
     58   size_t operator()(size_t n) { return n ? Rand() % n : 0; }
     59   bool RandBool() { return Rand() % 2; }
     60 };
     61 
     62 class FuzzerRandomLibc : public FuzzerRandomBase {
     63  public:
     64   FuzzerRandomLibc(unsigned int seed) { ResetSeed(seed); }
     65   void ResetSeed(unsigned int seed) override;
     66   ~FuzzerRandomLibc() override {}
     67   size_t Rand() override;
     68 };
     69 
     70 class MutationDispatcher {
     71  public:
     72   MutationDispatcher(FuzzerRandomBase &Rand);
     73   ~MutationDispatcher();
     74   /// Indicate that we are about to start a new sequence of mutations.
     75   void StartMutationSequence();
     76   /// Print the current sequence of mutations.
     77   void PrintMutationSequence();
     78   /// Mutates data by shuffling bytes.
     79   size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
     80   /// Mutates data by erasing a byte.
     81   size_t Mutate_EraseByte(uint8_t *Data, size_t Size, size_t MaxSize);
     82   /// Mutates data by inserting a byte.
     83   size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize);
     84   /// Mutates data by chanding one byte.
     85   size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize);
     86   /// Mutates data by chanding one bit.
     87   size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize);
     88 
     89   /// Mutates data by adding a word from the dictionary.
     90   size_t Mutate_AddWordFromDictionary(uint8_t *Data, size_t Size,
     91                                       size_t MaxSize);
     92 
     93   /// Tries to find an ASCII integer in Data, changes it to another ASCII int.
     94   size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize);
     95 
     96   /// CrossOver Data with some other element of the corpus.
     97   size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
     98 
     99   /// Applies one of the above mutations.
    100   /// Returns the new size of data which could be up to MaxSize.
    101   size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
    102 
    103   /// Creates a cross-over of two pieces of Data, returns its size.
    104   size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2,
    105                    size_t Size2, uint8_t *Out, size_t MaxOutSize);
    106 
    107   void AddWordToDictionary(const uint8_t *Word, size_t Size);
    108   void SetCorpus(const std::vector<Unit> *Corpus);
    109 
    110  private:
    111   FuzzerRandomBase &Rand;
    112   struct Impl;
    113   Impl *MDImpl;
    114 };
    115 
    116 // For backward compatibility only, deprecated.
    117 static inline size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize,
    118                             FuzzerRandomBase &Rand) {
    119   MutationDispatcher MD(Rand);
    120   return MD.Mutate(Data, Size, MaxSize);
    121 }
    122 
    123 /** An abstract class that allows to use user-supplied mutators with libFuzzer.
    124 
    125 Usage:
    126 
    127 #\code
    128 #include "FuzzerInterface.h"
    129 class MyFuzzer : public fuzzer::UserSuppliedFuzzer {
    130  public:
    131   MyFuzzer(fuzzer::FuzzerRandomBase *Rand);
    132   // Must define the target function.
    133   int TargetFunction(...) { ...; return 0; }
    134   // Optionally define the mutator.
    135   size_t Mutate(...) { ... }
    136   // Optionally define the CrossOver method.
    137   size_t CrossOver(...) { ... }
    138 };
    139 
    140 int main(int argc, char **argv) {
    141   MyFuzzer F;
    142   fuzzer::FuzzerDriver(argc, argv, F);
    143 }
    144 #\endcode
    145 */
    146 class UserSuppliedFuzzer {
    147  public:
    148   UserSuppliedFuzzer(FuzzerRandomBase *Rand);
    149   /// Executes the target function on 'Size' bytes of 'Data'.
    150   virtual int TargetFunction(const uint8_t *Data, size_t Size) = 0;
    151   virtual void StartMutationSequence() { MD.StartMutationSequence(); }
    152   virtual void PrintMutationSequence() { MD.PrintMutationSequence(); }
    153   virtual void SetCorpus(const std::vector<Unit> *Corpus) {
    154     MD.SetCorpus(Corpus);
    155   }
    156   /// Mutates 'Size' bytes of data in 'Data' inplace into up to 'MaxSize' bytes,
    157   /// returns the new size of the data, which should be positive.
    158   virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
    159     return MD.Mutate(Data, Size, MaxSize);
    160   }
    161   /// Crosses 'Data1' and 'Data2', writes up to 'MaxOutSize' bytes into Out,
    162   /// returns the number of bytes written, which should be positive.
    163   virtual size_t CrossOver(const uint8_t *Data1, size_t Size1,
    164                            const uint8_t *Data2, size_t Size2,
    165                            uint8_t *Out, size_t MaxOutSize) {
    166     return MD.CrossOver(Data1, Size1, Data2, Size2, Out, MaxOutSize);
    167   }
    168   virtual ~UserSuppliedFuzzer();
    169 
    170   FuzzerRandomBase &GetRand() { return *Rand; }
    171 
    172   MutationDispatcher &GetMD() { return MD; }
    173 
    174  private:
    175   bool OwnRand = false;
    176   FuzzerRandomBase *Rand;
    177   MutationDispatcher MD;
    178 };
    179 
    180 /// Runs the fuzzing with the UserSuppliedFuzzer.
    181 int FuzzerDriver(int argc, char **argv, UserSuppliedFuzzer &USF);
    182 
    183 /// More C++-ish interface.
    184 int FuzzerDriver(const std::vector<std::string> &Args, UserSuppliedFuzzer &USF);
    185 int FuzzerDriver(const std::vector<std::string> &Args, UserCallback Callback);
    186 
    187 }  // namespace fuzzer
    188 
    189 #endif  // LLVM_FUZZER_INTERFACE_H
    190