diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp --- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp @@ -88,6 +88,7 @@ static Vector *Inputs; static std::string *ProgName; +static Dictionary ManualDictionary; static void PrintHelp() { Printf("Usage:\n"); @@ -804,13 +805,15 @@ } Random Rand(Seed); - auto *MD = new MutationDispatcher(Rand, Options); + auto *MD = new MutationDispatcher(Rand, Options, ManualDictionary); auto *Corpus = new InputCorpus(Options.OutputCorpus, Entropic); auto *F = new Fuzzer(Callback, *Corpus, *MD, Options); for (auto &U: Dictionary) - if (U.size() <= Word::GetMaxSize()) - MD->AddWordToManualDictionary(Word(U.data(), U.size())); + if (U.size() <= Word::GetMaxSize()) { + Word UWord(U.data(), U.size()); + ManualDictionary.push_back({UWord, std::numeric_limits::max()}); + } // Threads are only supported by Chrome. Don't use them with emscripten // for now. @@ -919,6 +922,27 @@ return FuzzerDriver(argc, argv, UserCb); } +extern "C" ATTRIBUTE_INTERFACE void +LLVMFuzzerAddToDictionary(const uint8_t *Data, size_t Size) { + while (Size >= Word::kMaxSize) { + Word DataWord(Data, Word::kMaxSize); + if (!ManualDictionary.ContainsWord(DataWord)) { + ManualDictionary.push_back( + {DataWord, std::numeric_limits::max()}); + } + Size -= Word::kMaxSize; + Data += Word::kMaxSize; + } + + if (Size) { + Word DataWord(Data, Size); + if (!ManualDictionary.ContainsWord(DataWord)) { + ManualDictionary.push_back( + {DataWord, std::numeric_limits::max()}); + } + } +} + // Storage for global ExternalFunctions object. ExternalFunctions *EF = nullptr; diff --git a/compiler-rt/lib/fuzzer/FuzzerMutate.h b/compiler-rt/lib/fuzzer/FuzzerMutate.h --- a/compiler-rt/lib/fuzzer/FuzzerMutate.h +++ b/compiler-rt/lib/fuzzer/FuzzerMutate.h @@ -18,9 +18,12 @@ namespace fuzzer { +extern Dictionary DefaultEmptyDictionary; + class MutationDispatcher { public: - MutationDispatcher(Random &Rand, const FuzzingOptions &Options); + MutationDispatcher(Random &Rand, const FuzzingOptions &Options, + Dictionary &ManualDictionary = DefaultEmptyDictionary); ~MutationDispatcher() {} /// Indicate that we are about to start a new sequence of mutations. void StartMutationSequence(); @@ -87,8 +90,6 @@ size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, size_t Size2, uint8_t *Out, size_t MaxOutSize); - void AddWordToManualDictionary(const Word &W); - void PrintRecommendedDictionary(); void SetCrossOverWith(const Unit *U) { CrossOverWith = U; } @@ -127,8 +128,9 @@ Random &Rand; const FuzzingOptions Options; - // Dictionary provided by the user via -dict=DICT_FILE. - Dictionary ManualDictionary; + // Dictionary provided by the user via -dict=DICT_FILE or + // LLVMFuzzerAddToDictionary. + Dictionary &ManualDictionary; // Persistent dictionary modified by the fuzzer, consists of // entries that led to successful discoveries in the past mutations. Dictionary PersistentAutoDictionary; diff --git a/compiler-rt/lib/fuzzer/FuzzerMutate.cpp b/compiler-rt/lib/fuzzer/FuzzerMutate.cpp --- a/compiler-rt/lib/fuzzer/FuzzerMutate.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerMutate.cpp @@ -18,6 +18,9 @@ namespace fuzzer { const size_t Dictionary::kMaxDictSize; + +Dictionary DefaultEmptyDictionary; + static const size_t kMaxMutationsToPrint = 10; static void PrintASCII(const Word &W, const char *PrintAfter) { @@ -25,8 +28,9 @@ } MutationDispatcher::MutationDispatcher(Random &Rand, - const FuzzingOptions &Options) - : Rand(Rand), Options(Options) { + const FuzzingOptions &Options, + Dictionary &ManualDictionary) + : Rand(Rand), Options(Options), ManualDictionary(ManualDictionary) { DefaultMutators.insert( DefaultMutators.begin(), { @@ -570,9 +574,4 @@ return Size; } -void MutationDispatcher::AddWordToManualDictionary(const Word &W) { - ManualDictionary.push_back( - {W, std::numeric_limits::max()}); -} - } // namespace fuzzer diff --git a/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp b/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp --- a/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp +++ b/compiler-rt/lib/fuzzer/tests/FuzzerUnittest.cpp @@ -417,11 +417,15 @@ std::unique_ptr t(new ExternalFunctions()); fuzzer::EF = t.get(); Random Rand(0); - std::unique_ptr MD(new MutationDispatcher(Rand, {})); + Dictionary ManualDictionary; + std::unique_ptr MD( + new MutationDispatcher(Rand, {}, ManualDictionary)); uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD}; uint8_t Word2[3] = {0xFF, 0xEE, 0xEF}; - MD->AddWordToManualDictionary(Word(Word1, sizeof(Word1))); - MD->AddWordToManualDictionary(Word(Word2, sizeof(Word2))); + ManualDictionary.push_back( + {Word(Word1, 4), std::numeric_limits::max()}); + ManualDictionary.push_back( + {Word(Word2, 3), std::numeric_limits::max()}); int FoundMask = 0; uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD}; uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22};