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