13cab2bb3Spatrick //===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick // fuzzer::Dictionary 93cab2bb3Spatrick //===----------------------------------------------------------------------===// 103cab2bb3Spatrick 113cab2bb3Spatrick #ifndef LLVM_FUZZER_DICTIONARY_H 123cab2bb3Spatrick #define LLVM_FUZZER_DICTIONARY_H 133cab2bb3Spatrick 143cab2bb3Spatrick #include "FuzzerDefs.h" 153cab2bb3Spatrick #include "FuzzerIO.h" 163cab2bb3Spatrick #include "FuzzerUtil.h" 173cab2bb3Spatrick #include <algorithm> 183cab2bb3Spatrick #include <limits> 193cab2bb3Spatrick 203cab2bb3Spatrick namespace fuzzer { 213cab2bb3Spatrick // A simple POD sized array of bytes. 223cab2bb3Spatrick template <size_t kMaxSizeT> class FixedWord { 233cab2bb3Spatrick public: 243cab2bb3Spatrick static const size_t kMaxSize = kMaxSizeT; FixedWord()253cab2bb3Spatrick FixedWord() {} FixedWord(const uint8_t * B,size_t S)26d89ec533Spatrick FixedWord(const uint8_t *B, size_t S) { Set(B, S); } 273cab2bb3Spatrick Set(const uint8_t * B,size_t S)28d89ec533Spatrick void Set(const uint8_t *B, size_t S) { 29d89ec533Spatrick static_assert(kMaxSizeT <= std::numeric_limits<uint8_t>::max(), 30d89ec533Spatrick "FixedWord::kMaxSizeT cannot fit in a uint8_t."); 313cab2bb3Spatrick assert(S <= kMaxSize); 323cab2bb3Spatrick memcpy(Data, B, S); 33d89ec533Spatrick Size = static_cast<uint8_t>(S); 343cab2bb3Spatrick } 353cab2bb3Spatrick 363cab2bb3Spatrick bool operator==(const FixedWord<kMaxSize> &w) const { 373cab2bb3Spatrick return Size == w.Size && 0 == memcmp(Data, w.Data, Size); 383cab2bb3Spatrick } 393cab2bb3Spatrick GetMaxSize()403cab2bb3Spatrick static size_t GetMaxSize() { return kMaxSize; } data()413cab2bb3Spatrick const uint8_t *data() const { return Data; } size()423cab2bb3Spatrick uint8_t size() const { return Size; } 433cab2bb3Spatrick 443cab2bb3Spatrick private: 453cab2bb3Spatrick uint8_t Size = 0; 463cab2bb3Spatrick uint8_t Data[kMaxSize]; 473cab2bb3Spatrick }; 483cab2bb3Spatrick 493cab2bb3Spatrick typedef FixedWord<64> Word; 503cab2bb3Spatrick 513cab2bb3Spatrick class DictionaryEntry { 523cab2bb3Spatrick public: DictionaryEntry()533cab2bb3Spatrick DictionaryEntry() {} DictionaryEntry(Word W)543cab2bb3Spatrick DictionaryEntry(Word W) : W(W) {} DictionaryEntry(Word W,size_t PositionHint)55*810390e3Srobert DictionaryEntry(Word W, size_t PositionHint) 56*810390e3Srobert : W(W), PositionHint(PositionHint) {} GetW()573cab2bb3Spatrick const Word &GetW() const { return W; } 583cab2bb3Spatrick HasPositionHint()59*810390e3Srobert bool HasPositionHint() const { 60*810390e3Srobert return PositionHint != std::numeric_limits<size_t>::max(); 61*810390e3Srobert } GetPositionHint()623cab2bb3Spatrick size_t GetPositionHint() const { 633cab2bb3Spatrick assert(HasPositionHint()); 643cab2bb3Spatrick return PositionHint; 653cab2bb3Spatrick } IncUseCount()663cab2bb3Spatrick void IncUseCount() { UseCount++; } IncSuccessCount()673cab2bb3Spatrick void IncSuccessCount() { SuccessCount++; } GetUseCount()683cab2bb3Spatrick size_t GetUseCount() const { return UseCount; } GetSuccessCount()693cab2bb3Spatrick size_t GetSuccessCount() const {return SuccessCount; } 703cab2bb3Spatrick 713cab2bb3Spatrick void Print(const char *PrintAfter = "\n") { 723cab2bb3Spatrick PrintASCII(W.data(), W.size()); 733cab2bb3Spatrick if (HasPositionHint()) 743cab2bb3Spatrick Printf("@%zd", GetPositionHint()); 753cab2bb3Spatrick Printf("%s", PrintAfter); 763cab2bb3Spatrick } 773cab2bb3Spatrick 783cab2bb3Spatrick private: 793cab2bb3Spatrick Word W; 803cab2bb3Spatrick size_t PositionHint = std::numeric_limits<size_t>::max(); 813cab2bb3Spatrick size_t UseCount = 0; 823cab2bb3Spatrick size_t SuccessCount = 0; 833cab2bb3Spatrick }; 843cab2bb3Spatrick 853cab2bb3Spatrick class Dictionary { 863cab2bb3Spatrick public: 873cab2bb3Spatrick static const size_t kMaxDictSize = 1 << 14; 883cab2bb3Spatrick ContainsWord(const Word & W)893cab2bb3Spatrick bool ContainsWord(const Word &W) const { 903cab2bb3Spatrick return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) { 913cab2bb3Spatrick return DE.GetW() == W; 923cab2bb3Spatrick }); 933cab2bb3Spatrick } begin()943cab2bb3Spatrick const DictionaryEntry *begin() const { return &DE[0]; } end()953cab2bb3Spatrick const DictionaryEntry *end() const { return begin() + Size; } 963cab2bb3Spatrick DictionaryEntry & operator[] (size_t Idx) { 973cab2bb3Spatrick assert(Idx < Size); 983cab2bb3Spatrick return DE[Idx]; 993cab2bb3Spatrick } push_back(DictionaryEntry DE)1003cab2bb3Spatrick void push_back(DictionaryEntry DE) { 1013cab2bb3Spatrick if (Size < kMaxDictSize) 1023cab2bb3Spatrick this->DE[Size++] = DE; 1033cab2bb3Spatrick } clear()1043cab2bb3Spatrick void clear() { Size = 0; } empty()1053cab2bb3Spatrick bool empty() const { return Size == 0; } size()1063cab2bb3Spatrick size_t size() const { return Size; } 1073cab2bb3Spatrick 1083cab2bb3Spatrick private: 1093cab2bb3Spatrick DictionaryEntry DE[kMaxDictSize]; 1103cab2bb3Spatrick size_t Size = 0; 1113cab2bb3Spatrick }; 1123cab2bb3Spatrick 1133cab2bb3Spatrick // Parses one dictionary entry. 114*810390e3Srobert // If successful, writes the entry to Unit and returns true, 1153cab2bb3Spatrick // otherwise returns false. 1163cab2bb3Spatrick bool ParseOneDictionaryEntry(const std::string &Str, Unit *U); 1173cab2bb3Spatrick // Parses the dictionary file, fills Units, returns true iff all lines 1183cab2bb3Spatrick // were parsed successfully. 119*810390e3Srobert bool ParseDictionaryFile(const std::string &Text, std::vector<Unit> *Units); 1203cab2bb3Spatrick 1213cab2bb3Spatrick } // namespace fuzzer 1223cab2bb3Spatrick 1233cab2bb3Spatrick #endif // LLVM_FUZZER_DICTIONARY_H 124