-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Description
$ go version
go version devel go1.18-7fcf9a1e58 Fri Oct 8 19:41:16 2021 +0000 linux/amd64
$ cat fuzz_test.go
package main
import (
"testing"
)
func FuzzFoo(f *testing.F) {
f.Logf("parent f.Logf")
f.Fuzz(func(t *testing.T, n uint8) {
f.Logf("child f.Logf %d", n) // I'm allowed to use f.Logf here? f.Fatalf panics.
t.Logf("child t.Logf %d", n)
if n%3 == 0 {
t.Fatal("boom")
}
})
}
If I then fuzz via go test -fuzz=. on an empty corpus, I get:
$ rm -rf testdata/fuzz && rm -rf $(go env GOCACHE)/fuzz
$ go test -fuzz=.
warning: starting with empty corpus
fuzz: elapsed: 0s, execs: 0 (0/sec), new interesting: 0 (total: 0)
fuzz: minimizing 26-byte crash input...
fuzz: elapsed: 0s, minimizing
--- FAIL: FuzzFoo (0.10s)
fuzz_test.go:8: parent f.Logf
fuzz_test.go:8: parent f.Logf
fuzz_test.go:10: child f.Logf 78
--- FAIL: FuzzFoo (0.00s)
fuzz_test.go:11: child t.Logf 78
fuzz_test.go:13: boom
fuzz_test.go:10: child f.Logf 78
--- FAIL: FuzzFoo (0.00s)
fuzz_test.go:11: child t.Logf 78
fuzz_test.go:13: boom
fuzz_test.go:10: child f.Logf 78
--- FAIL: FuzzFoo (0.00s)
fuzz_test.go:11: child t.Logf 78
fuzz_test.go:13: boom
Crash written to testdata/fuzz/FuzzFoo/eca4c171b466a632930330d73dc661bd6d35f037e8dc7f2314c1adfc855b008b
To re-run:
go test test -run=FuzzFoo/eca4c171b466a632930330d73dc661bd6d35f037e8dc7f2314c1adfc855b008b
FAIL
exit status 1
FAIL test 0.106s
I see multiple unexpected issues:
-
Note the two
parent f.Logflines. I suspect one of them is redundant. My actual fuzz func logged over a dozen times while callingf.Add, so the duplication really added a lot of noise. -
I'm kinda confused why I see three separate
--- FAIL: FuzzFooblocks, all sharing the same input78. Presumably the fuzzer should only test each input case once? If keeping track of all visited inputs or otherwise avoiding duplicates is too expensive, then at least we should be deduplicating the results being printed. To the end user, printing the same failure result more than once is unnecessary noise. -
Note how
child f.Logfis allowed and ends up being printed along withparent f.Logf. It is not allowed to callf.Fatalffrom inside the fuzz function taking a*testing.T, so I think we should similarly disallow calling anytesting.TBmethods on the parent*testing.F, such asLogf. I actually usedf.Logfinstead oft.Logfby mistake, and was very confused why my log lines ended up in the wrong position in the resulting failure output.
These are three bugs into one, apologies :) I actually only intended to file number 3, but I ran into 1 and 2 while writing the reproducer. All three issues seem small and related enough to be OK within a single thread.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status