1c5f01b2fSopenharmony_ci//===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===// 2c5f01b2fSopenharmony_ci// 3c5f01b2fSopenharmony_ci// The LLVM Compiler Infrastructure 4c5f01b2fSopenharmony_ci// 5c5f01b2fSopenharmony_ci// This file is distributed under the University of Illinois Open Source 6c5f01b2fSopenharmony_ci// License. See LICENSE.TXT for details. 7c5f01b2fSopenharmony_ci// 8c5f01b2fSopenharmony_ci//===----------------------------------------------------------------------===// 9c5f01b2fSopenharmony_ci// FuzzerDriver and flag parsing. 10c5f01b2fSopenharmony_ci//===----------------------------------------------------------------------===// 11c5f01b2fSopenharmony_ci 12c5f01b2fSopenharmony_ci#include "FuzzerCorpus.h" 13c5f01b2fSopenharmony_ci#include "FuzzerInterface.h" 14c5f01b2fSopenharmony_ci#include "FuzzerInternal.h" 15c5f01b2fSopenharmony_ci#include "FuzzerIO.h" 16c5f01b2fSopenharmony_ci#include "FuzzerMutate.h" 17c5f01b2fSopenharmony_ci#include "FuzzerRandom.h" 18c5f01b2fSopenharmony_ci#include "FuzzerTracePC.h" 19c5f01b2fSopenharmony_ci#include <algorithm> 20c5f01b2fSopenharmony_ci#include <atomic> 21c5f01b2fSopenharmony_ci#include <chrono> 22c5f01b2fSopenharmony_ci#include <cstring> 23c5f01b2fSopenharmony_ci#include <mutex> 24c5f01b2fSopenharmony_ci#include <string> 25c5f01b2fSopenharmony_ci#include <thread> 26c5f01b2fSopenharmony_ci 27c5f01b2fSopenharmony_ci// This function should be present in the libFuzzer so that the client 28c5f01b2fSopenharmony_ci// binary can test for its existence. 29c5f01b2fSopenharmony_ciextern "C" __attribute__((used)) void __libfuzzer_is_present() {} 30c5f01b2fSopenharmony_ci 31c5f01b2fSopenharmony_cinamespace fuzzer { 32c5f01b2fSopenharmony_ci 33c5f01b2fSopenharmony_ci// Program arguments. 34c5f01b2fSopenharmony_cistruct FlagDescription { 35c5f01b2fSopenharmony_ci const char *Name; 36c5f01b2fSopenharmony_ci const char *Description; 37c5f01b2fSopenharmony_ci int Default; 38c5f01b2fSopenharmony_ci int *IntFlag; 39c5f01b2fSopenharmony_ci const char **StrFlag; 40c5f01b2fSopenharmony_ci unsigned int *UIntFlag; 41c5f01b2fSopenharmony_ci}; 42c5f01b2fSopenharmony_ci 43c5f01b2fSopenharmony_cistruct { 44c5f01b2fSopenharmony_ci#define FUZZER_DEPRECATED_FLAG(Name) 45c5f01b2fSopenharmony_ci#define FUZZER_FLAG_INT(Name, Default, Description) int Name; 46c5f01b2fSopenharmony_ci#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) unsigned int Name; 47c5f01b2fSopenharmony_ci#define FUZZER_FLAG_STRING(Name, Description) const char *Name; 48c5f01b2fSopenharmony_ci#include "FuzzerFlags.def" 49c5f01b2fSopenharmony_ci#undef FUZZER_DEPRECATED_FLAG 50c5f01b2fSopenharmony_ci#undef FUZZER_FLAG_INT 51c5f01b2fSopenharmony_ci#undef FUZZER_FLAG_UNSIGNED 52c5f01b2fSopenharmony_ci#undef FUZZER_FLAG_STRING 53c5f01b2fSopenharmony_ci} Flags; 54c5f01b2fSopenharmony_ci 55c5f01b2fSopenharmony_cistatic const FlagDescription FlagDescriptions [] { 56c5f01b2fSopenharmony_ci#define FUZZER_DEPRECATED_FLAG(Name) \ 57c5f01b2fSopenharmony_ci {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr}, 58c5f01b2fSopenharmony_ci#define FUZZER_FLAG_INT(Name, Default, Description) \ 59c5f01b2fSopenharmony_ci {#Name, Description, Default, &Flags.Name, nullptr, nullptr}, 60c5f01b2fSopenharmony_ci#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) \ 61c5f01b2fSopenharmony_ci {#Name, Description, static_cast<int>(Default), \ 62c5f01b2fSopenharmony_ci nullptr, nullptr, &Flags.Name}, 63c5f01b2fSopenharmony_ci#define FUZZER_FLAG_STRING(Name, Description) \ 64c5f01b2fSopenharmony_ci {#Name, Description, 0, nullptr, &Flags.Name, nullptr}, 65c5f01b2fSopenharmony_ci#include "FuzzerFlags.def" 66c5f01b2fSopenharmony_ci#undef FUZZER_DEPRECATED_FLAG 67c5f01b2fSopenharmony_ci#undef FUZZER_FLAG_INT 68c5f01b2fSopenharmony_ci#undef FUZZER_FLAG_UNSIGNED 69c5f01b2fSopenharmony_ci#undef FUZZER_FLAG_STRING 70c5f01b2fSopenharmony_ci}; 71c5f01b2fSopenharmony_ci 72c5f01b2fSopenharmony_cistatic const size_t kNumFlags = 73c5f01b2fSopenharmony_ci sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]); 74c5f01b2fSopenharmony_ci 75c5f01b2fSopenharmony_cistatic std::vector<std::string> *Inputs; 76c5f01b2fSopenharmony_cistatic std::string *ProgName; 77c5f01b2fSopenharmony_ci 78c5f01b2fSopenharmony_cistatic void PrintHelp() { 79c5f01b2fSopenharmony_ci Printf("Usage:\n"); 80c5f01b2fSopenharmony_ci auto Prog = ProgName->c_str(); 81c5f01b2fSopenharmony_ci Printf("\nTo run fuzzing pass 0 or more directories.\n"); 82c5f01b2fSopenharmony_ci Printf("%s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n", Prog); 83c5f01b2fSopenharmony_ci 84c5f01b2fSopenharmony_ci Printf("\nTo run individual tests without fuzzing pass 1 or more files:\n"); 85c5f01b2fSopenharmony_ci Printf("%s [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]\n", Prog); 86c5f01b2fSopenharmony_ci 87c5f01b2fSopenharmony_ci Printf("\nFlags: (strictly in form -flag=value)\n"); 88c5f01b2fSopenharmony_ci size_t MaxFlagLen = 0; 89c5f01b2fSopenharmony_ci for (size_t F = 0; F < kNumFlags; F++) 90c5f01b2fSopenharmony_ci MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen); 91c5f01b2fSopenharmony_ci 92c5f01b2fSopenharmony_ci for (size_t F = 0; F < kNumFlags; F++) { 93c5f01b2fSopenharmony_ci const auto &D = FlagDescriptions[F]; 94c5f01b2fSopenharmony_ci if (strstr(D.Description, "internal flag") == D.Description) continue; 95c5f01b2fSopenharmony_ci Printf(" %s", D.Name); 96c5f01b2fSopenharmony_ci for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++) 97c5f01b2fSopenharmony_ci Printf(" "); 98c5f01b2fSopenharmony_ci Printf("\t"); 99c5f01b2fSopenharmony_ci Printf("%d\t%s\n", D.Default, D.Description); 100c5f01b2fSopenharmony_ci } 101c5f01b2fSopenharmony_ci Printf("\nFlags starting with '--' will be ignored and " 102c5f01b2fSopenharmony_ci "will be passed verbatim to subprocesses.\n"); 103c5f01b2fSopenharmony_ci} 104c5f01b2fSopenharmony_ci 105c5f01b2fSopenharmony_cistatic const char *FlagValue(const char *Param, const char *Name) { 106c5f01b2fSopenharmony_ci size_t Len = strlen(Name); 107c5f01b2fSopenharmony_ci if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 && 108c5f01b2fSopenharmony_ci Param[Len + 1] == '=') 109c5f01b2fSopenharmony_ci return &Param[Len + 2]; 110c5f01b2fSopenharmony_ci return nullptr; 111c5f01b2fSopenharmony_ci} 112c5f01b2fSopenharmony_ci 113c5f01b2fSopenharmony_ci// Avoid calling stol as it triggers a bug in clang/glibc build. 114c5f01b2fSopenharmony_cistatic long MyStol(const char *Str) { 115c5f01b2fSopenharmony_ci long Res = 0; 116c5f01b2fSopenharmony_ci long Sign = 1; 117c5f01b2fSopenharmony_ci if (*Str == '-') { 118c5f01b2fSopenharmony_ci Str++; 119c5f01b2fSopenharmony_ci Sign = -1; 120c5f01b2fSopenharmony_ci } 121c5f01b2fSopenharmony_ci for (size_t i = 0; Str[i]; i++) { 122c5f01b2fSopenharmony_ci char Ch = Str[i]; 123c5f01b2fSopenharmony_ci if (Ch < '0' || Ch > '9') 124c5f01b2fSopenharmony_ci return Res; 125c5f01b2fSopenharmony_ci Res = Res * 10 + (Ch - '0'); 126c5f01b2fSopenharmony_ci } 127c5f01b2fSopenharmony_ci return Res * Sign; 128c5f01b2fSopenharmony_ci} 129c5f01b2fSopenharmony_ci 130c5f01b2fSopenharmony_cistatic bool ParseOneFlag(const char *Param) { 131c5f01b2fSopenharmony_ci if (Param[0] != '-') return false; 132c5f01b2fSopenharmony_ci if (Param[1] == '-') { 133c5f01b2fSopenharmony_ci static bool PrintedWarning = false; 134c5f01b2fSopenharmony_ci if (!PrintedWarning) { 135c5f01b2fSopenharmony_ci PrintedWarning = true; 136c5f01b2fSopenharmony_ci Printf("INFO: libFuzzer ignores flags that start with '--'\n"); 137c5f01b2fSopenharmony_ci } 138c5f01b2fSopenharmony_ci for (size_t F = 0; F < kNumFlags; F++) 139c5f01b2fSopenharmony_ci if (FlagValue(Param + 1, FlagDescriptions[F].Name)) 140c5f01b2fSopenharmony_ci Printf("WARNING: did you mean '%s' (single dash)?\n", Param + 1); 141c5f01b2fSopenharmony_ci return true; 142c5f01b2fSopenharmony_ci } 143c5f01b2fSopenharmony_ci for (size_t F = 0; F < kNumFlags; F++) { 144c5f01b2fSopenharmony_ci const char *Name = FlagDescriptions[F].Name; 145c5f01b2fSopenharmony_ci const char *Str = FlagValue(Param, Name); 146c5f01b2fSopenharmony_ci if (Str) { 147c5f01b2fSopenharmony_ci if (FlagDescriptions[F].IntFlag) { 148c5f01b2fSopenharmony_ci int Val = MyStol(Str); 149c5f01b2fSopenharmony_ci *FlagDescriptions[F].IntFlag = Val; 150c5f01b2fSopenharmony_ci if (Flags.verbosity >= 2) 151c5f01b2fSopenharmony_ci Printf("Flag: %s %d\n", Name, Val); 152c5f01b2fSopenharmony_ci return true; 153c5f01b2fSopenharmony_ci } else if (FlagDescriptions[F].UIntFlag) { 154c5f01b2fSopenharmony_ci unsigned int Val = std::stoul(Str); 155c5f01b2fSopenharmony_ci *FlagDescriptions[F].UIntFlag = Val; 156c5f01b2fSopenharmony_ci if (Flags.verbosity >= 2) 157c5f01b2fSopenharmony_ci Printf("Flag: %s %u\n", Name, Val); 158c5f01b2fSopenharmony_ci return true; 159c5f01b2fSopenharmony_ci } else if (FlagDescriptions[F].StrFlag) { 160c5f01b2fSopenharmony_ci *FlagDescriptions[F].StrFlag = Str; 161c5f01b2fSopenharmony_ci if (Flags.verbosity >= 2) 162c5f01b2fSopenharmony_ci Printf("Flag: %s %s\n", Name, Str); 163c5f01b2fSopenharmony_ci return true; 164c5f01b2fSopenharmony_ci } else { // Deprecated flag. 165c5f01b2fSopenharmony_ci Printf("Flag: %s: deprecated, don't use\n", Name); 166c5f01b2fSopenharmony_ci return true; 167c5f01b2fSopenharmony_ci } 168c5f01b2fSopenharmony_ci } 169c5f01b2fSopenharmony_ci } 170c5f01b2fSopenharmony_ci Printf("\n\nWARNING: unrecognized flag '%s'; " 171c5f01b2fSopenharmony_ci "use -help=1 to list all flags\n\n", Param); 172c5f01b2fSopenharmony_ci return true; 173c5f01b2fSopenharmony_ci} 174c5f01b2fSopenharmony_ci 175c5f01b2fSopenharmony_ci// We don't use any library to minimize dependencies. 176c5f01b2fSopenharmony_cistatic void ParseFlags(const std::vector<std::string> &Args) { 177c5f01b2fSopenharmony_ci for (size_t F = 0; F < kNumFlags; F++) { 178c5f01b2fSopenharmony_ci if (FlagDescriptions[F].IntFlag) 179c5f01b2fSopenharmony_ci *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default; 180c5f01b2fSopenharmony_ci if (FlagDescriptions[F].UIntFlag) 181c5f01b2fSopenharmony_ci *FlagDescriptions[F].UIntFlag = 182c5f01b2fSopenharmony_ci static_cast<unsigned int>(FlagDescriptions[F].Default); 183c5f01b2fSopenharmony_ci if (FlagDescriptions[F].StrFlag) 184c5f01b2fSopenharmony_ci *FlagDescriptions[F].StrFlag = nullptr; 185c5f01b2fSopenharmony_ci } 186c5f01b2fSopenharmony_ci Inputs = new std::vector<std::string>; 187c5f01b2fSopenharmony_ci for (size_t A = 1; A < Args.size(); A++) { 188c5f01b2fSopenharmony_ci if (ParseOneFlag(Args[A].c_str())) continue; 189c5f01b2fSopenharmony_ci Inputs->push_back(Args[A]); 190c5f01b2fSopenharmony_ci } 191c5f01b2fSopenharmony_ci} 192c5f01b2fSopenharmony_ci 193c5f01b2fSopenharmony_cistatic std::mutex Mu; 194c5f01b2fSopenharmony_ci 195c5f01b2fSopenharmony_cistatic void PulseThread() { 196c5f01b2fSopenharmony_ci while (true) { 197c5f01b2fSopenharmony_ci SleepSeconds(600); 198c5f01b2fSopenharmony_ci std::lock_guard<std::mutex> Lock(Mu); 199c5f01b2fSopenharmony_ci Printf("pulse...\n"); 200c5f01b2fSopenharmony_ci } 201c5f01b2fSopenharmony_ci} 202c5f01b2fSopenharmony_ci 203c5f01b2fSopenharmony_cistatic void WorkerThread(const std::string &Cmd, std::atomic<unsigned> *Counter, 204c5f01b2fSopenharmony_ci unsigned NumJobs, std::atomic<bool> *HasErrors) { 205c5f01b2fSopenharmony_ci while (true) { 206c5f01b2fSopenharmony_ci unsigned C = (*Counter)++; 207c5f01b2fSopenharmony_ci if (C >= NumJobs) break; 208c5f01b2fSopenharmony_ci std::string Log = "fuzz-" + std::to_string(C) + ".log"; 209c5f01b2fSopenharmony_ci std::string ToRun = Cmd + " > " + Log + " 2>&1\n"; 210c5f01b2fSopenharmony_ci if (Flags.verbosity) 211c5f01b2fSopenharmony_ci Printf("%s", ToRun.c_str()); 212c5f01b2fSopenharmony_ci int ExitCode = ExecuteCommand(ToRun); 213c5f01b2fSopenharmony_ci if (ExitCode != 0) 214c5f01b2fSopenharmony_ci *HasErrors = true; 215c5f01b2fSopenharmony_ci std::lock_guard<std::mutex> Lock(Mu); 216c5f01b2fSopenharmony_ci Printf("================== Job %u exited with exit code %d ============\n", 217c5f01b2fSopenharmony_ci C, ExitCode); 218c5f01b2fSopenharmony_ci fuzzer::CopyFileToErr(Log); 219c5f01b2fSopenharmony_ci } 220c5f01b2fSopenharmony_ci} 221c5f01b2fSopenharmony_ci 222c5f01b2fSopenharmony_cistd::string CloneArgsWithoutX(const std::vector<std::string> &Args, 223c5f01b2fSopenharmony_ci const char *X1, const char *X2) { 224c5f01b2fSopenharmony_ci std::string Cmd; 225c5f01b2fSopenharmony_ci for (auto &S : Args) { 226c5f01b2fSopenharmony_ci if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2)) 227c5f01b2fSopenharmony_ci continue; 228c5f01b2fSopenharmony_ci Cmd += S + " "; 229c5f01b2fSopenharmony_ci } 230c5f01b2fSopenharmony_ci return Cmd; 231c5f01b2fSopenharmony_ci} 232c5f01b2fSopenharmony_ci 233c5f01b2fSopenharmony_cistatic int RunInMultipleProcesses(const std::vector<std::string> &Args, 234c5f01b2fSopenharmony_ci unsigned NumWorkers, unsigned NumJobs) { 235c5f01b2fSopenharmony_ci std::atomic<unsigned> Counter(0); 236c5f01b2fSopenharmony_ci std::atomic<bool> HasErrors(false); 237c5f01b2fSopenharmony_ci std::string Cmd = CloneArgsWithoutX(Args, "jobs", "workers"); 238c5f01b2fSopenharmony_ci std::vector<std::thread> V; 239c5f01b2fSopenharmony_ci std::thread Pulse(PulseThread); 240c5f01b2fSopenharmony_ci Pulse.detach(); 241c5f01b2fSopenharmony_ci for (unsigned i = 0; i < NumWorkers; i++) 242c5f01b2fSopenharmony_ci V.push_back(std::thread(WorkerThread, Cmd, &Counter, NumJobs, &HasErrors)); 243c5f01b2fSopenharmony_ci for (auto &T : V) 244c5f01b2fSopenharmony_ci T.join(); 245c5f01b2fSopenharmony_ci return HasErrors ? 1 : 0; 246c5f01b2fSopenharmony_ci} 247c5f01b2fSopenharmony_ci 248c5f01b2fSopenharmony_cistatic void RssThread(Fuzzer *F, size_t RssLimitMb) { 249c5f01b2fSopenharmony_ci while (true) { 250c5f01b2fSopenharmony_ci SleepSeconds(1); 251c5f01b2fSopenharmony_ci size_t Peak = GetPeakRSSMb(); 252c5f01b2fSopenharmony_ci if (Peak > RssLimitMb) 253c5f01b2fSopenharmony_ci F->RssLimitCallback(); 254c5f01b2fSopenharmony_ci } 255c5f01b2fSopenharmony_ci} 256c5f01b2fSopenharmony_ci 257c5f01b2fSopenharmony_cistatic void StartRssThread(Fuzzer *F, size_t RssLimitMb) { 258c5f01b2fSopenharmony_ci if (!RssLimitMb) return; 259c5f01b2fSopenharmony_ci std::thread T(RssThread, F, RssLimitMb); 260c5f01b2fSopenharmony_ci T.detach(); 261c5f01b2fSopenharmony_ci} 262c5f01b2fSopenharmony_ci 263c5f01b2fSopenharmony_ciint RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) { 264c5f01b2fSopenharmony_ci Unit U = FileToVector(InputFilePath); 265c5f01b2fSopenharmony_ci if (MaxLen && MaxLen < U.size()) 266c5f01b2fSopenharmony_ci U.resize(MaxLen); 267c5f01b2fSopenharmony_ci F->RunOne(U.data(), U.size()); 268c5f01b2fSopenharmony_ci F->TryDetectingAMemoryLeak(U.data(), U.size(), true); 269c5f01b2fSopenharmony_ci return 0; 270c5f01b2fSopenharmony_ci} 271c5f01b2fSopenharmony_ci 272c5f01b2fSopenharmony_cistatic bool AllInputsAreFiles() { 273c5f01b2fSopenharmony_ci if (Inputs->empty()) return false; 274c5f01b2fSopenharmony_ci for (auto &Path : *Inputs) 275c5f01b2fSopenharmony_ci if (!IsFile(Path)) 276c5f01b2fSopenharmony_ci return false; 277c5f01b2fSopenharmony_ci return true; 278c5f01b2fSopenharmony_ci} 279c5f01b2fSopenharmony_ci 280c5f01b2fSopenharmony_ciint MinimizeCrashInput(const std::vector<std::string> &Args) { 281c5f01b2fSopenharmony_ci if (Inputs->size() != 1) { 282c5f01b2fSopenharmony_ci Printf("ERROR: -minimize_crash should be given one input file\n"); 283c5f01b2fSopenharmony_ci exit(1); 284c5f01b2fSopenharmony_ci } 285c5f01b2fSopenharmony_ci std::string InputFilePath = Inputs->at(0); 286c5f01b2fSopenharmony_ci std::string BaseCmd = 287c5f01b2fSopenharmony_ci CloneArgsWithoutX(Args, "minimize_crash", "exact_artifact_path"); 288c5f01b2fSopenharmony_ci auto InputPos = BaseCmd.find(" " + InputFilePath + " "); 289c5f01b2fSopenharmony_ci assert(InputPos != std::string::npos); 290c5f01b2fSopenharmony_ci BaseCmd.erase(InputPos, InputFilePath.size() + 1); 291c5f01b2fSopenharmony_ci if (Flags.runs <= 0 && Flags.max_total_time == 0) { 292c5f01b2fSopenharmony_ci Printf("INFO: you need to specify -runs=N or " 293c5f01b2fSopenharmony_ci "-max_total_time=N with -minimize_crash=1\n" 294c5f01b2fSopenharmony_ci "INFO: defaulting to -max_total_time=600\n"); 295c5f01b2fSopenharmony_ci BaseCmd += " -max_total_time=600"; 296c5f01b2fSopenharmony_ci } 297c5f01b2fSopenharmony_ci // BaseCmd += " > /dev/null 2>&1 "; 298c5f01b2fSopenharmony_ci 299c5f01b2fSopenharmony_ci std::string CurrentFilePath = InputFilePath; 300c5f01b2fSopenharmony_ci while (true) { 301c5f01b2fSopenharmony_ci Unit U = FileToVector(CurrentFilePath); 302c5f01b2fSopenharmony_ci if (U.size() < 2) { 303c5f01b2fSopenharmony_ci Printf("CRASH_MIN: '%s' is small enough\n", CurrentFilePath.c_str()); 304c5f01b2fSopenharmony_ci return 0; 305c5f01b2fSopenharmony_ci } 306c5f01b2fSopenharmony_ci Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n", 307c5f01b2fSopenharmony_ci CurrentFilePath.c_str(), U.size()); 308c5f01b2fSopenharmony_ci 309c5f01b2fSopenharmony_ci auto Cmd = BaseCmd + " " + CurrentFilePath; 310c5f01b2fSopenharmony_ci 311c5f01b2fSopenharmony_ci Printf("CRASH_MIN: executing: %s\n", Cmd.c_str()); 312c5f01b2fSopenharmony_ci int ExitCode = ExecuteCommand(Cmd); 313c5f01b2fSopenharmony_ci if (ExitCode == 0) { 314c5f01b2fSopenharmony_ci Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str()); 315c5f01b2fSopenharmony_ci exit(1); 316c5f01b2fSopenharmony_ci } 317c5f01b2fSopenharmony_ci Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize " 318c5f01b2fSopenharmony_ci "it further\n", 319c5f01b2fSopenharmony_ci CurrentFilePath.c_str(), U.size()); 320c5f01b2fSopenharmony_ci 321c5f01b2fSopenharmony_ci std::string ArtifactPath = "minimized-from-" + Hash(U); 322c5f01b2fSopenharmony_ci Cmd += " -minimize_crash_internal_step=1 -exact_artifact_path=" + 323c5f01b2fSopenharmony_ci ArtifactPath; 324c5f01b2fSopenharmony_ci Printf("CRASH_MIN: executing: %s\n", Cmd.c_str()); 325c5f01b2fSopenharmony_ci ExitCode = ExecuteCommand(Cmd); 326c5f01b2fSopenharmony_ci if (ExitCode == 0) { 327c5f01b2fSopenharmony_ci if (Flags.exact_artifact_path) { 328c5f01b2fSopenharmony_ci CurrentFilePath = Flags.exact_artifact_path; 329c5f01b2fSopenharmony_ci WriteToFile(U, CurrentFilePath); 330c5f01b2fSopenharmony_ci } 331c5f01b2fSopenharmony_ci Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n", 332c5f01b2fSopenharmony_ci CurrentFilePath.c_str(), U.size()); 333c5f01b2fSopenharmony_ci return 0; 334c5f01b2fSopenharmony_ci } 335c5f01b2fSopenharmony_ci CurrentFilePath = ArtifactPath; 336c5f01b2fSopenharmony_ci Printf("\n\n\n\n\n\n*********************************\n"); 337c5f01b2fSopenharmony_ci } 338c5f01b2fSopenharmony_ci return 0; 339c5f01b2fSopenharmony_ci} 340c5f01b2fSopenharmony_ci 341c5f01b2fSopenharmony_ciint MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) { 342c5f01b2fSopenharmony_ci assert(Inputs->size() == 1); 343c5f01b2fSopenharmony_ci std::string InputFilePath = Inputs->at(0); 344c5f01b2fSopenharmony_ci Unit U = FileToVector(InputFilePath); 345c5f01b2fSopenharmony_ci assert(U.size() > 2); 346c5f01b2fSopenharmony_ci Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size()); 347c5f01b2fSopenharmony_ci Corpus->AddToCorpus(U, 0); 348c5f01b2fSopenharmony_ci F->SetMaxInputLen(U.size()); 349c5f01b2fSopenharmony_ci F->SetMaxMutationLen(U.size() - 1); 350c5f01b2fSopenharmony_ci F->MinimizeCrashLoop(U); 351c5f01b2fSopenharmony_ci Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n"); 352c5f01b2fSopenharmony_ci exit(0); 353c5f01b2fSopenharmony_ci return 0; 354c5f01b2fSopenharmony_ci} 355c5f01b2fSopenharmony_ci 356c5f01b2fSopenharmony_ciint FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { 357c5f01b2fSopenharmony_ci using namespace fuzzer; 358c5f01b2fSopenharmony_ci assert(argc && argv && "Argument pointers cannot be nullptr"); 359c5f01b2fSopenharmony_ci EF = new ExternalFunctions(); 360c5f01b2fSopenharmony_ci if (EF->LLVMFuzzerInitialize) 361c5f01b2fSopenharmony_ci EF->LLVMFuzzerInitialize(argc, argv); 362c5f01b2fSopenharmony_ci const std::vector<std::string> Args(*argv, *argv + *argc); 363c5f01b2fSopenharmony_ci assert(!Args.empty()); 364c5f01b2fSopenharmony_ci ProgName = new std::string(Args[0]); 365c5f01b2fSopenharmony_ci ParseFlags(Args); 366c5f01b2fSopenharmony_ci if (Flags.help) { 367c5f01b2fSopenharmony_ci PrintHelp(); 368c5f01b2fSopenharmony_ci return 0; 369c5f01b2fSopenharmony_ci } 370c5f01b2fSopenharmony_ci 371c5f01b2fSopenharmony_ci if (Flags.minimize_crash) 372c5f01b2fSopenharmony_ci return MinimizeCrashInput(Args); 373c5f01b2fSopenharmony_ci 374c5f01b2fSopenharmony_ci if (Flags.close_fd_mask & 2) 375c5f01b2fSopenharmony_ci DupAndCloseStderr(); 376c5f01b2fSopenharmony_ci if (Flags.close_fd_mask & 1) 377c5f01b2fSopenharmony_ci CloseStdout(); 378c5f01b2fSopenharmony_ci 379c5f01b2fSopenharmony_ci if (Flags.jobs > 0 && Flags.workers == 0) { 380c5f01b2fSopenharmony_ci Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs); 381c5f01b2fSopenharmony_ci if (Flags.workers > 1) 382c5f01b2fSopenharmony_ci Printf("Running %u workers\n", Flags.workers); 383c5f01b2fSopenharmony_ci } 384c5f01b2fSopenharmony_ci 385c5f01b2fSopenharmony_ci if (Flags.workers > 0 && Flags.jobs > 0) 386c5f01b2fSopenharmony_ci return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs); 387c5f01b2fSopenharmony_ci 388c5f01b2fSopenharmony_ci const size_t kMaxSaneLen = 1 << 20; 389c5f01b2fSopenharmony_ci const size_t kMinDefaultLen = 64; 390c5f01b2fSopenharmony_ci FuzzingOptions Options; 391c5f01b2fSopenharmony_ci Options.Verbosity = Flags.verbosity; 392c5f01b2fSopenharmony_ci Options.MaxLen = Flags.max_len; 393c5f01b2fSopenharmony_ci Options.UnitTimeoutSec = Flags.timeout; 394c5f01b2fSopenharmony_ci Options.ErrorExitCode = Flags.error_exitcode; 395c5f01b2fSopenharmony_ci Options.TimeoutExitCode = Flags.timeout_exitcode; 396c5f01b2fSopenharmony_ci Options.MaxTotalTimeSec = Flags.max_total_time; 397c5f01b2fSopenharmony_ci Options.DoCrossOver = Flags.cross_over; 398c5f01b2fSopenharmony_ci Options.MutateDepth = Flags.mutate_depth; 399c5f01b2fSopenharmony_ci Options.UseCounters = Flags.use_counters; 400c5f01b2fSopenharmony_ci Options.UseIndirCalls = Flags.use_indir_calls; 401c5f01b2fSopenharmony_ci Options.UseMemcmp = Flags.use_memcmp; 402c5f01b2fSopenharmony_ci Options.UseMemmem = Flags.use_memmem; 403c5f01b2fSopenharmony_ci Options.UseCmp = Flags.use_cmp; 404c5f01b2fSopenharmony_ci Options.UseValueProfile = Flags.use_value_profile; 405c5f01b2fSopenharmony_ci Options.Shrink = Flags.shrink; 406c5f01b2fSopenharmony_ci Options.ShuffleAtStartUp = Flags.shuffle; 407c5f01b2fSopenharmony_ci Options.PreferSmall = Flags.prefer_small; 408c5f01b2fSopenharmony_ci Options.ReloadIntervalSec = Flags.reload; 409c5f01b2fSopenharmony_ci Options.OnlyASCII = Flags.only_ascii; 410c5f01b2fSopenharmony_ci Options.OutputCSV = Flags.output_csv; 411c5f01b2fSopenharmony_ci Options.DetectLeaks = Flags.detect_leaks; 412c5f01b2fSopenharmony_ci Options.TraceMalloc = Flags.trace_malloc; 413c5f01b2fSopenharmony_ci Options.RssLimitMb = Flags.rss_limit_mb; 414c5f01b2fSopenharmony_ci if (Flags.runs >= 0) 415c5f01b2fSopenharmony_ci Options.MaxNumberOfRuns = Flags.runs; 416c5f01b2fSopenharmony_ci if (!Inputs->empty() && !Flags.minimize_crash_internal_step) 417c5f01b2fSopenharmony_ci Options.OutputCorpus = (*Inputs)[0]; 418c5f01b2fSopenharmony_ci Options.ReportSlowUnits = Flags.report_slow_units; 419c5f01b2fSopenharmony_ci if (Flags.artifact_prefix) 420c5f01b2fSopenharmony_ci Options.ArtifactPrefix = Flags.artifact_prefix; 421c5f01b2fSopenharmony_ci if (Flags.exact_artifact_path) 422c5f01b2fSopenharmony_ci Options.ExactArtifactPath = Flags.exact_artifact_path; 423c5f01b2fSopenharmony_ci std::vector<Unit> Dictionary; 424c5f01b2fSopenharmony_ci if (Flags.dict) 425c5f01b2fSopenharmony_ci if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary)) 426c5f01b2fSopenharmony_ci return 1; 427c5f01b2fSopenharmony_ci if (Flags.verbosity > 0 && !Dictionary.empty()) 428c5f01b2fSopenharmony_ci Printf("Dictionary: %zd entries\n", Dictionary.size()); 429c5f01b2fSopenharmony_ci bool DoPlainRun = AllInputsAreFiles(); 430c5f01b2fSopenharmony_ci Options.SaveArtifacts = 431c5f01b2fSopenharmony_ci !DoPlainRun || Flags.minimize_crash_internal_step; 432c5f01b2fSopenharmony_ci Options.PrintNewCovPcs = Flags.print_pcs; 433c5f01b2fSopenharmony_ci Options.PrintFinalStats = Flags.print_final_stats; 434c5f01b2fSopenharmony_ci Options.PrintCorpusStats = Flags.print_corpus_stats; 435c5f01b2fSopenharmony_ci Options.PrintCoverage = Flags.print_coverage; 436c5f01b2fSopenharmony_ci Options.DumpCoverage = Flags.dump_coverage; 437c5f01b2fSopenharmony_ci if (Flags.exit_on_src_pos) 438c5f01b2fSopenharmony_ci Options.ExitOnSrcPos = Flags.exit_on_src_pos; 439c5f01b2fSopenharmony_ci if (Flags.exit_on_item) 440c5f01b2fSopenharmony_ci Options.ExitOnItem = Flags.exit_on_item; 441c5f01b2fSopenharmony_ci 442c5f01b2fSopenharmony_ci unsigned Seed = Flags.seed; 443c5f01b2fSopenharmony_ci // Initialize Seed. 444c5f01b2fSopenharmony_ci if (Seed == 0) 445c5f01b2fSopenharmony_ci Seed = (std::chrono::system_clock::now().time_since_epoch().count() << 10) + 446c5f01b2fSopenharmony_ci GetPid(); 447c5f01b2fSopenharmony_ci if (Flags.verbosity) 448c5f01b2fSopenharmony_ci Printf("INFO: Seed: %u\n", Seed); 449c5f01b2fSopenharmony_ci 450c5f01b2fSopenharmony_ci Random Rand(Seed); 451c5f01b2fSopenharmony_ci auto *MD = new MutationDispatcher(Rand, Options); 452c5f01b2fSopenharmony_ci auto *Corpus = new InputCorpus(Options.OutputCorpus); 453c5f01b2fSopenharmony_ci auto *F = new Fuzzer(Callback, *Corpus, *MD, Options); 454c5f01b2fSopenharmony_ci 455c5f01b2fSopenharmony_ci for (auto &U: Dictionary) 456c5f01b2fSopenharmony_ci if (U.size() <= Word::GetMaxSize()) 457c5f01b2fSopenharmony_ci MD->AddWordToManualDictionary(Word(U.data(), U.size())); 458c5f01b2fSopenharmony_ci 459c5f01b2fSopenharmony_ci StartRssThread(F, Flags.rss_limit_mb); 460c5f01b2fSopenharmony_ci 461c5f01b2fSopenharmony_ci Options.HandleAbrt = Flags.handle_abrt; 462c5f01b2fSopenharmony_ci Options.HandleBus = Flags.handle_bus; 463c5f01b2fSopenharmony_ci Options.HandleFpe = Flags.handle_fpe; 464c5f01b2fSopenharmony_ci Options.HandleIll = Flags.handle_ill; 465c5f01b2fSopenharmony_ci Options.HandleInt = Flags.handle_int; 466c5f01b2fSopenharmony_ci Options.HandleSegv = Flags.handle_segv; 467c5f01b2fSopenharmony_ci Options.HandleTerm = Flags.handle_term; 468c5f01b2fSopenharmony_ci SetSignalHandler(Options); 469c5f01b2fSopenharmony_ci 470c5f01b2fSopenharmony_ci if (Flags.minimize_crash_internal_step) 471c5f01b2fSopenharmony_ci return MinimizeCrashInputInternalStep(F, Corpus); 472c5f01b2fSopenharmony_ci 473c5f01b2fSopenharmony_ci if (DoPlainRun) { 474c5f01b2fSopenharmony_ci Options.SaveArtifacts = false; 475c5f01b2fSopenharmony_ci int Runs = std::max(1, Flags.runs); 476c5f01b2fSopenharmony_ci Printf("%s: Running %zd inputs %d time(s) each.\n", ProgName->c_str(), 477c5f01b2fSopenharmony_ci Inputs->size(), Runs); 478c5f01b2fSopenharmony_ci for (auto &Path : *Inputs) { 479c5f01b2fSopenharmony_ci auto StartTime = system_clock::now(); 480c5f01b2fSopenharmony_ci Printf("Running: %s\n", Path.c_str()); 481c5f01b2fSopenharmony_ci for (int Iter = 0; Iter < Runs; Iter++) 482c5f01b2fSopenharmony_ci RunOneTest(F, Path.c_str(), Options.MaxLen); 483c5f01b2fSopenharmony_ci auto StopTime = system_clock::now(); 484c5f01b2fSopenharmony_ci auto MS = duration_cast<milliseconds>(StopTime - StartTime).count(); 485c5f01b2fSopenharmony_ci Printf("Executed %s in %zd ms\n", Path.c_str(), (long)MS); 486c5f01b2fSopenharmony_ci } 487c5f01b2fSopenharmony_ci Printf("***\n" 488c5f01b2fSopenharmony_ci "*** NOTE: fuzzing was not performed, you have only\n" 489c5f01b2fSopenharmony_ci "*** executed the target code on a fixed set of inputs.\n" 490c5f01b2fSopenharmony_ci "***\n"); 491c5f01b2fSopenharmony_ci F->PrintFinalStats(); 492c5f01b2fSopenharmony_ci exit(0); 493c5f01b2fSopenharmony_ci } 494c5f01b2fSopenharmony_ci 495c5f01b2fSopenharmony_ci if (Flags.merge) { 496c5f01b2fSopenharmony_ci if (Options.MaxLen == 0) 497c5f01b2fSopenharmony_ci F->SetMaxInputLen(kMaxSaneLen); 498c5f01b2fSopenharmony_ci if (TPC.UsingTracePcGuard()) { 499c5f01b2fSopenharmony_ci if (Flags.merge_control_file) 500c5f01b2fSopenharmony_ci F->CrashResistantMergeInternalStep(Flags.merge_control_file); 501c5f01b2fSopenharmony_ci else 502c5f01b2fSopenharmony_ci F->CrashResistantMerge(Args, *Inputs); 503c5f01b2fSopenharmony_ci } else { 504c5f01b2fSopenharmony_ci F->Merge(*Inputs); 505c5f01b2fSopenharmony_ci } 506c5f01b2fSopenharmony_ci exit(0); 507c5f01b2fSopenharmony_ci } 508c5f01b2fSopenharmony_ci 509c5f01b2fSopenharmony_ci size_t TemporaryMaxLen = Options.MaxLen ? Options.MaxLen : kMaxSaneLen; 510c5f01b2fSopenharmony_ci 511c5f01b2fSopenharmony_ci UnitVector InitialCorpus; 512c5f01b2fSopenharmony_ci for (auto &Inp : *Inputs) { 513c5f01b2fSopenharmony_ci Printf("Loading corpus dir: %s\n", Inp.c_str()); 514c5f01b2fSopenharmony_ci ReadDirToVectorOfUnits(Inp.c_str(), &InitialCorpus, nullptr, 515c5f01b2fSopenharmony_ci TemporaryMaxLen, /*ExitOnError=*/false); 516c5f01b2fSopenharmony_ci } 517c5f01b2fSopenharmony_ci 518c5f01b2fSopenharmony_ci if (Options.MaxLen == 0) { 519c5f01b2fSopenharmony_ci size_t MaxLen = 0; 520c5f01b2fSopenharmony_ci for (auto &U : InitialCorpus) 521c5f01b2fSopenharmony_ci MaxLen = std::max(U.size(), MaxLen); 522c5f01b2fSopenharmony_ci F->SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxLen), kMaxSaneLen)); 523c5f01b2fSopenharmony_ci } 524c5f01b2fSopenharmony_ci 525c5f01b2fSopenharmony_ci if (InitialCorpus.empty()) { 526c5f01b2fSopenharmony_ci InitialCorpus.push_back(Unit({'\n'})); // Valid ASCII input. 527c5f01b2fSopenharmony_ci if (Options.Verbosity) 528c5f01b2fSopenharmony_ci Printf("INFO: A corpus is not provided, starting from an empty corpus\n"); 529c5f01b2fSopenharmony_ci } 530c5f01b2fSopenharmony_ci F->ShuffleAndMinimize(&InitialCorpus); 531c5f01b2fSopenharmony_ci InitialCorpus.clear(); // Don't need this memory any more. 532c5f01b2fSopenharmony_ci F->Loop(); 533c5f01b2fSopenharmony_ci 534c5f01b2fSopenharmony_ci if (Flags.verbosity) 535c5f01b2fSopenharmony_ci Printf("Done %d runs in %zd second(s)\n", F->getTotalNumberOfRuns(), 536c5f01b2fSopenharmony_ci F->secondsSinceProcessStartUp()); 537c5f01b2fSopenharmony_ci F->PrintFinalStats(); 538c5f01b2fSopenharmony_ci 539c5f01b2fSopenharmony_ci exit(0); // Don't let F destroy itself. 540c5f01b2fSopenharmony_ci} 541c5f01b2fSopenharmony_ci 542c5f01b2fSopenharmony_ci// Storage for global ExternalFunctions object. 543c5f01b2fSopenharmony_ciExternalFunctions *EF = nullptr; 544c5f01b2fSopenharmony_ci 545c5f01b2fSopenharmony_ci} // namespace fuzzer 546