From: Katie Hockman Date: Fri, 10 Sep 2021 19:25:30 +0000 (-0400) Subject: [dev.fuzz] internal/fuzz: fix bug for -fuzzminimizetime of zero X-Git-Tag: go1.18beta1~1282^2~10 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=17f62c0ac3de14c3dbff77b706f86dfb7dc820c7;p=gostls13.git [dev.fuzz] internal/fuzz: fix bug for -fuzzminimizetime of zero Updates golang/go#48321 Change-Id: Ib35388f17580f1244a6eae4e5879f8329b6b44ce Reviewed-on: https://go-review.googlesource.com/c/go/+/349090 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod --- diff --git a/src/cmd/go/testdata/script/test_fuzz_minimize.txt b/src/cmd/go/testdata/script/test_fuzz_minimize.txt index dac11231ef..c180890a9b 100644 --- a/src/cmd/go/testdata/script/test_fuzz_minimize.txt +++ b/src/cmd/go/testdata/script/test_fuzz_minimize.txt @@ -6,18 +6,6 @@ # We clean the fuzz cache during this test. Don't clean the user's cache. env GOCACHE=$WORK/gocache -# Test that fuzzminimizetime can be zero seconds -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=0s minimizer_test.go -! stdout '^ok' -stdout 'contains a non-zero byte' -stdout FAIL - -# Test that fuzzminimizetime can be zero times -! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=0x minimizer_test.go -! stdout '^ok' -stdout 'contains a non-zero byte' -stdout FAIL - # Test that fuzzminimizetime cannot be negative seconds ! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1ms minimizer_test.go ! stdout '^ok' @@ -32,6 +20,20 @@ stdout FAIL stdout 'invalid count' stdout FAIL +# Test that fuzzminimizetime can be zero seconds, and minimization is disabled +! go test -fuzz=FuzzMinimizeZeroDurationSet -run=FuzzMinimizeZeroDurationSet -fuzztime=10000x -fuzzminimizetime=0s minimizer_test.go +! stdout '^ok' +! stdout 'found a crash, minimizing...' +stdout 'there was an Error' +stdout FAIL + +# Test that fuzzminimizetime can be zero times, and minimization is disabled +! go test -fuzz=FuzzMinimizeZeroLimitSet -run=FuzzMinimizeZeroLimitSet -fuzztime=10000x -fuzzminimizetime=0x minimizer_test.go +! stdout '^ok' +! stdout 'found a crash, minimizing...' +stdout 'there was an Error' +stdout FAIL + # Test that minimization is working for recoverable errors. ! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x minimizer_test.go ! stdout '^ok' @@ -87,6 +89,22 @@ import ( "testing" ) +func FuzzMinimizeZeroDurationSet(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) > 5 { + t.Errorf("there was an Error") + } + }) +} + +func FuzzMinimizeZeroLimitSet(f *testing.F) { + f.Fuzz(func(t *testing.T, b []byte) { + if len(b) > 5 { + t.Errorf("there was an Error") + } + }) +} + func FuzzMinimizerRecoverable(f *testing.F) { f.Add(make([]byte, 100)) f.Fuzz(func(t *testing.T, b []byte) { diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index 6c07da2dbe..c19ea35f23 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -40,13 +40,16 @@ type CoordinateFuzzingOpts struct { Limit int64 // MinimizeTimeout is the amount of wall clock time to spend minimizing - // after discovering a crasher. If zero, there will be no time limit. + // after discovering a crasher. If zero, there will be no time limit. If + // MinimizeTimeout and MinimizeLimit are both zero, then minimization will + // be disabled. MinimizeTimeout time.Duration // MinimizeLimit is the maximum number of calls to the fuzz function to be - // made while minimizing after finding a crash. If zero, there will be - // no limit. Calls to the fuzz function made when minimizing also count - // toward Limit. + // made while minimizing after finding a crash. If zero, there will be no + // limit. Calls to the fuzz function made when minimizing also count toward + // Limit. If MinimizeTimeout and MinimizeLimit are both zero, then + // minimization will be disabled. MinimizeLimit int64 // parallel is the number of worker processes to run in parallel. If zero, @@ -552,9 +555,10 @@ type coordinator struct { // generated values that workers reported as interesting. corpus corpus - // typesAreMinimizable is true if one or more of the types of fuzz function's - // parameters can be minimized. - typesAreMinimizable bool + // minimizationAllowed is true if one or more of the types of fuzz + // function's parameters can be minimized, and either the limit or duration + // for minimization is non-zero. + minimizationAllowed bool // inputQueue is a queue of inputs that workers should try fuzzing. This is // initially populated from the seed corpus and cached inputs. More inputs @@ -604,10 +608,12 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) { resultC: make(chan fuzzResult), corpus: corpus, } - for _, t := range opts.Types { - if isMinimizable(t) { - c.typesAreMinimizable = true - break + if opts.MinimizeLimit > 0 || opts.MinimizeTimeout > 0 { + for _, t := range opts.Types { + if isMinimizable(t) { + c.minimizationAllowed = true + break + } } } @@ -736,7 +742,7 @@ func (c *coordinator) queueForMinimization(result fuzzResult, keepCoverage []byt // peekMinimizeInput returns the next input that should be sent to workers for // minimization. func (c *coordinator) peekMinimizeInput() (fuzzMinimizeInput, bool) { - if c.opts.Limit > 0 && c.count+c.countWaiting >= c.opts.Limit { + if !c.canMinimize() { // Already making the maximum number of calls to the fuzz function. // Don't send more inputs right now. return fuzzMinimizeInput{}, false @@ -810,7 +816,7 @@ func (c *coordinator) updateCoverage(newCoverage []byte) int { // canMinimize returns whether the coordinator should attempt to find smaller // inputs that reproduce a crash or new coverage. func (c *coordinator) canMinimize() bool { - return c.typesAreMinimizable && + return c.minimizationAllowed && (c.opts.Limit == 0 || c.count+c.countWaiting < c.opts.Limit) }