blob: 0a6746b4c911abfd2e2ee728db0ec3b6599c30a9 [file] [log] [blame]
Aaron Ballmanef116982015-01-29 16:58:29 +00001//===- 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"
Kostya Serebryany96eab652015-05-14 22:41:49 +000013#include <sstream>
14#include <iomanip>
Aaron Ballmanef116982015-01-29 16:58:29 +000015#include <sys/time.h>
16#include <cassert>
17#include <cstring>
18#include <signal.h>
Kostya Serebryany9838b2b2015-09-03 20:23:46 +000019#include <sstream>
Kostya Serebryanyf47198a2015-05-12 22:03:34 +000020#include <unistd.h>
Aaron Ballmanef116982015-01-29 16:58:29 +000021
22namespace fuzzer {
23
Kostya Serebryany98abb2c2016-01-13 23:46:01 +000024void PrintHexArray(const uint8_t *Data, size_t Size,
25 const char *PrintAfter) {
26 for (size_t i = 0; i < Size; i++)
27 Printf("0x%x,", (unsigned)Data[i]);
Kostya Serebryany7c180ea2015-05-23 01:22:35 +000028 Printf("%s", PrintAfter);
Aaron Ballmanef116982015-01-29 16:58:29 +000029}
30
Kostya Serebryany98abb2c2016-01-13 23:46:01 +000031void Print(const Unit &v, const char *PrintAfter) {
32 PrintHexArray(v.data(), v.size(), PrintAfter);
33}
34
Kostya Serebryany41740052016-01-12 02:36:59 +000035void PrintASCIIByte(uint8_t Byte) {
36 if (Byte == '\\')
37 Printf("\\\\");
38 else if (Byte == '"')
39 Printf("\\\"");
40 else if (Byte >= 32 && Byte < 127)
41 Printf("%c", Byte);
42 else
43 Printf("\\x%02x", Byte);
44}
45
46void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) {
47 for (size_t i = 0; i < Size; i++)
48 PrintASCIIByte(Data[i]);
49 Printf("%s", PrintAfter);
50}
51
Aaron Ballmanef116982015-01-29 16:58:29 +000052void PrintASCII(const Unit &U, const char *PrintAfter) {
Kostya Serebryany41740052016-01-12 02:36:59 +000053 for (auto X : U)
54 PrintASCIIByte(X);
Kostya Serebryany7c180ea2015-05-23 01:22:35 +000055 Printf("%s", PrintAfter);
Aaron Ballmanef116982015-01-29 16:58:29 +000056}
57
Kostya Serebryany96eab652015-05-14 22:41:49 +000058std::string Hash(const Unit &U) {
59 uint8_t Hash[kSHA1NumBytes];
60 ComputeSHA1(U.data(), U.size(), Hash);
61 std::stringstream SS;
62 for (int i = 0; i < kSHA1NumBytes; i++)
63 SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Hash[i];
64 return SS.str();
Aaron Ballmanef116982015-01-29 16:58:29 +000065}
66
67static void AlarmHandler(int, siginfo_t *, void *) {
Kostya Serebryany52a788e2015-03-31 20:13:20 +000068 Fuzzer::StaticAlarmCallback();
Aaron Ballmanef116982015-01-29 16:58:29 +000069}
70
71void SetTimer(int Seconds) {
72 struct itimerval T {{Seconds, 0}, {Seconds, 0}};
Aaron Ballmanef116982015-01-29 16:58:29 +000073 int Res = setitimer(ITIMER_REAL, &T, nullptr);
74 assert(Res == 0);
75 struct sigaction sigact;
76 memset(&sigact, 0, sizeof(sigact));
77 sigact.sa_sigaction = AlarmHandler;
78 Res = sigaction(SIGALRM, &sigact, 0);
79 assert(Res == 0);
80}
81
Kostya Serebryany9690fcf2015-05-12 18:51:57 +000082int NumberOfCpuCores() {
83 FILE *F = popen("nproc", "r");
84 int N = 0;
85 fscanf(F, "%d", &N);
86 fclose(F);
87 return N;
88}
89
Kostya Serebryanydc3135d2015-11-12 01:02:01 +000090int ExecuteCommand(const std::string &Command) {
91 return system(Command.c_str());
Kostya Serebryany2da7b842015-05-18 21:34:20 +000092}
93
Kostya Serebryanybc7c0ad2015-08-11 01:44:42 +000094bool ToASCII(Unit &U) {
95 bool Changed = false;
96 for (auto &X : U) {
97 auto NewX = X;
98 NewX &= 127;
99 if (!isspace(NewX) && !isprint(NewX))
100 NewX = ' ';
101 Changed |= NewX != X;
102 X = NewX;
103 }
104 return Changed;
105}
106
Kostya Serebryanya9346c22015-09-02 19:08:08 +0000107bool IsASCII(const Unit &U) {
108 for (auto X : U)
109 if (!(isprint(X) || isspace(X))) return false;
110 return true;
111}
112
Kostya Serebryany9838b2b2015-09-03 20:23:46 +0000113bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) {
114 U->clear();
115 if (Str.empty()) return false;
116 size_t L = 0, R = Str.size() - 1; // We are parsing the range [L,R].
117 // Skip spaces from both sides.
118 while (L < R && isspace(Str[L])) L++;
119 while (R > L && isspace(Str[R])) R--;
120 if (R - L < 2) return false;
121 // Check the closing "
122 if (Str[R] != '"') return false;
123 R--;
124 // Find the opening "
125 while (L < R && Str[L] != '"') L++;
126 if (L >= R) return false;
127 assert(Str[L] == '\"');
128 L++;
129 assert(L <= R);
130 for (size_t Pos = L; Pos <= R; Pos++) {
131 uint8_t V = (uint8_t)Str[Pos];
132 if (!isprint(V) && !isspace(V)) return false;
133 if (V =='\\') {
134 // Handle '\\'
135 if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) {
136 U->push_back(Str[Pos + 1]);
137 Pos++;
138 continue;
139 }
140 // Handle '\xAB'
141 if (Pos + 3 <= R && Str[Pos + 1] == 'x'
142 && isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) {
143 char Hex[] = "0xAA";
144 Hex[2] = Str[Pos + 2];
145 Hex[3] = Str[Pos + 3];
146 U->push_back(strtol(Hex, nullptr, 16));
147 Pos += 3;
148 continue;
149 }
150 return false; // Invalid escape.
151 } else {
152 // Any other character.
153 U->push_back(V);
154 }
155 }
156 return true;
157}
158
159bool ParseDictionaryFile(const std::string &Text, std::vector<Unit> *Units) {
160 if (Text.empty()) {
161 Printf("ParseDictionaryFile: file does not exist or is empty\n");
162 return false;
163 }
164 std::istringstream ISS(Text);
165 Units->clear();
166 Unit U;
167 int LineNo = 0;
168 std::string S;
169 while (std::getline(ISS, S, '\n')) {
170 LineNo++;
171 size_t Pos = 0;
172 while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces.
173 if (Pos == S.size()) continue; // Empty line.
174 if (S[Pos] == '#') continue; // Comment line.
175 if (ParseOneDictionaryEntry(S, &U)) {
176 Units->push_back(U);
177 } else {
178 Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo,
179 S.c_str());
180 return false;
181 }
182 }
183 return true;
184}
185
Kostya Serebryanyd6edce92015-10-16 23:04:31 +0000186int GetPid() { return getpid(); }
187
Kostya Serebryany9e48cda2015-12-04 22:29:39 +0000188
189std::string Base64(const Unit &U) {
190 static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
191 "abcdefghijklmnopqrstuvwxyz"
192 "0123456789+/";
193 std::string Res;
194 size_t i;
195 for (i = 0; i + 2 < U.size(); i += 3) {
196 uint32_t x = (U[i] << 16) + (U[i + 1] << 8) + U[i + 2];
197 Res += Table[(x >> 18) & 63];
198 Res += Table[(x >> 12) & 63];
199 Res += Table[(x >> 6) & 63];
200 Res += Table[x & 63];
201 }
202 if (i + 1 == U.size()) {
203 uint32_t x = (U[i] << 16);
204 Res += Table[(x >> 18) & 63];
205 Res += Table[(x >> 12) & 63];
206 Res += "==";
207 } else if (i + 2 == U.size()) {
208 uint32_t x = (U[i] << 16) + (U[i + 1] << 8);
209 Res += Table[(x >> 18) & 63];
210 Res += Table[(x >> 12) & 63];
211 Res += Table[(x >> 6) & 63];
212 Res += "=";
213 }
214 return Res;
215}
216
Aaron Ballmanef116982015-01-29 16:58:29 +0000217} // namespace fuzzer