diff options
Diffstat (limited to 'lib/fuzzer/FuzzerMutate.cpp')
| -rw-r--r-- | lib/fuzzer/FuzzerMutate.cpp | 93 | 
1 files changed, 71 insertions, 22 deletions
diff --git a/lib/fuzzer/FuzzerMutate.cpp b/lib/fuzzer/FuzzerMutate.cpp index 9ee5299f1b60..ff076cca683f 100644 --- a/lib/fuzzer/FuzzerMutate.cpp +++ b/lib/fuzzer/FuzzerMutate.cpp @@ -30,39 +30,41 @@ MutationDispatcher::MutationDispatcher(Random &Rand,    DefaultMutators.insert(        DefaultMutators.begin(),        { -          {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"}, -          {&MutationDispatcher::Mutate_InsertByte, "InsertByte"}, +          {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes", 0, 0}, +          {&MutationDispatcher::Mutate_InsertByte, "InsertByte", 0, 0},            {&MutationDispatcher::Mutate_InsertRepeatedBytes, -           "InsertRepeatedBytes"}, -          {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"}, -          {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"}, -          {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"}, -          {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"}, -          {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"}, -          {&MutationDispatcher::Mutate_CopyPart, "CopyPart"}, -          {&MutationDispatcher::Mutate_CrossOver, "CrossOver"}, +           "InsertRepeatedBytes", 0, 0}, +          {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte", 0, 0}, +          {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit", 0, 0}, +          {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes", 0, 0}, +          {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt", 0, +           0}, +          {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt", 0, +           0}, +          {&MutationDispatcher::Mutate_CopyPart, "CopyPart", 0, 0}, +          {&MutationDispatcher::Mutate_CrossOver, "CrossOver", 0, 0},            {&MutationDispatcher::Mutate_AddWordFromManualDictionary, -           "ManualDict"}, +           "ManualDict", 0, 0},            {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary, -           "PersAutoDict"}, +           "PersAutoDict", 0, 0},        });    if(Options.UseCmp)      DefaultMutators.push_back( -        {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"}); +        {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP", 0, 0});    if (EF->LLVMFuzzerCustomMutator) -    Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"}); +    Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom", 0, 0});    else      Mutators = DefaultMutators;    if (EF->LLVMFuzzerCustomCrossOver)      Mutators.push_back( -        {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"}); +        {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver", 0, 0});  }  static char RandCh(Random &Rand) {    if (Rand.RandBool()) return Rand(256); -  const char *Special = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00"; +  const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";    return Special[Rand(sizeof(Special) - 1)];  } @@ -195,7 +197,6 @@ DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(      const void *Arg1Mutation, const void *Arg2Mutation,      size_t ArgSize, const uint8_t *Data,      size_t Size) { -  ScopedDoingMyOwnMemOrStr scoped_doing_my_own_mem_os_str;    bool HandleFirst = Rand.RandBool();    const void *ExistingBytes, *DesiredBytes;    Word W; @@ -339,7 +340,9 @@ size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize,  size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size,                                             size_t MaxSize) {    if (Size > MaxSize || Size == 0) return 0; -  if (Rand.RandBool()) +  // If Size == MaxSize, `InsertPartOf(...)` will +  // fail so there's no point using it in this case. +  if (Size == MaxSize || Rand.RandBool())      return CopyPartOf(Data, Size, Data, Size);    else      return InsertPartOf(Data, Size, Data, Size, MaxSize); @@ -463,6 +466,7 @@ void MutationDispatcher::RecordSuccessfulMutationSequence() {      if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))        PersistentAutoDictionary.push_back({DE->GetW(), 1});    } +  RecordUsefulMutations();  }  void MutationDispatcher::PrintRecommendedDictionary() { @@ -483,8 +487,7 @@ void MutationDispatcher::PrintRecommendedDictionary() {  void MutationDispatcher::PrintMutationSequence() {    Printf("MS: %zd ", CurrentMutatorSequence.size()); -  for (auto M : CurrentMutatorSequence) -    Printf("%s-", M.Name); +  for (auto M : CurrentMutatorSequence) Printf("%s-", M->Name);    if (!CurrentDictionaryEntrySequence.empty()) {      Printf(" DE: ");      for (auto DE : CurrentDictionaryEntrySequence) { @@ -512,12 +515,13 @@ size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,    // in which case they will return 0.    // Try several times before returning un-mutated data.    for (int Iter = 0; Iter < 100; Iter++) { -    auto M = Mutators[Rand(Mutators.size())]; -    size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize); +    auto M = &Mutators[Rand(Mutators.size())]; +    size_t NewSize = (this->*(M->Fn))(Data, Size, MaxSize);      if (NewSize && NewSize <= MaxSize) {        if (Options.OnlyASCII)          ToASCII(Data, NewSize);        CurrentMutatorSequence.push_back(M); +      M->TotalCount++;        return NewSize;      }    } @@ -525,9 +529,54 @@ size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,    return 1;   // Fallback, should not happen frequently.  } +// Mask represents the set of Data bytes that are worth mutating. +size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size, +                                          size_t MaxSize, +                                          const Vector<uint8_t> &Mask) { +  assert(Size <= Mask.size()); +  // * Copy the worthy bytes into a temporary array T +  // * Mutate T +  // * Copy T back. +  // This is totally unoptimized. +  auto &T = MutateWithMaskTemp; +  if (T.size() < Size) +    T.resize(Size); +  size_t OneBits = 0; +  for (size_t I = 0; I < Size; I++) +    if (Mask[I]) +      T[OneBits++] = Data[I]; + +  assert(!T.empty()); +  size_t NewSize = Mutate(T.data(), OneBits, OneBits); +  assert(NewSize <= OneBits); +  (void)NewSize; +  // Even if NewSize < OneBits we still use all OneBits bytes. +  for (size_t I = 0, J = 0; I < Size; I++) +    if (Mask[I]) +      Data[I] = T[J++]; +  return Size; +} +  void MutationDispatcher::AddWordToManualDictionary(const Word &W) {    ManualDictionary.push_back(        {W, std::numeric_limits<size_t>::max()});  } +void MutationDispatcher::RecordUsefulMutations() { +  for (auto M : CurrentMutatorSequence) M->UsefulCount++; +} + +void MutationDispatcher::PrintMutationStats() { +  Printf("\nstat::mutation_usefulness:      "); +  for (size_t i = 0; i < Mutators.size(); i++) { +    double UsefulPercentage = +        Mutators[i].TotalCount +            ? (100.0 * Mutators[i].UsefulCount) / Mutators[i].TotalCount +            : 0; +    Printf("%.3f", UsefulPercentage); +    if (i < Mutators.size() - 1) Printf(","); +  } +  Printf("\n"); +} +  }  // namespace fuzzer  | 
