MariusVanDerWijden/filler

★ 0Forks 0GoGitHub ↗Compare

README

filler

filler turns an opaque slice of bytes — such as the input a fuzzer hands you — into populated Go values, using reflection.

Usage

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 populated

Fill 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.

With Go's native fuzzer

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
	})
}

Low-level accessors

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 size

f.UsedUp() reports whether all input bytes have been consumed at least once; f.Reset() rewinds to the start.

Extras

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.

Ethereum types preset

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.

Contributors

MariusVanDerWijden

Issues