blob: 88b18d704c23e487a1fc86b3a704881d0281bb33 [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>
Kostya Serebryany66ff0752016-02-26 22:42:23 +000015#include <sys/resource.h>
Aaron Ballmanef116982015-01-29 16:58:29 +000016#include <sys/time.h>
Kostya Serebryany8b8f7a32016-05-06 23:38:07 +000017#include <sys/types.h>
18#include <sys/syscall.h>
Aaron Ballmanef116982015-01-29 16:58:29 +000019#include <cassert>
Kostya Serebryany8b8f7a32016-05-06 23:38:07 +000020#include <chrono>
Aaron Ballmanef116982015-01-29 16:58:29 +000021#include <cstring>
22#include <signal.h>
Kostya Serebryany9838b2b2015-09-03 20:23:46 +000023#include <sstream>
Kostya Serebryanyf47198a2015-05-12 22:03:34 +000024#include <unistd.h>
Dmitry Vyukov2eed1212016-03-02 09:54:40 +000025#include <errno.h>
Kostya Serebryany8b8f7a32016-05-06 23:38:07 +000026#include <thread>
Aaron Ballmanef116982015-01-29 16:58:29 +000027
28namespace fuzzer {
29
Kostya Serebryany98abb2c2016-01-13 23:46:01 +000030void PrintHexArray(const uint8_t *Data, size_t Size,
31 const char *PrintAfter) {
32 for (size_t i = 0; i < Size; i++)
33 Printf("0x%x,", (unsigned)Data[i]);
Kostya Serebryany7c180ea2015-05-23 01:22:35 +000034 Printf("%s", PrintAfter);
Aaron Ballmanef116982015-01-29 16:58:29 +000035}
36
Kostya Serebryany98abb2c2016-01-13 23:46:01 +000037void Print(const Unit &v, const char *PrintAfter) {
38 PrintHexArray(v.data(), v.size(), PrintAfter);
39}
40
Kostya Serebryany41740052016-01-12 02:36:59 +000041void PrintASCIIByte(uint8_t Byte) {
42 if (Byte == '\\')
43 Printf("\\\\");
44 else if (Byte == '"')
45 Printf("\\\"");
46 else if (Byte >= 32 && Byte < 127)
47 Printf("%c", Byte);
48 else
49 Printf("\\x%02x", Byte);
50}
51
52void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) {
53 for (size_t i = 0; i < Size; i++)
54 PrintASCIIByte(Data[i]);
55 Printf("%s", PrintAfter);
56}
57
Kostya Serebryany476f0ce2016-01-16 03:53:32 +000058void PrintASCII(const Word &W, const char *PrintAfter) {
59 PrintASCII(W.data(), W.size(), PrintAfter);
60}
61
Aaron Ballmanef116982015-01-29 16:58:29 +000062void PrintASCII(const Unit &U, const char *PrintAfter) {
Kostya Serebryany476f0ce2016-01-16 03:53:32 +000063 PrintASCII(U.data(), U.size(), PrintAfter);
Aaron Ballmanef116982015-01-29 16:58:29 +000064}
65
Kostya Serebryany96eab652015-05-14 22:41:49 +000066std::string Hash(const Unit &U) {
67 uint8_t Hash[kSHA1NumBytes];
68 ComputeSHA1(U.data(), U.size(), Hash);
69 std::stringstream SS;
70 for (int i = 0; i < kSHA1NumBytes; i++)
71 SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Hash[i];
72 return SS.str();
Aaron Ballmanef116982015-01-29 16:58:29 +000073}
74
75static void AlarmHandler(int, siginfo_t *, void *) {
Kostya Serebryany52a788e2015-03-31 20:13:20 +000076 Fuzzer::StaticAlarmCallback();
Aaron Ballmanef116982015-01-29 16:58:29 +000077}
78
Kostya Serebryany228d5b12016-03-01 22:19:21 +000079static void CrashHandler(int, siginfo_t *, void *) {
80 Fuzzer::StaticCrashSignalCallback();
81}
82
83static void InterruptHandler(int, siginfo_t *, void *) {
84 Fuzzer::StaticInterruptCallback();
85}
86
87static void SetSigaction(int signum,
88 void (*callback)(int, siginfo_t *, void *)) {
89 struct sigaction sigact;
90 memset(&sigact, 0, sizeof(sigact));
91 sigact.sa_sigaction = callback;
Dmitry Vyukov2eed1212016-03-02 09:54:40 +000092 if (sigaction(signum, &sigact, 0)) {
93 Printf("libFuzzer: sigaction failed with %d\n", errno);
94 exit(1);
95 }
Kostya Serebryany228d5b12016-03-01 22:19:21 +000096}
97
Aaron Ballmanef116982015-01-29 16:58:29 +000098void SetTimer(int Seconds) {
99 struct itimerval T {{Seconds, 0}, {Seconds, 0}};
Dmitry Vyukov2eed1212016-03-02 09:54:40 +0000100 if (setitimer(ITIMER_REAL, &T, nullptr)) {
101 Printf("libFuzzer: setitimer failed with %d\n", errno);
102 exit(1);
103 }
Kostya Serebryany228d5b12016-03-01 22:19:21 +0000104 SetSigaction(SIGALRM, AlarmHandler);
Aaron Ballmanef116982015-01-29 16:58:29 +0000105}
106
Kostya Serebryany228d5b12016-03-01 22:19:21 +0000107void SetSigSegvHandler() { SetSigaction(SIGSEGV, CrashHandler); }
108void SetSigBusHandler() { SetSigaction(SIGBUS, CrashHandler); }
109void SetSigAbrtHandler() { SetSigaction(SIGABRT, CrashHandler); }
110void SetSigIllHandler() { SetSigaction(SIGILL, CrashHandler); }
111void SetSigFpeHandler() { SetSigaction(SIGFPE, CrashHandler); }
112void SetSigIntHandler() { SetSigaction(SIGINT, InterruptHandler); }
Kostya Serebryanyf389ae12016-03-24 21:03:58 +0000113void SetSigTermHandler() { SetSigaction(SIGTERM, InterruptHandler); }
Kostya Serebryany228d5b12016-03-01 22:19:21 +0000114
Kostya Serebryany9690fcf2015-05-12 18:51:57 +0000115int NumberOfCpuCores() {
116 FILE *F = popen("nproc", "r");
117 int N = 0;
Dmitry Vyukov2eed1212016-03-02 09:54:40 +0000118 if (fscanf(F, "%d", &N) != 1)
119 N = 1;
Kostya Serebryany9690fcf2015-05-12 18:51:57 +0000120 fclose(F);
121 return N;
122}
123
Kostya Serebryanydc3135d2015-11-12 01:02:01 +0000124int ExecuteCommand(const std::string &Command) {
125 return system(Command.c_str());
Kostya Serebryany2da7b842015-05-18 21:34:20 +0000126}
127
Kostya Serebryany8a5bef02016-02-13 17:56:51 +0000128bool ToASCII(uint8_t *Data, size_t Size) {
Kostya Serebryanybc7c0ad2015-08-11 01:44:42 +0000129 bool Changed = false;
Kostya Serebryany8a5bef02016-02-13 17:56:51 +0000130 for (size_t i = 0; i < Size; i++) {
131 uint8_t &X = Data[i];
Kostya Serebryanybc7c0ad2015-08-11 01:44:42 +0000132 auto NewX = X;
133 NewX &= 127;
134 if (!isspace(NewX) && !isprint(NewX))
135 NewX = ' ';
136 Changed |= NewX != X;
137 X = NewX;
138 }
139 return Changed;
140}
141
Kostya Serebryanya9346c22015-09-02 19:08:08 +0000142bool IsASCII(const Unit &U) {
143 for (auto X : U)
144 if (!(isprint(X) || isspace(X))) return false;
145 return true;
146}
147
Kostya Serebryany9838b2b2015-09-03 20:23:46 +0000148bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) {
149 U->clear();
150 if (Str.empty()) return false;
151 size_t L = 0, R = Str.size() - 1; // We are parsing the range [L,R].
152 // Skip spaces from both sides.
153 while (L < R && isspace(Str[L])) L++;
154 while (R > L && isspace(Str[R])) R--;
155 if (R - L < 2) return false;
156 // Check the closing "
157 if (Str[R] != '"') return false;
158 R--;
159 // Find the opening "
160 while (L < R && Str[L] != '"') L++;
161 if (L >= R) return false;
162 assert(Str[L] == '\"');
163 L++;
164 assert(L <= R);
165 for (size_t Pos = L; Pos <= R; Pos++) {
166 uint8_t V = (uint8_t)Str[Pos];
167 if (!isprint(V) && !isspace(V)) return false;
168 if (V =='\\') {
169 // Handle '\\'
170 if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) {
171 U->push_back(Str[Pos + 1]);
172 Pos++;
173 continue;
174 }
175 // Handle '\xAB'
176 if (Pos + 3 <= R && Str[Pos + 1] == 'x'
177 && isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) {
178 char Hex[] = "0xAA";
179 Hex[2] = Str[Pos + 2];
180 Hex[3] = Str[Pos + 3];
181 U->push_back(strtol(Hex, nullptr, 16));
182 Pos += 3;
183 continue;
184 }
185 return false; // Invalid escape.
186 } else {
187 // Any other character.
188 U->push_back(V);
189 }
190 }
191 return true;
192}
193
194bool ParseDictionaryFile(const std::string &Text, std::vector<Unit> *Units) {
195 if (Text.empty()) {
196 Printf("ParseDictionaryFile: file does not exist or is empty\n");
197 return false;
198 }
199 std::istringstream ISS(Text);
200 Units->clear();
201 Unit U;
202 int LineNo = 0;
203 std::string S;
204 while (std::getline(ISS, S, '\n')) {
205 LineNo++;
206 size_t Pos = 0;
207 while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces.
208 if (Pos == S.size()) continue; // Empty line.
209 if (S[Pos] == '#') continue; // Comment line.
210 if (ParseOneDictionaryEntry(S, &U)) {
211 Units->push_back(U);
212 } else {
213 Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo,
214 S.c_str());
215 return false;
216 }
217 }
218 return true;
219}
220
Kostya Serebryany8b8f7a32016-05-06 23:38:07 +0000221void SleepSeconds(int Seconds) {
222 std::this_thread::sleep_for(std::chrono::seconds(Seconds));
223}
Kostya Serebryanyd6edce92015-10-16 23:04:31 +0000224
Kostya Serebryany8b8f7a32016-05-06 23:38:07 +0000225int GetPid() { return getpid(); }
226int SignalToMainThread() {
227#ifdef __linux__
228 return syscall(SYS_tgkill, GetPid(), GetPid(), SIGALRM);
229#else
230 return 0;
231#endif
232}
Kostya Serebryany9e48cda2015-12-04 22:29:39 +0000233
234std::string Base64(const Unit &U) {
235 static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
236 "abcdefghijklmnopqrstuvwxyz"
237 "0123456789+/";
238 std::string Res;
239 size_t i;
240 for (i = 0; i + 2 < U.size(); i += 3) {
241 uint32_t x = (U[i] << 16) + (U[i + 1] << 8) + U[i + 2];
242 Res += Table[(x >> 18) & 63];
243 Res += Table[(x >> 12) & 63];
244 Res += Table[(x >> 6) & 63];
245 Res += Table[x & 63];
246 }
247 if (i + 1 == U.size()) {
248 uint32_t x = (U[i] << 16);
249 Res += Table[(x >> 18) & 63];
250 Res += Table[(x >> 12) & 63];
251 Res += "==";
252 } else if (i + 2 == U.size()) {
253 uint32_t x = (U[i] << 16) + (U[i + 1] << 8);
254 Res += Table[(x >> 18) & 63];
255 Res += Table[(x >> 12) & 63];
256 Res += Table[(x >> 6) & 63];
257 Res += "=";
258 }
259 return Res;
260}
261
Kostya Serebryany66ff0752016-02-26 22:42:23 +0000262size_t GetPeakRSSMb() {
263 struct rusage usage;
264 if (getrusage(RUSAGE_SELF, &usage))
265 return 0;
266 return usage.ru_maxrss >> 10;
267}
268
Aaron Ballmanef116982015-01-29 16:58:29 +0000269} // namespace fuzzer