aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-06-27 12:34:40 +0200
committerDmitry Vyukov <dvyukov@google.com>2024-07-02 15:07:08 +0000
commit6a2ff1acbd95b320444a729d9d281835be88ec66 (patch)
tree03fd314126b66aa19341b6ec359243bb17c56688
parent3d475bc56886c8183b3189b762451095985b6c84 (diff)
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.
-rw-r--r--pkg/fuzzer/fuzzer.go12
-rw-r--r--pkg/fuzzer/job.go44
-rw-r--r--pkg/fuzzer/stats.go8
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",