From 61890fb1237a3d2c3be809f66dd3f831cd2cc3d2 Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Tue, 12 Oct 2021 16:45:40 -0400 Subject: [PATCH] internal/fuzz: fix -fuzzminimizetime with 'x' bug Fixes #48928 Change-Id: I3825ec615ab5fc19389ef4c10ad1042005a3761c Reviewed-on: https://go-review.googlesource.com/c/go/+/355450 Trust: Katie Hockman Run-TryBot: Katie Hockman Reviewed-by: Jay Conrod TryBot-Result: Go Bot --- .../go/testdata/script/test_fuzz_fuzztime.txt | 59 ++++++++++++++++--- src/internal/fuzz/fuzz.go | 8 ++- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt index 7d644b4d13..9c9972f9e9 100644 --- a/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt +++ b/src/cmd/go/testdata/script/test_fuzz_fuzztime.txt @@ -16,13 +16,24 @@ exec ./fuzz.test$GOEXE -test.timeout=10ms -test.fuzz=FuzzFast -test.fuzztime=5s # Timeout should not cause inputs to be written as crashers. ! exists testdata/fuzz -# When we use fuzztime with an "x" suffix, it runs a specific number of times. -# This fuzz function creates a file with a unique name ($pid.$count) on each run. -# We count the files to find the number of runs. -mkdir count env GOCACHE=$WORK/tmp -go test -fuzz=FuzzCount -fuzztime=1000x -fuzzminimizetime=1x -go run check_file_count.go 1000 + +# When we use fuzztime with an "x" suffix, it runs a specific number of times. +# This fuzz function creates a file with a unique name ($pid.$count) on each +# run. We count the files to find the number of runs. +mkdir count +go test -fuzz=FuzzTestCount -fuzztime=1000x -fuzzminimizetime=1x +go run check_file_count.go count 1000 + +# When we use fuzzminimizetime with an "x" suffix, it runs a specific number of +# times while minimizing. This fuzz function creates a file with a unique name +# ($pid.$count) on each run once the first crash has been found. That means that +# there should be one file for each execution of the fuzz function during +# minimization, so we count these to determine how many times minimization was +# run. +mkdir minimizecount +! go test -fuzz=FuzzMinimizeCount -fuzzminimizetime=3x -parallel=1 +go run check_file_count.go minimizecount 3 -- go.mod -- module fuzz @@ -45,7 +56,7 @@ import ( "testing" ) -func FuzzCount(f *testing.F) { +func FuzzTestCount(f *testing.F) { pid := os.Getpid() n := 0 f.Fuzz(func(t *testing.T, _ []byte) { @@ -56,6 +67,36 @@ func FuzzCount(f *testing.F) { n++ }) } +-- fuzz_minimize_count_test.go -- +package fuzz + +import ( + "bytes" + "fmt" + "os" + "testing" +) + +func FuzzMinimizeCount(f *testing.F) { + pid := os.Getpid() + n := 0 + seed := bytes.Repeat([]byte("a"), 357) + f.Add(seed) + crashFound := false + f.Fuzz(func(t *testing.T, b []byte) { + if crashFound { + name := fmt.Sprintf("minimizecount/%v.%d", pid, n) + if err := os.WriteFile(name, nil, 0666); err != nil { + t.Fatal(err) + } + n++ + } + if !bytes.Equal(b, seed) { // this should happen right away + crashFound = true + t.Error("minimize this!") + } + }) +} -- check_file_count.go -- // +build ignore @@ -68,13 +109,13 @@ import ( ) func main() { - dir, err := os.ReadDir("count") + dir, err := os.ReadDir(os.Args[1]) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } got := len(dir) - want, _ := strconv.Atoi(os.Args[1]) + want, _ := strconv.Atoi(os.Args[2]) if got != want { fmt.Fprintf(os.Stderr, "got %d files; want %d\n", got, want) os.Exit(1) diff --git a/src/internal/fuzz/fuzz.go b/src/internal/fuzz/fuzz.go index a8bbd60b1c..03071d5521 100644 --- a/src/internal/fuzz/fuzz.go +++ b/src/internal/fuzz/fuzz.go @@ -825,9 +825,11 @@ func (c *coordinator) peekMinimizeInput() (fuzzMinimizeInput, bool) { } } } - remaining := c.opts.Limit - c.count - c.countWaiting - if input.limit > remaining { - input.limit = remaining + if c.opts.Limit > 0 { + remaining := c.opts.Limit - c.count - c.countWaiting + if input.limit > remaining { + input.limit = remaining + } } return input, true }