]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.fuzz] internal/fuzz: ensure crash is written if minimization interrupted
authorJay Conrod <jayconrod@google.com>
Mon, 16 Aug 2021 23:16:51 +0000 (16:16 -0700)
committerJay Conrod <jayconrod@google.com>
Tue, 31 Aug 2021 20:28:07 +0000 (20:28 +0000)
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 <jayconrod@google.com>
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
src/internal/fuzz/fuzz.go

index b06ab146f76a02d8a45121781dfba566af17fee2..9a9a4564c241962c39f6e75a01782d972867b505 100644 (file)
@@ -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,