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