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