1
0
mirror of https://github.com/golang/go synced 2024-11-17 12:14:47 -07:00

[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 <katie@golang.org>
Run-TryBot: Katie Hockman <katie@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
This commit is contained in:
Katie Hockman 2021-09-10 15:25:30 -04:00
parent d106089fa6
commit 17f62c0ac3
2 changed files with 49 additions and 25 deletions

View File

@ -6,18 +6,6 @@
# We clean the fuzz cache during this test. Don't clean the user's cache. # We clean the fuzz cache during this test. Don't clean the user's cache.
env GOCACHE=$WORK/gocache 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 # Test that fuzzminimizetime cannot be negative seconds
! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1ms minimizer_test.go ! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x -fuzzminimizetime=-1ms minimizer_test.go
! stdout '^ok' ! stdout '^ok'
@ -32,6 +20,20 @@ stdout FAIL
stdout 'invalid count' stdout 'invalid count'
stdout FAIL 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. # Test that minimization is working for recoverable errors.
! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x minimizer_test.go ! go test -fuzz=FuzzMinimizerRecoverable -run=FuzzMinimizerRecoverable -fuzztime=10000x minimizer_test.go
! stdout '^ok' ! stdout '^ok'
@ -87,6 +89,22 @@ import (
"testing" "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) { func FuzzMinimizerRecoverable(f *testing.F) {
f.Add(make([]byte, 100)) f.Add(make([]byte, 100))
f.Fuzz(func(t *testing.T, b []byte) { f.Fuzz(func(t *testing.T, b []byte) {

View File

@ -40,13 +40,16 @@ type CoordinateFuzzingOpts struct {
Limit int64 Limit int64
// MinimizeTimeout is the amount of wall clock time to spend minimizing // 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 MinimizeTimeout time.Duration
// MinimizeLimit is the maximum number of calls to the fuzz function to be // 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 // made while minimizing after finding a crash. If zero, there will be no
// no limit. Calls to the fuzz function made when minimizing also count // limit. Calls to the fuzz function made when minimizing also count toward
// toward Limit. // Limit. If MinimizeTimeout and MinimizeLimit are both zero, then
// minimization will be disabled.
MinimizeLimit int64 MinimizeLimit int64
// parallel is the number of worker processes to run in parallel. If zero, // 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. // generated values that workers reported as interesting.
corpus corpus corpus corpus
// typesAreMinimizable is true if one or more of the types of fuzz function's // minimizationAllowed is true if one or more of the types of fuzz
// parameters can be minimized. // function's parameters can be minimized, and either the limit or duration
typesAreMinimizable bool // for minimization is non-zero.
minimizationAllowed bool
// inputQueue is a queue of inputs that workers should try fuzzing. This is // inputQueue is a queue of inputs that workers should try fuzzing. This is
// initially populated from the seed corpus and cached inputs. More inputs // initially populated from the seed corpus and cached inputs. More inputs
@ -604,12 +608,14 @@ func newCoordinator(opts CoordinateFuzzingOpts) (*coordinator, error) {
resultC: make(chan fuzzResult), resultC: make(chan fuzzResult),
corpus: corpus, corpus: corpus,
} }
if opts.MinimizeLimit > 0 || opts.MinimizeTimeout > 0 {
for _, t := range opts.Types { for _, t := range opts.Types {
if isMinimizable(t) { if isMinimizable(t) {
c.typesAreMinimizable = true c.minimizationAllowed = true
break break
} }
} }
}
covSize := len(coverage()) covSize := len(coverage())
if covSize == 0 { if covSize == 0 {
@ -736,7 +742,7 @@ func (c *coordinator) queueForMinimization(result fuzzResult, keepCoverage []byt
// peekMinimizeInput returns the next input that should be sent to workers for // peekMinimizeInput returns the next input that should be sent to workers for
// minimization. // minimization.
func (c *coordinator) peekMinimizeInput() (fuzzMinimizeInput, bool) { 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. // Already making the maximum number of calls to the fuzz function.
// Don't send more inputs right now. // Don't send more inputs right now.
return fuzzMinimizeInput{}, false return fuzzMinimizeInput{}, false
@ -810,7 +816,7 @@ func (c *coordinator) updateCoverage(newCoverage []byte) int {
// canMinimize returns whether the coordinator should attempt to find smaller // canMinimize returns whether the coordinator should attempt to find smaller
// inputs that reproduce a crash or new coverage. // inputs that reproduce a crash or new coverage.
func (c *coordinator) canMinimize() bool { func (c *coordinator) canMinimize() bool {
return c.typesAreMinimizable && return c.minimizationAllowed &&
(c.opts.Limit == 0 || c.count+c.countWaiting < c.opts.Limit) (c.opts.Limit == 0 || c.count+c.countWaiting < c.opts.Limit)
} }