X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FFuzzer%2FFuzzerMain.cpp;h=c5af5b059091026ac0e5266ca8530a3ba72eac7d;hb=f24a5b58cd7ecc4fada221308073b9f13672d6c0;hp=e0720b41bb0db7666eaf4c4502943c02ed1a42c7;hpb=a1667be228a061de1d6d8cd2c5459710e21904e3;p=oota-llvm.git diff --git a/lib/Fuzzer/FuzzerMain.cpp b/lib/Fuzzer/FuzzerMain.cpp index e0720b41bb0..c5af5b05909 100644 --- a/lib/Fuzzer/FuzzerMain.cpp +++ b/lib/Fuzzer/FuzzerMain.cpp @@ -9,176 +9,12 @@ // main() and flags. //===----------------------------------------------------------------------===// +#include "FuzzerInterface.h" #include "FuzzerInternal.h" -#include -#include -#include -#include -#include -#include - -// ASAN options: -// * don't dump the coverage to disk. -// * enable coverage by default. -extern "C" const char *__asan_default_options() { - return "coverage_pcs=0:coverage=1"; -} - -// Program arguments. -struct FlagDescription { - const char *Name; - const char *Description; - int Default; - int *Flag; -}; - -struct { -#define FUZZER_FLAG(Type, Name, Default, Description) Type Name; -#include "FuzzerFlags.def" -#undef FUZZER_FLAG -} Flags; - -static FlagDescription FlagDescriptions [] { -#define FUZZER_FLAG(Type, Name, Default, Description) {#Name, Description, Default, &Flags.Name}, -#include "FuzzerFlags.def" -#undef FUZZER_FLAG -}; - -static const size_t kNumFlags = - sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]); - -static std::vector inputs; -static const char *ProgName; - -static void PrintHelp() { - std::cerr << "Usage: " << ProgName - << " [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n"; - std::cerr << "\nFlags: (strictly in form -flag=value)\n"; - size_t MaxFlagLen = 0; - for (size_t F = 0; F < kNumFlags; F++) - MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen); - - for (size_t F = 0; F < kNumFlags; F++) { - const auto &D = FlagDescriptions[F]; - std::cerr << " " << D.Name; - for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++) - std::cerr << " "; - std::cerr << "\t"; - std::cerr << D.Default << "\t" << D.Description << "\n"; - } -} - -static const char *FlagValue(const char *Param, const char *Name) { - size_t Len = strlen(Name); - if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 && - Param[Len + 1] == '=') - return &Param[Len + 2]; - return nullptr; -} - -static bool ParseOneFlag(const char *Param) { - if (Param[0] != '-') return false; - for (size_t F = 0; F < kNumFlags; F++) { - const char *Name = FlagDescriptions[F].Name; - const char *Str = FlagValue(Param, Name); - if (Str) { - int Val = std::stol(Str); - *FlagDescriptions[F].Flag = Val; - if (Flags.verbosity >= 2) - std::cerr << "Flag: " << Name << " " << Val << "\n"; - return true; - } - } - PrintHelp(); - exit(1); -} - -// We don't use any library to minimize dependencies. -static void ParseFlags(int argc, char **argv) { - for (size_t F = 0; F < kNumFlags; F++) - *FlagDescriptions[F].Flag = FlagDescriptions[F].Default; - for (int A = 1; A < argc; A++) { - if (ParseOneFlag(argv[A])) continue; - inputs.push_back(argv[A]); - } -} - -static void WorkerThread(const std::string &Cmd, std::atomic *Counter, - int NumJobs) { - while (true) { - int C = (*Counter)++; - if (C >= NumJobs) return; - std::string ToRun = Cmd + " > fuzz-" + std::to_string(C) + ".log 2>&1\n"; - if (Flags.verbosity) - std::cerr << ToRun; - system(ToRun.c_str()); - } -} - -static int RunInMultipleProcesses(int argc, char **argv, int NumWorkers, - int NumJobs) { - std::atomic Counter(0); - std::string Cmd; - for (int i = 0; i < argc; i++) { - if (FlagValue(argv[i], "jobs") || FlagValue(argv[i], "workers")) continue; - Cmd += argv[i]; - Cmd += " "; - } - std::vector V; - for (int i = 0; i < NumWorkers; i++) - V.push_back(std::thread(WorkerThread, Cmd, &Counter, NumJobs)); - for (auto &T : V) - T.join(); - return 0; -} +// This function should be defined by the user. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int main(int argc, char **argv) { - using namespace fuzzer; - - ProgName = argv[0]; - ParseFlags(argc, argv); - if (Flags.help) { - PrintHelp(); - return 0; - } - - if (Flags.workers > 0 && Flags.jobs > 0) - return RunInMultipleProcesses(argc, argv, Flags.workers, Flags.jobs); - - Fuzzer::FuzzingOptions Options; - Options.Verbosity = Flags.verbosity; - Options.MaxLen = Flags.max_len; - Options.DoCrossOver = Flags.cross_over; - Options.MutateDepth = Flags.mutate_depth; - Options.ExitOnFirst = Flags.exit_on_first; - Options.UseFullCoverageSet = Flags.use_full_coverage_set; - if (!inputs.empty()) - Options.OutputCorpus = inputs[0]; - Fuzzer F(Options); - - unsigned seed = Flags.seed; - // Initialize seed. - if (seed == 0) - seed = time(0) * 10000 + getpid(); - if (Flags.verbosity) - std::cerr << "Seed: " << seed << "\n"; - srand(seed); - - // Timer - if (Flags.timeout > 0) - SetTimer(Flags.timeout); - - for (auto &inp : inputs) - F.ReadDir(inp); - - if (F.CorpusSize() == 0) - F.AddToCorpus(Unit()); // Can't fuzz empty corpus, so add an empty input. - F.ShuffleAndMinimize(); - if (Flags.save_minimized_corpus) - F.SaveCorpus(); - F.Loop(Flags.iterations < 0 ? INT_MAX : Flags.iterations); - if (Flags.verbosity) - std::cerr << "Done\n"; - return 1; + return fuzzer::FuzzerDriver(argc, argv, LLVMFuzzerTestOneInput); }