Path: blob/main/contrib/llvm-project/compiler-rt/lib/fuzzer/FuzzerUtil.cpp
35262 views
//===- FuzzerUtil.cpp - Misc utils ----------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7// Misc utils.8//===----------------------------------------------------------------------===//910#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>2324namespace fuzzer {2526void PrintHexArray(const uint8_t *Data, size_t Size,27const char *PrintAfter) {28for (size_t i = 0; i < Size; i++)29Printf("0x%x,", (unsigned)Data[i]);30Printf("%s", PrintAfter);31}3233void Print(const Unit &v, const char *PrintAfter) {34PrintHexArray(v.data(), v.size(), PrintAfter);35}3637void PrintASCIIByte(uint8_t Byte) {38if (Byte == '\\')39Printf("\\\\");40else if (Byte == '"')41Printf("\\\"");42else if (Byte >= 32 && Byte < 127)43Printf("%c", Byte);44else45Printf("\\%03o", Byte);46}4748void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) {49for (size_t i = 0; i < Size; i++)50PrintASCIIByte(Data[i]);51Printf("%s", PrintAfter);52}5354void PrintASCII(const Unit &U, const char *PrintAfter) {55PrintASCII(U.data(), U.size(), PrintAfter);56}5758bool ToASCII(uint8_t *Data, size_t Size) {59bool Changed = false;60for (size_t i = 0; i < Size; i++) {61uint8_t &X = Data[i];62auto NewX = X;63NewX &= 127;64if (!isspace(NewX) && !isprint(NewX))65NewX = ' ';66Changed |= NewX != X;67X = NewX;68}69return Changed;70}7172bool IsASCII(const Unit &U) { return IsASCII(U.data(), U.size()); }7374bool IsASCII(const uint8_t *Data, size_t Size) {75for (size_t i = 0; i < Size; i++)76if (!(isprint(Data[i]) || isspace(Data[i]))) return false;77return true;78}7980bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) {81U->clear();82if (Str.empty()) return false;83size_t L = 0, R = Str.size() - 1; // We are parsing the range [L,R].84// Skip spaces from both sides.85while (L < R && isspace(Str[L])) L++;86while (R > L && isspace(Str[R])) R--;87if (R - L < 2) return false;88// Check the closing "89if (Str[R] != '"') return false;90R--;91// Find the opening "92while (L < R && Str[L] != '"') L++;93if (L >= R) return false;94assert(Str[L] == '\"');95L++;96assert(L <= R);97for (size_t Pos = L; Pos <= R; Pos++) {98uint8_t V = (uint8_t)Str[Pos];99if (!isprint(V) && !isspace(V)) return false;100if (V =='\\') {101// Handle '\\'102if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) {103U->push_back(Str[Pos + 1]);104Pos++;105continue;106}107// Handle '\xAB'108if (Pos + 3 <= R && Str[Pos + 1] == 'x'109&& isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) {110char Hex[] = "0xAA";111Hex[2] = Str[Pos + 2];112Hex[3] = Str[Pos + 3];113U->push_back(static_cast<uint8_t>(strtol(Hex, nullptr, 16)));114Pos += 3;115continue;116}117return false; // Invalid escape.118} else {119// Any other character.120U->push_back(V);121}122}123return true;124}125126bool ParseDictionaryFile(const std::string &Text, std::vector<Unit> *Units) {127if (Text.empty()) {128Printf("ParseDictionaryFile: file does not exist or is empty\n");129return false;130}131std::istringstream ISS(Text);132Units->clear();133Unit U;134int LineNo = 0;135std::string S;136while (std::getline(ISS, S, '\n')) {137LineNo++;138size_t Pos = 0;139while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces.140if (Pos == S.size()) continue; // Empty line.141if (S[Pos] == '#') continue; // Comment line.142if (ParseOneDictionaryEntry(S, &U)) {143Units->push_back(U);144} else {145Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo,146S.c_str());147return false;148}149}150return true;151}152153// Code duplicated (and tested) in llvm/include/llvm/Support/Base64.h154std::string Base64(const Unit &U) {155static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"156"abcdefghijklmnopqrstuvwxyz"157"0123456789+/";158std::string Buffer;159Buffer.resize(((U.size() + 2) / 3) * 4);160161size_t i = 0, j = 0;162for (size_t n = U.size() / 3 * 3; i < n; i += 3, j += 4) {163uint32_t x = ((unsigned char)U[i] << 16) | ((unsigned char)U[i + 1] << 8) |164(unsigned char)U[i + 2];165Buffer[j + 0] = Table[(x >> 18) & 63];166Buffer[j + 1] = Table[(x >> 12) & 63];167Buffer[j + 2] = Table[(x >> 6) & 63];168Buffer[j + 3] = Table[x & 63];169}170if (i + 1 == U.size()) {171uint32_t x = ((unsigned char)U[i] << 16);172Buffer[j + 0] = Table[(x >> 18) & 63];173Buffer[j + 1] = Table[(x >> 12) & 63];174Buffer[j + 2] = '=';175Buffer[j + 3] = '=';176} else if (i + 2 == U.size()) {177uint32_t x = ((unsigned char)U[i] << 16) | ((unsigned char)U[i + 1] << 8);178Buffer[j + 0] = Table[(x >> 18) & 63];179Buffer[j + 1] = Table[(x >> 12) & 63];180Buffer[j + 2] = Table[(x >> 6) & 63];181Buffer[j + 3] = '=';182}183return Buffer;184}185186static std::mutex SymbolizeMutex;187188std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) {189std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock);190if (!EF->__sanitizer_symbolize_pc || !l.owns_lock())191return "<can not symbolize>";192char PcDescr[1024] = {};193EF->__sanitizer_symbolize_pc(reinterpret_cast<void*>(PC),194SymbolizedFMT, PcDescr, sizeof(PcDescr));195PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case.196return PcDescr;197}198199void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC) {200if (EF->__sanitizer_symbolize_pc)201Printf("%s", DescribePC(SymbolizedFMT, PC).c_str());202else203Printf(FallbackFMT, PC);204}205206void PrintStackTrace() {207std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock);208if (EF->__sanitizer_print_stack_trace && l.owns_lock())209EF->__sanitizer_print_stack_trace();210}211212void PrintMemoryProfile() {213std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock);214if (EF->__sanitizer_print_memory_profile && l.owns_lock())215EF->__sanitizer_print_memory_profile(95, 8);216}217218unsigned NumberOfCpuCores() {219unsigned N = std::thread::hardware_concurrency();220if (!N) {221Printf("WARNING: std::thread::hardware_concurrency not well defined for "222"your platform. Assuming CPU count of 1.\n");223N = 1;224}225return N;226}227228uint64_t SimpleFastHash(const void *Data, size_t Size, uint64_t Initial) {229uint64_t Res = Initial;230const uint8_t *Bytes = static_cast<const uint8_t *>(Data);231for (size_t i = 0; i < Size; i++)232Res = Res * 11 + Bytes[i];233return Res;234}235236} // namespace fuzzer237238239