filler turns an opaque slice of bytes — such as the input a fuzzer hands you —
into populated Go values, using reflection.
import "github.com/mariusvanderwijden/filler"
type Person struct {
Name string
Age uint8
Friends []Person
}
f := filler.NewFiller(data) // data []byte from the fuzzer
var p Person
f.Fill(&p) // p is now populatedFill only returns an error if you pass something that isn't a non-nil pointer.
It handles bools, all int/uint/float/complex widths, strings, slices, arrays,
maps, pointers and nested structs. Channels, funcs and interfaces are left at
their zero value.
Because Fill takes a plain []byte, it drops straight into go test fuzzing
for coverage-guided, struct-aware inputs:
func FuzzPerson(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
var p Person
filler.NewFiller(data).Fill(&p)
MyTarget(p) // must not panic
})
}The Filler is also useful directly as a deterministic value source:
f.Byte() // a byte
f.Bool() // a bool
f.ByteSlice(n) // n bytes
f.ByteSlice256() // 0..255 bytes, length from the data
f.Uint16/32/64() // fixed-width unsigned ints (big-endian)
f.Float32/64() // any bit pattern, including NaN/Inf
f.BigInt16/32/64/256() // *big.Int of the given bit sizef.UsedUp() reports whether all input bytes have been consumed at least once;
f.Reset() rewinds to the start.
Custom type constructors. For types the generic path can't build well (e.g.
*big.Int, or domain types like common.Address), register a constructor:
f.AddFunc(func(f *filler.Filler) *big.Int { return f.BigInt256() })
f.AddFunc(func(f *filler.Filler) common.Address {
return common.BytesToAddress(f.ByteSlice(20))
})Any value of that type encountered during Fill is produced by your function.
Skipping fields. Tag a field with fuzz:"-" to leave it untouched:
type T struct {
Data []byte
private int `fuzz:"-"`
}Unexported fields. Off by default. Enable with
f.AllowUnexportedFields() to populate unexported fields via unsafe.
The ethfiller subpackage registers constructors for common go-ethereum types
in one call. It lives in its own module so the core filler stays
dependency-free:
import "github.com/mariusvanderwijden/filler/ethfiller"
f := ethfiller.NewFiller(data) // filler.NewFiller + the geth presets
// or, onto an existing filler: ethfiller.Register(f)
var tx struct {
From common.Address
Value *big.Int
Amount *uint256.Int
ChainID *hexutil.Big
}
f.Fill(&tx)It covers common.Address, common.Hash, *big.Int, uint256.Int /
*uint256.Int, and the hexutil wrappers (Big/*Big, Uint64, Uint,
Bytes). Fixed-size array types like common.Address and types.Bloom already
fill correctly through the generic path; the preset mainly matters for
*big.Int and the hexutil.Big wrappers, whose unexported internals the
generic path can't build.