Index: lib/fuzzer/FuzzerDriver.cpp =================================================================== --- lib/fuzzer/FuzzerDriver.cpp +++ lib/fuzzer/FuzzerDriver.cpp @@ -619,7 +619,8 @@ Options.PrintCorpusStats = Flags.print_corpus_stats; Options.PrintCoverage = Flags.print_coverage; Options.PrintUnstableStats = Flags.print_unstable_stats; - if (Flags.handle_unstable) + if (Flags.handle_unstable == TracePC::MinUnstable || + Flags.handle_unstable == TracePC::ZeroUnstable) Options.HandleUnstable = Flags.handle_unstable; Options.DumpCoverage = Flags.dump_coverage; if (Flags.exit_on_src_pos) Index: lib/fuzzer/FuzzerFlags.def =================================================================== --- lib/fuzzer/FuzzerFlags.def +++ lib/fuzzer/FuzzerFlags.def @@ -114,7 +114,9 @@ " Executes every input 3 times in total if a unique feature" " is found during the first execution." " If 1, we only use the minimum hit count from the 3 runs" - " to determine whether an input is interesting.") + " to determine whether an input is interesting." + " If 2, we disregard edges that are found unstable for" + " feature collection.") FUZZER_FLAG_INT(print_unstable_stats, 0, "Experimental." " If 1, print unstable statistics at exit.") FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.") Index: lib/fuzzer/FuzzerLoop.cpp =================================================================== --- lib/fuzzer/FuzzerLoop.cpp +++ lib/fuzzer/FuzzerLoop.cpp @@ -472,7 +472,8 @@ TPC.UpdateUnstableCounters(Options.HandleUnstable); // Move minimum hit counts back to ModuleInline8bitCounters - if (Options.HandleUnstable) + if (Options.HandleUnstable == TracePC::MinUnstable || + Options.HandleUnstable == TracePC::ZeroUnstable) TPC.ApplyUnstableCounters(); } Index: lib/fuzzer/FuzzerTracePC.h =================================================================== --- lib/fuzzer/FuzzerTracePC.h +++ lib/fuzzer/FuzzerTracePC.h @@ -73,6 +73,11 @@ // How many bits of PC are used from __sanitizer_cov_trace_pc. static const size_t kTracePcBits = 18; + enum HandleUnstableOptions { + MinUnstable = 1, + ZeroUnstable = 2, + }; + void HandleInit(uint32_t *Start, uint32_t *Stop); void HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop); void HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop); Index: lib/fuzzer/FuzzerTracePC.cpp =================================================================== --- lib/fuzzer/FuzzerTracePC.cpp +++ lib/fuzzer/FuzzerTracePC.cpp @@ -83,11 +83,14 @@ // and records differences as unstable edges. void TracePC::UpdateUnstableCounters(int UnstableMode) { IterateInline8bitCounters([&](int i, int j, int UnstableIdx) { - if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) + if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) { UnstableCounters[UnstableIdx].IsUnstable = true; - if (UnstableMode && - ModuleCounters[i].Start[j] < UnstableCounters[UnstableIdx].Counter) - UnstableCounters[UnstableIdx].Counter = ModuleCounters[i].Start[j]; + if (UnstableMode == ZeroUnstable) + UnstableCounters[UnstableIdx].Counter = 0; + if (UnstableMode == MinUnstable && + ModuleCounters[i].Start[j] < UnstableCounters[UnstableIdx].Counter) + UnstableCounters[UnstableIdx].Counter = ModuleCounters[i].Start[j]; + } }); } Index: test/fuzzer/handle_unstable_zerounstable.test =================================================================== --- /dev/null +++ test/fuzzer/handle_unstable_zerounstable.test @@ -0,0 +1,20 @@ +RUN: %cpp_compiler %S/PrintUnstableStatsTest.cpp -o %t-HandleUnstableZeroUnstableTest +RUN: %run %t-HandleUnstableZeroUnstableTest -print_coverage=1 -handle_unstable=2 -runs=1 2>&1 | FileCheck %s --check-prefix=UNSTABLE +UNSTABLE-NOT: ini0() +UNSTABLE-NOT: ini1() +UNSTABLE-NOT: ini2() +UNSTABLE-NOT: {{\b}}t0() +UNSTABLE-NOT: {{\b}}t1() +UNSTABLE-NOT: {{\b}}t2() +UNSTABLE-NOT: {{\b}}t3() +UNSTABLE-NOT: {{\b}}t4() + +RUN: %run %t-HandleUnstableZeroUnstableTest -print_coverage=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=NORMAL +NORMAL-DAG: ini0() +NORMAL-DAG: ini1() +NORMAL-DAG: ini2() +NORMAL-DAG: t0() +NORMAL-DAG: t1() +NORMAL-DAG: t2() +NORMAL-DAG: t3() +NORMAL-DAG: t4()