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
PrintHexArray(const uint8_t * Data,size_t Size,const char * PrintAfter)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
Print(const Unit & v,const char * PrintAfter)35 void Print(const Unit &v, const char *PrintAfter) {
36 PrintHexArray(v.data(), v.size(), PrintAfter);
37 }
38
PrintASCIIByte(uint8_t Byte)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
PrintASCII(const uint8_t * Data,size_t Size,const char * PrintAfter)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
PrintASCII(const Unit & U,const char * PrintAfter)56 void PrintASCII(const Unit &U, const char *PrintAfter) {
57 PrintASCII(U.data(), U.size(), PrintAfter);
58 }
59
ToASCII(uint8_t * Data,size_t Size)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
IsASCII(const Unit & U)74 bool IsASCII(const Unit &U) { return IsASCII(U.data(), U.size()); }
75
IsASCII(const uint8_t * Data,size_t Size)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
ParseOneDictionaryEntry(const std::string & Str,Unit * U)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
ParseDictionaryFile(const std::string & Text,Vector<Unit> * Units)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
Base64(const Unit & U)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
DescribePC(const char * SymbolizedFMT,uintptr_t PC)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
PrintPC(const char * SymbolizedFMT,const char * FallbackFMT,uintptr_t PC)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
PrintStackTrace()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
PrintMemoryProfile()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
NumberOfCpuCores()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
SimpleFastHash(const uint8_t * Data,size_t Size)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