1 1.1 kamil //===- FuzzerUtil.cpp - Misc utils ----------------------------------------===// 2 1.1 kamil // 3 1.1 kamil // The LLVM Compiler Infrastructure 4 1.1 kamil // 5 1.1 kamil // This file is distributed under the University of Illinois Open Source 6 1.1 kamil // License. See LICENSE.TXT for details. 7 1.1 kamil // 8 1.1 kamil //===----------------------------------------------------------------------===// 9 1.1 kamil // Misc utils. 10 1.1 kamil //===----------------------------------------------------------------------===// 11 1.1 kamil 12 1.1 kamil #include "FuzzerUtil.h" 13 1.1 kamil #include "FuzzerIO.h" 14 1.1 kamil #include "FuzzerInternal.h" 15 1.1 kamil #include <cassert> 16 1.1 kamil #include <chrono> 17 1.1 kamil #include <cstring> 18 1.1 kamil #include <errno.h> 19 1.1 kamil #include <mutex> 20 1.1 kamil #include <signal.h> 21 1.1 kamil #include <sstream> 22 1.1 kamil #include <stdio.h> 23 1.1 kamil #include <sys/types.h> 24 1.1 kamil #include <thread> 25 1.1 kamil 26 1.1 kamil namespace fuzzer { 27 1.1 kamil 28 1.1 kamil void PrintHexArray(const uint8_t *Data, size_t Size, 29 1.1 kamil const char *PrintAfter) { 30 1.1 kamil for (size_t i = 0; i < Size; i++) 31 1.1 kamil Printf("0x%x,", (unsigned)Data[i]); 32 1.1 kamil Printf("%s", PrintAfter); 33 1.1 kamil } 34 1.1 kamil 35 1.1 kamil void Print(const Unit &v, const char *PrintAfter) { 36 1.1 kamil PrintHexArray(v.data(), v.size(), PrintAfter); 37 1.1 kamil } 38 1.1 kamil 39 1.1 kamil void PrintASCIIByte(uint8_t Byte) { 40 1.1 kamil if (Byte == '\\') 41 1.1 kamil Printf("\\\\"); 42 1.1 kamil else if (Byte == '"') 43 1.1 kamil Printf("\\\""); 44 1.1 kamil else if (Byte >= 32 && Byte < 127) 45 1.1 kamil Printf("%c", Byte); 46 1.1 kamil else 47 1.1 kamil Printf("\\x%02x", Byte); 48 1.1 kamil } 49 1.1 kamil 50 1.1 kamil void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) { 51 1.1 kamil for (size_t i = 0; i < Size; i++) 52 1.1 kamil PrintASCIIByte(Data[i]); 53 1.1 kamil Printf("%s", PrintAfter); 54 1.1 kamil } 55 1.1 kamil 56 1.1 kamil void PrintASCII(const Unit &U, const char *PrintAfter) { 57 1.1 kamil PrintASCII(U.data(), U.size(), PrintAfter); 58 1.1 kamil } 59 1.1 kamil 60 1.1 kamil bool ToASCII(uint8_t *Data, size_t Size) { 61 1.1 kamil bool Changed = false; 62 1.1 kamil for (size_t i = 0; i < Size; i++) { 63 1.1 kamil uint8_t &X = Data[i]; 64 1.1 kamil auto NewX = X; 65 1.1 kamil NewX &= 127; 66 1.1 kamil if (!isspace(NewX) && !isprint(NewX)) 67 1.1 kamil NewX = ' '; 68 1.1 kamil Changed |= NewX != X; 69 1.1 kamil X = NewX; 70 1.1 kamil } 71 1.1 kamil return Changed; 72 1.1 kamil } 73 1.1 kamil 74 1.1 kamil bool IsASCII(const Unit &U) { return IsASCII(U.data(), U.size()); } 75 1.1 kamil 76 1.1 kamil bool IsASCII(const uint8_t *Data, size_t Size) { 77 1.1 kamil for (size_t i = 0; i < Size; i++) 78 1.1 kamil if (!(isprint(Data[i]) || isspace(Data[i]))) return false; 79 1.1 kamil return true; 80 1.1 kamil } 81 1.1 kamil 82 1.1 kamil bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) { 83 1.1 kamil U->clear(); 84 1.1 kamil if (Str.empty()) return false; 85 1.1 kamil size_t L = 0, R = Str.size() - 1; // We are parsing the range [L,R]. 86 1.1 kamil // Skip spaces from both sides. 87 1.1 kamil while (L < R && isspace(Str[L])) L++; 88 1.1 kamil while (R > L && isspace(Str[R])) R--; 89 1.1 kamil if (R - L < 2) return false; 90 1.1 kamil // Check the closing " 91 1.1 kamil if (Str[R] != '"') return false; 92 1.1 kamil R--; 93 1.1 kamil // Find the opening " 94 1.1 kamil while (L < R && Str[L] != '"') L++; 95 1.1 kamil if (L >= R) return false; 96 1.1 kamil assert(Str[L] == '\"'); 97 1.1 kamil L++; 98 1.1 kamil assert(L <= R); 99 1.1 kamil for (size_t Pos = L; Pos <= R; Pos++) { 100 1.1 kamil uint8_t V = (uint8_t)Str[Pos]; 101 1.1 kamil if (!isprint(V) && !isspace(V)) return false; 102 1.1 kamil if (V =='\\') { 103 1.1 kamil // Handle '\\' 104 1.1 kamil if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) { 105 1.1 kamil U->push_back(Str[Pos + 1]); 106 1.1 kamil Pos++; 107 1.1 kamil continue; 108 1.1 kamil } 109 1.1 kamil // Handle '\xAB' 110 1.1 kamil if (Pos + 3 <= R && Str[Pos + 1] == 'x' 111 1.1 kamil && isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) { 112 1.1 kamil char Hex[] = "0xAA"; 113 1.1 kamil Hex[2] = Str[Pos + 2]; 114 1.1 kamil Hex[3] = Str[Pos + 3]; 115 1.1 kamil U->push_back(strtol(Hex, nullptr, 16)); 116 1.1 kamil Pos += 3; 117 1.1 kamil continue; 118 1.1 kamil } 119 1.1 kamil return false; // Invalid escape. 120 1.1 kamil } else { 121 1.1 kamil // Any other character. 122 1.1 kamil U->push_back(V); 123 1.1 kamil } 124 1.1 kamil } 125 1.1 kamil return true; 126 1.1 kamil } 127 1.1 kamil 128 1.1 kamil bool ParseDictionaryFile(const std::string &Text, Vector<Unit> *Units) { 129 1.1 kamil if (Text.empty()) { 130 1.1 kamil Printf("ParseDictionaryFile: file does not exist or is empty\n"); 131 1.1 kamil return false; 132 1.1 kamil } 133 1.1 kamil std::istringstream ISS(Text); 134 1.1 kamil Units->clear(); 135 1.1 kamil Unit U; 136 1.1 kamil int LineNo = 0; 137 1.1 kamil std::string S; 138 1.1 kamil while (std::getline(ISS, S, '\n')) { 139 1.1 kamil LineNo++; 140 1.1 kamil size_t Pos = 0; 141 1.1 kamil while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces. 142 1.1 kamil if (Pos == S.size()) continue; // Empty line. 143 1.1 kamil if (S[Pos] == '#') continue; // Comment line. 144 1.1 kamil if (ParseOneDictionaryEntry(S, &U)) { 145 1.1 kamil Units->push_back(U); 146 1.1 kamil } else { 147 1.1 kamil Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo, 148 1.1 kamil S.c_str()); 149 1.1 kamil return false; 150 1.1 kamil } 151 1.1 kamil } 152 1.1 kamil return true; 153 1.1 kamil } 154 1.1 kamil 155 1.1 kamil std::string Base64(const Unit &U) { 156 1.1 kamil static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 157 1.1 kamil "abcdefghijklmnopqrstuvwxyz" 158 1.1 kamil "0123456789+/"; 159 1.1 kamil std::string Res; 160 1.1 kamil size_t i; 161 1.1 kamil for (i = 0; i + 2 < U.size(); i += 3) { 162 1.1 kamil uint32_t x = (U[i] << 16) + (U[i + 1] << 8) + U[i + 2]; 163 1.1 kamil Res += Table[(x >> 18) & 63]; 164 1.1 kamil Res += Table[(x >> 12) & 63]; 165 1.1 kamil Res += Table[(x >> 6) & 63]; 166 1.1 kamil Res += Table[x & 63]; 167 1.1 kamil } 168 1.1 kamil if (i + 1 == U.size()) { 169 1.1 kamil uint32_t x = (U[i] << 16); 170 1.1 kamil Res += Table[(x >> 18) & 63]; 171 1.1 kamil Res += Table[(x >> 12) & 63]; 172 1.1 kamil Res += "=="; 173 1.1 kamil } else if (i + 2 == U.size()) { 174 1.1 kamil uint32_t x = (U[i] << 16) + (U[i + 1] << 8); 175 1.1 kamil Res += Table[(x >> 18) & 63]; 176 1.1 kamil Res += Table[(x >> 12) & 63]; 177 1.1 kamil Res += Table[(x >> 6) & 63]; 178 1.1 kamil Res += "="; 179 1.1 kamil } 180 1.1 kamil return Res; 181 1.1 kamil } 182 1.1 kamil 183 1.1 kamil static std::mutex SymbolizeMutex; 184 1.1 kamil 185 1.1 kamil std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) { 186 1.1 kamil std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock); 187 1.1 kamil if (!EF->__sanitizer_symbolize_pc || !l.owns_lock()) 188 1.1 kamil return "<can not symbolize>"; 189 1.1 kamil char PcDescr[1024] = {}; 190 1.1 kamil EF->__sanitizer_symbolize_pc(reinterpret_cast<void*>(PC), 191 1.1 kamil SymbolizedFMT, PcDescr, sizeof(PcDescr)); 192 1.1 kamil PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case. 193 1.1 kamil return PcDescr; 194 1.1 kamil } 195 1.1 kamil 196 1.1 kamil void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC) { 197 1.1 kamil if (EF->__sanitizer_symbolize_pc) 198 1.1 kamil Printf("%s", DescribePC(SymbolizedFMT, PC).c_str()); 199 1.1 kamil else 200 1.1 kamil Printf(FallbackFMT, PC); 201 1.1 kamil } 202 1.1 kamil 203 1.1 kamil void PrintStackTrace() { 204 1.1 kamil std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock); 205 1.1 kamil if (EF->__sanitizer_print_stack_trace && l.owns_lock()) 206 1.1 kamil EF->__sanitizer_print_stack_trace(); 207 1.1 kamil } 208 1.1 kamil 209 1.1 kamil void PrintMemoryProfile() { 210 1.1 kamil std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock); 211 1.1 kamil if (EF->__sanitizer_print_memory_profile && l.owns_lock()) 212 1.1 kamil EF->__sanitizer_print_memory_profile(95, 8); 213 1.1 kamil } 214 1.1 kamil 215 1.1 kamil unsigned NumberOfCpuCores() { 216 1.1 kamil unsigned N = std::thread::hardware_concurrency(); 217 1.1 kamil if (!N) { 218 1.1 kamil Printf("WARNING: std::thread::hardware_concurrency not well defined for " 219 1.1 kamil "your platform. Assuming CPU count of 1.\n"); 220 1.1 kamil N = 1; 221 1.1 kamil } 222 1.1 kamil return N; 223 1.1 kamil } 224 1.1 kamil 225 1.1 kamil size_t SimpleFastHash(const uint8_t *Data, size_t Size) { 226 1.1 kamil size_t Res = 0; 227 1.1 kamil for (size_t i = 0; i < Size; i++) 228 1.1 kamil Res = Res * 11 + Data[i]; 229 1.1 kamil return Res; 230 1.1 kamil } 231 1.1 kamil 232 1.1 kamil } // namespace fuzzer 233