From 18c288ef8b8a3e7d2c02d3bb4c06e9f7c006b9da Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Mon, 16 Aug 2021 16:16:51 -0700 Subject: [PATCH] [dev.fuzz] internal/fuzz: ensure crash is written if minimization interrupted If any error occurs when minimizing a crash, for example, the user presses ^C because minimization is taking too long, the coordinator will now write the unminimized crash to testdata. Change-Id: I0c754125781eb184846e496c728e0505a28639d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/342995 Trust: Jay Conrod Trust: Katie Hockman Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/internal/fuzz/fuzz.go | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index b06ab146f7..9a9a4564c2 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -133,6 +133,27 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err inputC = nil } + // Ensure that any crash we find is written to the corpus, even if an error + // or interruption occurs while minimizing it. + var crashMinimizing *fuzzResult + crashWritten := false + defer func() { + if crashMinimizing == nil || crashWritten { + return + } + fileName, werr := writeToCorpus(crashMinimizing.entry.Data, opts.CorpusDir) + if werr != nil { + err = fmt.Errorf("%w\n%v", err, werr) + return + } + if err == nil { + err = &crashError{ + name: filepath.Base(fileName), + err: errors.New(crashMinimizing.crasherMsg), + } + } + }() + // Start workers. // TODO(jayconrod): do we want to support fuzzing different binaries? dir := "" // same as self @@ -175,8 +196,6 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err statTicker := time.NewTicker(3 * time.Second) defer statTicker.Stop() defer c.logStats() - crashMinimizing := false - crashWritten := false for { select { @@ -194,7 +213,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err if result.crasherMsg != "" { if c.canMinimize() && !result.minimizeAttempted { - if crashMinimizing { + if crashMinimizing != nil { // This crash is not minimized, and another crash is being minimized. // Ignore this one and wait for the other one to finish. break @@ -202,7 +221,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err // Found a crasher but haven't yet attempted to minimize it. // Send it back to a worker for minimization. Disable inputC so // other workers don't continue fuzzing. - crashMinimizing = true + crashMinimizing = &result inputC = nil fmt.Fprintf(c.opts.Log, "found a crash, minimizing...\n") c.minimizeC <- c.minimizeInputForResult(result) @@ -304,7 +323,7 @@ func CoordinateFuzzing(ctx context.Context, opts CoordinateFuzzingOpts) (err err } } } - if inputC == nil && !crashMinimizing && !stopping && !c.coverageOnlyRun() { + if inputC == nil && crashMinimizing == nil && !stopping && !c.coverageOnlyRun() { // Re-enable inputC if it was disabled earlier because we hit the limit // on the number of inputs to fuzz (nextInput returned false). Workers // can do less work than requested, so after receiving a result above, -- 2.50.0