diff --git a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp index ce8c2fb7471448..f1895ec2621a46 100644 --- a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp @@ -636,7 +636,7 @@ void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) { PrintStats(Text, ""); if (Options.Verbosity) { Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize()); - MD.PrintMutationSequence(); + MD.PrintMutationSequence(Options.Verbosity >= 2); Printf("\n"); } } diff --git a/compiler-rt/lib/fuzzer/FuzzerMutate.cpp b/compiler-rt/lib/fuzzer/FuzzerMutate.cpp index 121b450e8b8c56..cf34a9fe8e2e12 100644 --- a/compiler-rt/lib/fuzzer/FuzzerMutate.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerMutate.cpp @@ -18,6 +18,7 @@ namespace fuzzer { const size_t Dictionary::kMaxDictSize; +static const size_t kMaxMutationsToPrint = 10; static void PrintASCII(const Word &W, const char *PrintAfter) { PrintASCII(W.data(), W.size(), PrintAfter); @@ -481,15 +482,21 @@ void MutationDispatcher::PrintRecommendedDictionary() { Printf("###### End of recommended dictionary. ######\n"); } -void MutationDispatcher::PrintMutationSequence() { +void MutationDispatcher::PrintMutationSequence(bool Verbose) { Printf("MS: %zd ", CurrentMutatorSequence.size()); - for (auto M : CurrentMutatorSequence) - Printf("%s-", M.Name); + size_t EntriesToPrint = + Verbose ? CurrentMutatorSequence.size() + : std::min(kMaxMutationsToPrint, CurrentMutatorSequence.size()); + for (size_t i = 0; i < EntriesToPrint; i++) + Printf("%s-", CurrentMutatorSequence[i].Name); if (!CurrentDictionaryEntrySequence.empty()) { Printf(" DE: "); - for (auto DE : CurrentDictionaryEntrySequence) { + EntriesToPrint = Verbose ? CurrentDictionaryEntrySequence.size() + : std::min(kMaxMutationsToPrint, + CurrentDictionaryEntrySequence.size()); + for (size_t i = 0; i < EntriesToPrint; i++) { Printf("\""); - PrintASCII(DE->GetW(), "\"-"); + PrintASCII(CurrentDictionaryEntrySequence[i]->GetW(), "\"-"); } } } diff --git a/compiler-rt/lib/fuzzer/FuzzerMutate.h b/compiler-rt/lib/fuzzer/FuzzerMutate.h index 3ce3159f6893be..37fd6100dac330 100644 --- a/compiler-rt/lib/fuzzer/FuzzerMutate.h +++ b/compiler-rt/lib/fuzzer/FuzzerMutate.h @@ -24,8 +24,9 @@ class MutationDispatcher { ~MutationDispatcher() {} /// Indicate that we are about to start a new sequence of mutations. void StartMutationSequence(); - /// Print the current sequence of mutations. - void PrintMutationSequence(); + /// Print the current sequence of mutations. Only prints the full sequence + /// when Verbose is true. + void PrintMutationSequence(bool Verbose = true); /// Return the current sequence of mutations. std::string MutationSequence(); /// Indicate that the current sequence of mutations was successful. diff --git a/compiler-rt/test/fuzzer/CustomMutatorWithLongSequencesTest.cpp b/compiler-rt/test/fuzzer/CustomMutatorWithLongSequencesTest.cpp new file mode 100644 index 00000000000000..4c9714788f5690 --- /dev/null +++ b/compiler-rt/test/fuzzer/CustomMutatorWithLongSequencesTest.cpp @@ -0,0 +1,40 @@ +// 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 + +// Simple test for a cutom mutator that results in long sequences of mutations. +#include +#include +#include +#include +#include +#include + +#include "FuzzerInterface.h" + +static volatile int Sink; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + assert(Data); + if (Size > 0 && Data[0] == 'H') { + Sink = 1; + if (Size > 1 && Data[1] == 'i') { + Sink = 2; + if (Size > 2 && Data[2] == '!') { + std::cout << "BINGO; Found the target, exiting\n" + << std::flush; + exit(1); + } + } + } + return 0; +} + +extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, + size_t MaxSize, unsigned int Seed) { + // Run this 25 times to generate a large mutation sequence. + for (size_t i = 0; i < 25; i++) { + LLVMFuzzerMutate(Data, Size, MaxSize); + } + return LLVMFuzzerMutate(Data, Size, MaxSize); +} diff --git a/compiler-rt/test/fuzzer/fuzzer-custommutator.test b/compiler-rt/test/fuzzer/fuzzer-custommutator.test index 25f5fe697b43fd..7d94ae064bf969 100644 --- a/compiler-rt/test/fuzzer/fuzzer-custommutator.test +++ b/compiler-rt/test/fuzzer/fuzzer-custommutator.test @@ -11,3 +11,17 @@ LLVMFuzzerCustomMutatorWithLenControl: INFO: found LLVMFuzzerCustomMutator LLVMFuzzerCustomMutatorWithLenControl: In LLVMFuzzerCustomMutator LLVMFuzzerCustomMutatorWithLenControl: {{.*}} lim: {{[1-9][0-9]?}} {{.*}} LLVMFuzzerCustomMutatorWithLenControl: BINGO + +# sanity check: verify that we do get long lines with verbose printing on +RUN: %cpp_compiler %S/CustomMutatorWithLongSequencesTest.cpp -o %t-CustomMutatorWithLongSequencesTest +RUN: not %run %t-CustomMutatorWithLongSequencesTest -verbosity=2 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutatorLongSequence +LLVMFuzzerCustomMutatorLongSequence: Flag: verbosity 2 +LLVMFuzzerCustomMutatorLongSequence: {{.*}} MS: {{[0-9]*}} {{(([a-zA-Z]*-){11,})}} {{.*}} +LLVMFuzzerCustomMutatorLongSequence: BINGO + +# check a target that prints long mutation sequences and verifies the printed +# output is capped at 10 entries +RUN: not %run %t-CustomMutatorWithLongSequencesTest 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutatorLongSequenceTrimmed +LLVMFuzzerCustomMutatorLongSequenceTrimmed-NOT: Flag: verbosity 2 +LLVMFuzzerCustomMutatorLongSequenceTrimmed-NOT: {{.*}} MS: {{[0-9]*}} {{(([a-zA-Z]*-){11,})}} {{.*}} +LLVMFuzzerCustomMutatorLongSequenceTrimmed: BINGO