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