-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Describe the bug
I originally sent this on the mailing list but it didn't seem to make it through moderation.
I'm experimenting with augmenting Syzkaller signal/coverage data with additional feedback metrics based upon static analysis and noticed a quirk about triageJob.minimize and triageJob.handleCall. At
Line 169 in 875573a
| p := job.p.Clone() |
triageJob.run, the program for handleCall is cloned from job.p, yet minimize still uses the original job.p here Line 354 in 875573a
| p, call := prog.Minimize(job.p, call, mode, func(p1 *prog.Prog, call1 int) bool { |
Shouldn't this use the newly cloned program p? Otherwise, if no minimizations occur from prog/minimization.go, minimize returns the original job.p.
I don't believe this causes any issues currently, but this logic doesn't seem to match the intent of the Clone.
To Reproduce
I noticed this because my experiments added some additional post-processing data to Prog as I assumed uniqueness at this point, and a race condition popped up between two handleCall goroutines that processed programs without successful minimizations (hence the same job.p)
Expected behavior
The intent of clone should be matched and minimize should use the cloned program rather than the Prog pointer from the job struct.
Additional context
Here is a sample fix:
diff --git a/pkg/fuzzer/job.go b/pkg/fuzzer/job.go
index 7b06bc97f..e0c2e9772 100644
--- a/pkg/fuzzer/job.go
+++ b/pkg/fuzzer/job.go
@@ -168,7 +168,7 @@ func (job *triageJob) handleCall(call int, info *triageCall) {
p := job.p.Clone()
if job.flags&ProgMinimized == 0 {
- p, call = job.minimize(call, info)
+ p, call = job.minimize(p, call, info)
if p == nil {
return
}
@@ -340,7 +340,7 @@ func (job *triageJob) stopDeflake(run, needRuns int, noNewSignal bool) bool {
return false
}
-func (job *triageJob) minimize(call int, info *triageCall) (*prog.Prog, int) {
+func (job *triageJob) minimize(p *prog.Prog, call int, info *triageCall) (*prog.Prog, int) {
job.info.Logf("[call #%d] minimize started", call)
minimizeAttempts := 3
if job.fuzzer.Config.Snapshot {
@@ -351,7 +351,7 @@ func (job *triageJob) minimize(call int, info *triageCall) (*prog.Prog, int) {
if job.fuzzer.Config.PatchTest {
mode = prog.MinimizeCallsOnly
}
- p, call := prog.Minimize(job.p, call, mode, func(p1 *prog.Prog, call1 int) bool {
+ p, call = prog.Minimize(p, call, mode, func(p1 *prog.Prog, call1 int) bool {
if stop {
return false
}