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 "FuzzerInternal.h" 13 #include <sstream> 14 #include <iomanip> 15 #include <sys/time.h> 16 #include <cassert> 17 #include <cstring> 18 #include <signal.h> 19 #include <sstream> 20 #include <unistd.h> 21 22 namespace fuzzer { 23 24 void Print(const Unit &v, const char *PrintAfter) { 25 for (auto x : v) 26 Printf("0x%x,", (unsigned) x); 27 Printf("%s", PrintAfter); 28 } 29 30 void PrintASCII(const Unit &U, const char *PrintAfter) { 31 for (auto X : U) { 32 if (isprint(X)) 33 Printf("%c", X); 34 else 35 Printf("\\x%x", (unsigned)X); 36 } 37 Printf("%s", PrintAfter); 38 } 39 40 std::string Hash(const Unit &U) { 41 uint8_t Hash[kSHA1NumBytes]; 42 ComputeSHA1(U.data(), U.size(), Hash); 43 std::stringstream SS; 44 for (int i = 0; i < kSHA1NumBytes; i++) 45 SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Hash[i]; 46 return SS.str(); 47 } 48 49 static void AlarmHandler(int, siginfo_t *, void *) { 50 Fuzzer::StaticAlarmCallback(); 51 } 52 53 void SetTimer(int Seconds) { 54 struct itimerval T {{Seconds, 0}, {Seconds, 0}}; 55 int Res = setitimer(ITIMER_REAL, &T, nullptr); 56 assert(Res == 0); 57 struct sigaction sigact; 58 memset(&sigact, 0, sizeof(sigact)); 59 sigact.sa_sigaction = AlarmHandler; 60 Res = sigaction(SIGALRM, &sigact, 0); 61 assert(Res == 0); 62 } 63 64 int NumberOfCpuCores() { 65 FILE *F = popen("nproc", "r"); 66 int N = 0; 67 fscanf(F, "%d", &N); 68 fclose(F); 69 return N; 70 } 71 72 int ExecuteCommand(const std::string &Command) { 73 return system(Command.c_str()); 74 } 75 76 bool ToASCII(Unit &U) { 77 bool Changed = false; 78 for (auto &X : U) { 79 auto NewX = X; 80 NewX &= 127; 81 if (!isspace(NewX) && !isprint(NewX)) 82 NewX = ' '; 83 Changed |= NewX != X; 84 X = NewX; 85 } 86 return Changed; 87 } 88 89 bool IsASCII(const Unit &U) { 90 for (auto X : U) 91 if (!(isprint(X) || isspace(X))) return false; 92 return true; 93 } 94 95 bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) { 96 U->clear(); 97 if (Str.empty()) return false; 98 size_t L = 0, R = Str.size() - 1; // We are parsing the range [L,R]. 99 // Skip spaces from both sides. 100 while (L < R && isspace(Str[L])) L++; 101 while (R > L && isspace(Str[R])) R--; 102 if (R - L < 2) return false; 103 // Check the closing " 104 if (Str[R] != '"') return false; 105 R--; 106 // Find the opening " 107 while (L < R && Str[L] != '"') L++; 108 if (L >= R) return false; 109 assert(Str[L] == '\"'); 110 L++; 111 assert(L <= R); 112 for (size_t Pos = L; Pos <= R; Pos++) { 113 uint8_t V = (uint8_t)Str[Pos]; 114 if (!isprint(V) && !isspace(V)) return false; 115 if (V =='\\') { 116 // Handle '\\' 117 if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) { 118 U->push_back(Str[Pos + 1]); 119 Pos++; 120 continue; 121 } 122 // Handle '\xAB' 123 if (Pos + 3 <= R && Str[Pos + 1] == 'x' 124 && isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) { 125 char Hex[] = "0xAA"; 126 Hex[2] = Str[Pos + 2]; 127 Hex[3] = Str[Pos + 3]; 128 U->push_back(strtol(Hex, nullptr, 16)); 129 Pos += 3; 130 continue; 131 } 132 return false; // Invalid escape. 133 } else { 134 // Any other character. 135 U->push_back(V); 136 } 137 } 138 return true; 139 } 140 141 bool ParseDictionaryFile(const std::string &Text, std::vector<Unit> *Units) { 142 if (Text.empty()) { 143 Printf("ParseDictionaryFile: file does not exist or is empty\n"); 144 return false; 145 } 146 std::istringstream ISS(Text); 147 Units->clear(); 148 Unit U; 149 int LineNo = 0; 150 std::string S; 151 while (std::getline(ISS, S, '\n')) { 152 LineNo++; 153 size_t Pos = 0; 154 while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces. 155 if (Pos == S.size()) continue; // Empty line. 156 if (S[Pos] == '#') continue; // Comment line. 157 if (ParseOneDictionaryEntry(S, &U)) { 158 Units->push_back(U); 159 } else { 160 Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo, 161 S.c_str()); 162 return false; 163 } 164 } 165 return true; 166 } 167 168 int GetPid() { return getpid(); } 169 170 171 std::string Base64(const Unit &U) { 172 static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 173 "abcdefghijklmnopqrstuvwxyz" 174 "0123456789+/"; 175 std::string Res; 176 size_t i; 177 for (i = 0; i + 2 < U.size(); i += 3) { 178 uint32_t x = (U[i] << 16) + (U[i + 1] << 8) + U[i + 2]; 179 Res += Table[(x >> 18) & 63]; 180 Res += Table[(x >> 12) & 63]; 181 Res += Table[(x >> 6) & 63]; 182 Res += Table[x & 63]; 183 } 184 if (i + 1 == U.size()) { 185 uint32_t x = (U[i] << 16); 186 Res += Table[(x >> 18) & 63]; 187 Res += Table[(x >> 12) & 63]; 188 Res += "=="; 189 } else if (i + 2 == U.size()) { 190 uint32_t x = (U[i] << 16) + (U[i + 1] << 8); 191 Res += Table[(x >> 18) & 63]; 192 Res += Table[(x >> 12) & 63]; 193 Res += Table[(x >> 6) & 63]; 194 Res += "="; 195 } 196 return Res; 197 } 198 199 } // namespace fuzzer 200