Skip to content

stjordanis/go-fuzz-utils

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

go-fuzz-utils

go-fuzz-utils is a helper package for use with go-fuzz or other fuzzing utilities. It provides a simple interface to produce random values for various data types and can recursively populate complex structures from raw fuzz data generated by go-fuzz. Spend more time writing property tests, and less time with ugly data type conversions, edge cases supporting full value ranges, nil cases, etc. Simply feed go-fuzz data into go-fuzz-utils to produce fuzzed objects and use them in your property tests as needed.

When populating variables, you can configure a number of parameters:

  • Minimum/maximum sizes of strings, maps, slices
  • Probability of nil for maps, slices, pointers
  • Depth limit for nested structures
  • Toggle for filling unexported fields in structures
  • Probability of skipping a field when filling (to randomly fuzz over valid structure fields)

Setup

Import this package into your go-fuzz tests:

import "github.com/trailofbits/go-fuzz-utils"

Construct a new TypeProvider using NewTypeProvider(...).

func Fuzz(data []byte) int {
	// Create a new type provider
	tp, err := go_fuzz_utils.NewTypeProvider(data)
	if err != nil {
		return 0 // not enough data was supplied, exit gracefully for the next fuzzing iteration
	}
[...]

Note: the data go-fuzz generates on some runs may be too small to construct the TypeProvider or derive all the values needed for your test. Ensure errors are handled appropriately. If one is encountered, exit gracefully to continue to the next run where more data may be produced. Fill parameters such as mapping/slice/string length and nil probability can be set using the SetParams[...] methods.

Simple data types

You can obtain the necessary type of data with exported functions such as:

	// Obtain a byte
	b, err := tp.GetByte()
...
	// Obtain a bool
	bl, err := tp.GetBool()
...
	// Obtain an int16
	i16, err := tp.GetInt16()
...
	// Obtain a float32
	f32, err := tp.GetFloat32()
...
	// Obtain a fixed-length string
	strFixed, err := tp.GetFixedString(7)
...
	// Obtain a dynamic-length string
	strDynamic, err := tp.GetString() // uses TypeProvider parameters to determine length/nil possibility
...
	// Obtain a fixed-length byte array
	bytesFixed, err := tp.GetNBytes(2)
...
	// Obtain a dynamic-length byte array
	bytesDynamic, err := tp.GetBytes() // uses TypeProvider parameters to determine length/nil possibility

Structures

go-fuzz-utils exposes a generic Fill(...) method which can populate simple data types, mappings, arrays, and arbitrary structures recursively via reflection.

For example, given the following structure:

	type Person struct {
		ID uint64
		Name string
		Photo []byte
		Employed bool
		EmergencyContact *Person
	}

You can simply perform a Fill call to populate it with the fuzz data. Even though Person has a circular reference in EmergencyContact, you can configure depth limits and nil bias settings to prevent infinite loops while giving us various deeply nested structures.

	// Create a person struct and fill it recursively. 
	var p Person
	err := tp.Fill(&p)    

Similarly, you can fill other data types as needed:

	// Create an array of mappings and fill them
	mappingArr := make([]map[string]int, 15)
	err = tp.Fill(&mappingArr)

About

No description, website, or topics provided.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 100.0%