FuzzerUtil.cpp 6.9 KB

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