brintos

brintos / llvm-project-archived public Read only

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