Index: lib/fuzzer/FuzzerDriver.cpp =================================================================== --- lib/fuzzer/FuzzerDriver.cpp +++ lib/fuzzer/FuzzerDriver.cpp @@ -614,6 +614,7 @@ Options.PrintNewCovFuncs = Flags.print_funcs; Options.PrintFinalStats = Flags.print_final_stats; Options.PrintMutationStats = Flags.print_mutation_stats; + Options.PrintMutationUsefulness = Flags.print_mutation_usefulness; Options.PrintCorpusStats = Flags.print_corpus_stats; Options.PrintCoverage = Flags.print_coverage; Options.DumpCoverage = Flags.dump_coverage; @@ -715,6 +716,8 @@ "*** executed the target code on a fixed set of inputs.\n" "***\n"); F->PrintFinalStats(); + F->PrintMutationStats(); + F->PrintMutationUsefulness(); exit(0); } @@ -762,6 +765,8 @@ Printf("Done %zd runs in %zd second(s)\n", F->getTotalNumberOfRuns(), F->secondsSinceProcessStartUp()); F->PrintFinalStats(); + F->PrintMutationStats(); + F->PrintMutationUsefulness(); exit(0); // Don't let F destroy itself. } Index: lib/fuzzer/FuzzerFlags.def =================================================================== --- lib/fuzzer/FuzzerFlags.def +++ lib/fuzzer/FuzzerFlags.def @@ -154,3 +154,4 @@ FUZZER_DEPRECATED_FLAG(use_clang_coverage) FUZZER_FLAG_STRING(data_flow_trace, "Experimental: use the data flow trace") FUZZER_FLAG_INT(print_mutation_stats, 0, "Experimental") +FUZZER_FLAG_INT(print_mutation_usefulness, 0, "Experimental") Index: lib/fuzzer/FuzzerInternal.h =================================================================== --- lib/fuzzer/FuzzerInternal.h +++ lib/fuzzer/FuzzerInternal.h @@ -80,6 +80,8 @@ void CrashResistantMergeInternalStep(const std::string &ControlFilePath); MutationDispatcher &GetMD() { return MD; } void PrintFinalStats(); + void PrintMutationStats(); + void PrintMutationUsefulness(); void SetMaxInputLen(size_t MaxInputLen); void SetMaxMutationLen(size_t MaxMutationLen); void RssLimitCallback(); Index: lib/fuzzer/FuzzerLoop.cpp =================================================================== --- lib/fuzzer/FuzzerLoop.cpp +++ lib/fuzzer/FuzzerLoop.cpp @@ -134,6 +134,8 @@ DumpCurrentUnit("oom-"); Printf("SUMMARY: libFuzzer: out-of-memory\n"); PrintFinalStats(); + PrintMutationStats(); + PrintMutationUsefulness(); _Exit(Options.ErrorExitCode); // Stop right now. } @@ -195,6 +197,8 @@ void Fuzzer::DeathCallback() { DumpCurrentUnit("crash-"); PrintFinalStats(); + PrintMutationStats(); + PrintMutationUsefulness(); } void Fuzzer::StaticAlarmCallback() { @@ -239,6 +243,8 @@ Printf("SUMMARY: libFuzzer: deadly signal\n"); DumpCurrentUnit("crash-"); PrintFinalStats(); + PrintMutationStats(); + PrintMutationUsefulness(); _Exit(Options.ErrorExitCode); // Stop right now. } @@ -253,6 +259,8 @@ Printf("SUMMARY: libFuzzer: fuzz target exited\n"); DumpCurrentUnit("crash-"); PrintFinalStats(); + PrintMutationStats(); + PrintMutationUsefulness(); _Exit(Options.ErrorExitCode); } @@ -260,12 +268,16 @@ if (!GracefulExitRequested) return; Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid()); PrintFinalStats(); + PrintMutationStats(); + PrintMutationUsefulness(); _Exit(0); } void Fuzzer::InterruptCallback() { Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid()); PrintFinalStats(); + PrintMutationStats(); + PrintMutationUsefulness(); _Exit(0); // Stop right now, don't perform any at-exit actions. } @@ -298,6 +310,8 @@ PrintStackTrace(); Printf("SUMMARY: libFuzzer: timeout\n"); PrintFinalStats(); + PrintMutationStats(); + PrintMutationUsefulness(); _Exit(Options.TimeoutExitCode); // Stop right now. } } @@ -314,6 +328,8 @@ DumpCurrentUnit("oom-"); Printf("SUMMARY: libFuzzer: out-of-memory\n"); PrintFinalStats(); + PrintMutationStats(); + PrintMutationUsefulness(); _Exit(Options.ErrorExitCode); // Stop right now. } @@ -364,11 +380,18 @@ Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded); Printf("stat::slowest_unit_time_sec: %zd\n", TimeOfLongestUnitInSeconds); Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb()); +} +void Fuzzer::PrintMutationStats() { if (Options.PrintMutationStats) MStats->PrintMutationCounts(); } +void Fuzzer::PrintMutationUsefulness() { + if (Options.PrintMutationUsefulness) + MStats->PrintMutationUsefulness(); +} + void Fuzzer::SetMaxInputLen(size_t MaxInputLen) { assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0. assert(MaxInputLen); @@ -625,6 +648,8 @@ CurrentUnitSize = Size; DumpCurrentUnit("leak-"); PrintFinalStats(); + PrintMutationStats(); + PrintMutationUsefulness(); _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on. } } @@ -835,6 +860,8 @@ DumpCurrentUnit("mismatch-"); Printf("SUMMARY: libFuzzer: equivalence-mismatch\n"); PrintFinalStats(); + PrintMutationStats(); + PrintMutationUsefulness(); _Exit(Options.ErrorExitCode); } } Index: lib/fuzzer/FuzzerMutationStats.h =================================================================== --- lib/fuzzer/FuzzerMutationStats.h +++ lib/fuzzer/FuzzerMutationStats.h @@ -19,6 +19,7 @@ void PrintMutationCounts(); void IncTotalMutationCount(MutationType MType); void IncUsefulMutationCount(MutationType MType); + void PrintMutationUsefulness(); private: // A total count of each mutation used in the fuzzing process. Index: lib/fuzzer/FuzzerMutationStats.cpp =================================================================== --- lib/fuzzer/FuzzerMutationStats.cpp +++ lib/fuzzer/FuzzerMutationStats.cpp @@ -9,31 +9,50 @@ // Mutate a test input. //===----------------------------------------------------------------------===// -#include "FuzzerMutate.h" #include "FuzzerMutationStats.h" #include "FuzzerIO.h" +#include "FuzzerMutate.h" namespace fuzzer { -MutationStats* MStats = new MutationStats(); +MutationStats *MStats = new MutationStats(); void MutationStats::PrintMutationCounts() { // Outputs the number of each mutation used - Printf("\nTotal Mutations ----------\n"); + Printf("\nstat::total_mutations: "); + for (int i = 0; i < MaxNumberOfMutationTypes; i++) { + if (i < MaxNumberOfMutationTypes-1) + Printf("%zd, ", TotalMutations.at(i)); + else + Printf("%zd", TotalMutations.at(i)); + } + + Printf("\nstat::useful_mutations: "); for (int i = 0; i < MaxNumberOfMutationTypes; i++) { - auto current = kMutationNames.find((MutationType) i); - Printf("%s: %d\n", current->second.c_str(), TotalMutations.at(i)); + if (i < MaxNumberOfMutationTypes-1) + Printf("%zd, ", UsefulMutations.at(i)); + else + Printf("%zd", UsefulMutations.at(i)); } +} - Printf("\nUseful Mutations ----------\n"); +void MutationStats::PrintMutationUsefulness() { + Printf("\nstat::mutation_usefulness: "); for (int i = 0; i < MaxNumberOfMutationTypes; i++) { - auto current = kMutationNames.find((MutationType) i); - Printf("%s: %d\n", current->second.c_str(), UsefulMutations.at(i)); + auto Current = kMutationNames.find((MutationType)i); + double CurrentRatio = + (TotalMutations.at(i) != 0) + ? (UsefulMutations.at(i) / + static_cast(TotalMutations.at(i)) * 100) + : 0; + if (i < MaxNumberOfMutationTypes-1) + Printf("%.3f, ", Current->second.c_str(), CurrentRatio); + else + Printf("%.3f", Current->second.c_str(), CurrentRatio); } + Printf("\n\n"); } -// Updates the count of mutations (total/useful) depending on type. -// Types: (0) Total, (1) Useful void MutationStats::IncTotalMutationCount(MutationType MType) { if ((MType < 0) || MType >= MaxNumberOfMutationTypes) return; @@ -48,4 +67,4 @@ UsefulMutations[MType]++; } -} // namespace fuzzer +} // namespace fuzzer Index: lib/fuzzer/FuzzerOptions.h =================================================================== --- lib/fuzzer/FuzzerOptions.h +++ lib/fuzzer/FuzzerOptions.h @@ -53,6 +53,7 @@ int PrintNewCovFuncs = 0; bool PrintFinalStats = false; bool PrintMutationStats = false; + bool PrintMutationUsefulness = false; bool PrintCorpusStats = false; bool PrintCoverage = false; bool DumpCoverage = false;