xref: /freebsd/contrib/llvm-project/compiler-rt/lib/fuzzer/FuzzerDictionary.h (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric // fuzzer::Dictionary
90b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #ifndef LLVM_FUZZER_DICTIONARY_H
120b57cec5SDimitry Andric #define LLVM_FUZZER_DICTIONARY_H
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "FuzzerDefs.h"
150b57cec5SDimitry Andric #include "FuzzerIO.h"
160b57cec5SDimitry Andric #include "FuzzerUtil.h"
170b57cec5SDimitry Andric #include <algorithm>
180b57cec5SDimitry Andric #include <limits>
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace fuzzer {
210b57cec5SDimitry Andric // A simple POD sized array of bytes.
220b57cec5SDimitry Andric template <size_t kMaxSizeT> class FixedWord {
230b57cec5SDimitry Andric public:
240b57cec5SDimitry Andric   static const size_t kMaxSize = kMaxSizeT;
250b57cec5SDimitry Andric   FixedWord() {}
26*fe6060f1SDimitry Andric   FixedWord(const uint8_t *B, size_t S) { Set(B, S); }
270b57cec5SDimitry Andric 
28*fe6060f1SDimitry Andric   void Set(const uint8_t *B, size_t S) {
29*fe6060f1SDimitry Andric     static_assert(kMaxSizeT <= std::numeric_limits<uint8_t>::max(),
30*fe6060f1SDimitry Andric                   "FixedWord::kMaxSizeT cannot fit in a uint8_t.");
310b57cec5SDimitry Andric     assert(S <= kMaxSize);
320b57cec5SDimitry Andric     memcpy(Data, B, S);
33*fe6060f1SDimitry Andric     Size = static_cast<uint8_t>(S);
340b57cec5SDimitry Andric   }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   bool operator==(const FixedWord<kMaxSize> &w) const {
370b57cec5SDimitry Andric     return Size == w.Size && 0 == memcmp(Data, w.Data, Size);
380b57cec5SDimitry Andric   }
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   static size_t GetMaxSize() { return kMaxSize; }
410b57cec5SDimitry Andric   const uint8_t *data() const { return Data; }
420b57cec5SDimitry Andric   uint8_t size() const { return Size; }
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric private:
450b57cec5SDimitry Andric   uint8_t Size = 0;
460b57cec5SDimitry Andric   uint8_t Data[kMaxSize];
470b57cec5SDimitry Andric };
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric typedef FixedWord<64> Word;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric class DictionaryEntry {
520b57cec5SDimitry Andric  public:
530b57cec5SDimitry Andric   DictionaryEntry() {}
540b57cec5SDimitry Andric   DictionaryEntry(Word W) : W(W) {}
550b57cec5SDimitry Andric   DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {}
560b57cec5SDimitry Andric   const Word &GetW() const { return W; }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   bool HasPositionHint() const { return PositionHint != std::numeric_limits<size_t>::max(); }
590b57cec5SDimitry Andric   size_t GetPositionHint() const {
600b57cec5SDimitry Andric     assert(HasPositionHint());
610b57cec5SDimitry Andric     return PositionHint;
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric   void IncUseCount() { UseCount++; }
640b57cec5SDimitry Andric   void IncSuccessCount() { SuccessCount++; }
650b57cec5SDimitry Andric   size_t GetUseCount() const { return UseCount; }
660b57cec5SDimitry Andric   size_t GetSuccessCount() const {return SuccessCount; }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   void Print(const char *PrintAfter = "\n") {
690b57cec5SDimitry Andric     PrintASCII(W.data(), W.size());
700b57cec5SDimitry Andric     if (HasPositionHint())
710b57cec5SDimitry Andric       Printf("@%zd", GetPositionHint());
720b57cec5SDimitry Andric     Printf("%s", PrintAfter);
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric private:
760b57cec5SDimitry Andric   Word W;
770b57cec5SDimitry Andric   size_t PositionHint = std::numeric_limits<size_t>::max();
780b57cec5SDimitry Andric   size_t UseCount = 0;
790b57cec5SDimitry Andric   size_t SuccessCount = 0;
800b57cec5SDimitry Andric };
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric class Dictionary {
830b57cec5SDimitry Andric  public:
840b57cec5SDimitry Andric   static const size_t kMaxDictSize = 1 << 14;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   bool ContainsWord(const Word &W) const {
870b57cec5SDimitry Andric     return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) {
880b57cec5SDimitry Andric       return DE.GetW() == W;
890b57cec5SDimitry Andric     });
900b57cec5SDimitry Andric   }
910b57cec5SDimitry Andric   const DictionaryEntry *begin() const { return &DE[0]; }
920b57cec5SDimitry Andric   const DictionaryEntry *end() const { return begin() + Size; }
930b57cec5SDimitry Andric   DictionaryEntry & operator[] (size_t Idx) {
940b57cec5SDimitry Andric     assert(Idx < Size);
950b57cec5SDimitry Andric     return DE[Idx];
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric   void push_back(DictionaryEntry DE) {
980b57cec5SDimitry Andric     if (Size < kMaxDictSize)
990b57cec5SDimitry Andric       this->DE[Size++] = DE;
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric   void clear() { Size = 0; }
1020b57cec5SDimitry Andric   bool empty() const { return Size == 0; }
1030b57cec5SDimitry Andric   size_t size() const { return Size; }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric private:
1060b57cec5SDimitry Andric   DictionaryEntry DE[kMaxDictSize];
1070b57cec5SDimitry Andric   size_t Size = 0;
1080b57cec5SDimitry Andric };
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric // Parses one dictionary entry.
1110b57cec5SDimitry Andric // If successful, write the enty to Unit and returns true,
1120b57cec5SDimitry Andric // otherwise returns false.
1130b57cec5SDimitry Andric bool ParseOneDictionaryEntry(const std::string &Str, Unit *U);
1140b57cec5SDimitry Andric // Parses the dictionary file, fills Units, returns true iff all lines
1150b57cec5SDimitry Andric // were parsed successfully.
1160b57cec5SDimitry Andric bool ParseDictionaryFile(const std::string &Text, Vector<Unit> *Units);
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric }  // namespace fuzzer
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric #endif  // LLVM_FUZZER_DICTIONARY_H
121