From 6a2ff1acbd95b320444a729d9d281835be88ec66 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 27 Jun 2024 12:34:40 +0200 Subject: pkg/fuzzer: optimize smash jobs 1. Run only 25 mutations during smash. 2. Run collide during normal fuzzing rather than during smashing. 3. Run hints and fault injection before random mutations and order hints/fault injection jobs. 4. Random mutations still run round-robin w/o ordering to give better diversity. --- pkg/fuzzer/fuzzer.go | 12 +++++++++--- pkg/fuzzer/job.go | 44 ++++++++++++++++++++++---------------------- pkg/fuzzer/stats.go | 8 +++++--- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/pkg/fuzzer/fuzzer.go b/pkg/fuzzer/fuzzer.go index 5b95f4eec..09ce69c00 100644 --- a/pkg/fuzzer/fuzzer.go +++ b/pkg/fuzzer/fuzzer.go @@ -67,10 +67,10 @@ func NewFuzzer(ctx context.Context, cfg *Config, rnd *rand.Rand, } type execQueues struct { - smashQueue *queue.PlainQueue - triageQueue *queue.DynamicOrderer - candidateQueue *queue.PlainQueue triageCandidateQueue *queue.DynamicOrderer + candidateQueue *queue.PlainQueue + triageQueue *queue.DynamicOrderer + smashQueue *queue.PlainQueue source queue.Source } @@ -229,6 +229,12 @@ func (fuzzer *Fuzzer) genFuzz() *queue.Request { if req == nil { req = genProgRequest(fuzzer, rnd) } + if fuzzer.Config.Collide && rnd.Intn(3) == 0 { + req = &queue.Request{ + Prog: randomCollide(req.Prog, rnd), + Stat: fuzzer.statExecCollide, + } + } fuzzer.prepare(req, 0, 0) return req } diff --git a/pkg/fuzzer/job.go b/pkg/fuzzer/job.go index 0268172a9..d1397c5b2 100644 --- a/pkg/fuzzer/job.go +++ b/pkg/fuzzer/job.go @@ -123,8 +123,21 @@ func (job *triageJob) handleCall(call int, info *triageCall) { job.fuzzer.startJob(job.fuzzer.statJobsSmash, &smashJob{ exec: job.fuzzer.smashQueue, p: p.Clone(), - call: call, }) + if job.fuzzer.Config.Comparisons && call >= 0 { + job.fuzzer.startJob(job.fuzzer.statJobsHints, &hintsJob{ + exec: job.fuzzer.smashQueue, + p: p.Clone(), + call: call, + }) + } + if job.fuzzer.Config.FaultInjection && call >= 0 { + job.fuzzer.startJob(job.fuzzer.statJobsFaultInjection, &faultInjectionJob{ + exec: job.fuzzer.smashQueue, + p: p.Clone(), + call: call, + }) + } } job.fuzzer.Logf(2, "added new input for %v to the corpus: %s", callName, p) input := corpus.NewInput{ @@ -301,15 +314,8 @@ type smashJob struct { func (job *smashJob) run(fuzzer *Fuzzer) { fuzzer.Logf(2, "smashing the program %s (call=%d):", job.p, job.call) - if fuzzer.Config.Comparisons && job.call >= 0 { - fuzzer.startJob(fuzzer.statJobsHints, &hintsJob{ - exec: fuzzer.smashQueue, - p: job.p.Clone(), - call: job.call, - }) - } - const iters = 75 + const iters = 25 rnd := fuzzer.rand() for i := 0; i < iters; i++ { p := job.p.Clone() @@ -325,18 +331,6 @@ func (job *smashJob) run(fuzzer *Fuzzer) { if result.Stop() { return } - if fuzzer.Config.Collide { - result := fuzzer.execute(job.exec, &queue.Request{ - Prog: randomCollide(p, rnd), - Stat: fuzzer.statExecCollide, - }) - if result.Stop() { - return - } - } - } - if fuzzer.Config.FaultInjection && job.call >= 0 { - job.faultInjection(fuzzer) } } @@ -362,7 +356,13 @@ func randomCollide(origP *prog.Prog, rnd *rand.Rand) *prog.Prog { return p } -func (job *smashJob) faultInjection(fuzzer *Fuzzer) { +type faultInjectionJob struct { + exec queue.Executor + p *prog.Prog + call int +} + +func (job *faultInjectionJob) run(fuzzer *Fuzzer) { for nth := 1; nth <= 100; nth++ { fuzzer.Logf(2, "injecting fault into call %v, step %v", job.call, nth) diff --git a/pkg/fuzzer/stats.go b/pkg/fuzzer/stats.go index a5df691df..db2dfd3b3 100644 --- a/pkg/fuzzer/stats.go +++ b/pkg/fuzzer/stats.go @@ -12,6 +12,7 @@ type Stats struct { statJobsTriage *stats.Val statJobsTriageCandidate *stats.Val statJobsSmash *stats.Val + statJobsFaultInjection *stats.Val statJobsHints *stats.Val statExecTime *stats.Val statExecGenerate *stats.Val @@ -36,9 +37,10 @@ func newStats() Stats { statJobsTriage: stats.Create("triage jobs", "Running triage jobs", stats.StackedGraph("jobs")), statJobsTriageCandidate: stats.Create("candidate triage jobs", "Running candidate triage jobs", stats.StackedGraph("jobs")), - statJobsSmash: stats.Create("smash jobs", "Running smash jobs", stats.StackedGraph("jobs")), - statJobsHints: stats.Create("hints jobs", "Running hints jobs", stats.StackedGraph("jobs")), - statExecTime: stats.Create("prog exec time", "Test program execution time (ms)", stats.Distribution{}), + statJobsSmash: stats.Create("smash jobs", "Running smash jobs", stats.StackedGraph("jobs")), + statJobsFaultInjection: stats.Create("fault jobs", "Running fault injection jobs", stats.StackedGraph("jobs")), + statJobsHints: stats.Create("hints jobs", "Running hints jobs", stats.StackedGraph("jobs")), + statExecTime: stats.Create("prog exec time", "Test program execution time (ms)", stats.Distribution{}), statExecGenerate: stats.Create("exec gen", "Executions of generated programs", stats.Rate{}, stats.StackedGraph("exec")), statExecFuzz: stats.Create("exec fuzz", "Executions of mutated programs", -- cgit mrf-deployment