Go

How does native fuzzing work in Go? Write a fuzz test and explain the corpus.

Question 382HardGo 1.22 to 1.25

Since Go 1.18, func FuzzXxx(f *testing.F) defines a coverage-guided fuzz target. f.Add supplies seed inputs; f.Fuzz takes a function whose first parameter is *testing.T followed by fuzzable types: string, []byte, all int/uint sizes, float32/64, bool, rune, byte.

func FuzzRoundTrip(f *testing.F) {
    f.Add("hello")
    f.Add("")
    f.Add("日本語\x00")
    f.Fuzz(func(t *testing.T, s string) {
        enc := Encode(s)
        dec, err := Decode(enc)
        if err != nil {
            t.Fatalf("Decode(Encode(%q)) error: %v", s, err)
        }
        if dec != s {
            t.Fatalf("round trip: got %q, want %q", dec, s)
        }
    })
}
go test                                   # runs seeds + testdata corpus only (regression mode)
go test -run='^
  

 -fuzz='^FuzzRoundTrip
  

 -fuzztime=60s

Corpus: seeds from f.Add, plus files in testdata/fuzz/FuzzRoundTrip/ (commit these); generated interesting inputs are cached in $GOCACHE/fuzz. When a failure is found, the minimized input is written to testdata/fuzz/... so plain go test reproduces it forever.

Best targets are properties: round-trip, no panic on arbitrary input, equivalence with a reference implementation, invariants. Gotchas: -fuzz must match exactly one target; the fuzz function must be deterministic and fast; don't keep state between calls.

More on Performance, Profiling & Testing

All 38 Performance, Profiling & Testing questions