1 //===- FuzzerUtil.cpp - Misc utils ----------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 //===----------------------------------------------------------------------===//
12 #include "FuzzerUtil.h"
14 #include "FuzzerInternal.h"
23 #include <sys/types.h>
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);
35 void Print(const Unit &v, const char *PrintAfter) {
36 PrintHexArray(v.data(), v.size(), PrintAfter);
39 void PrintASCIIByte(uint8_t Byte) {
44 else if (Byte >= 32 && Byte < 127)
47 Printf("\\x%02x", Byte);
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);
56 void PrintASCII(const Unit &U, const char *PrintAfter) {
57 PrintASCII(U.data(), U.size(), PrintAfter);
60 bool ToASCII(uint8_t *Data, size_t Size) {
62 for (size_t i = 0; i < Size; i++) {
66 if (!isspace(NewX) && !isprint(NewX))
74 bool IsASCII(const Unit &U) { return IsASCII(U.data(), U.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;
82 bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) {
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;
94 while (L < R && Str[L] != '"') L++;
95 if (L >= R) return false;
96 assert(Str[L] == '\"');
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;
104 if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) {
105 U->push_back(Str[Pos + 1]);
110 if (Pos + 3 <= R && Str[Pos + 1] == 'x'
111 && isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) {
113 Hex[2] = Str[Pos + 2];
114 Hex[3] = Str[Pos + 3];
115 U->push_back(strtol(Hex, nullptr, 16));
119 return false; // Invalid escape.
121 // Any other character.
128 bool ParseDictionaryFile(const std::string &Text, Vector<Unit> *Units) {
130 Printf("ParseDictionaryFile: file does not exist or is empty\n");
133 std::istringstream ISS(Text);
138 while (std::getline(ISS, S, '\n')) {
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)) {
147 Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo,
155 std::string Base64(const Unit &U) {
156 static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
157 "abcdefghijklmnopqrstuvwxyz"
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];
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];
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];
183 static std::mutex SymbolizeMutex;
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.
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());
200 Printf(FallbackFMT, PC);
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();
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);
215 unsigned NumberOfCpuCores() {
216 unsigned N = std::thread::hardware_concurrency();
218 Printf("WARNING: std::thread::hardware_concurrency not well defined for "
219 "your platform. Assuming CPU count of 1.\n");
225 size_t SimpleFastHash(const uint8_t *Data, size_t Size) {
227 for (size_t i = 0; i < Size; i++)
228 Res = Res * 11 + Data[i];
232 } // namespace fuzzer