go_fuzz_utils

package module
v0.0.0-...-58c38da Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 13, 2023 License: AGPL-3.0 Imports: 7 Imported by: 2

README

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)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type TypeProvider

type TypeProvider struct {
	// contains filtered or unexported fields
}

TypeProvider ingests an arbitrary byte array and uses it to extract common data types and populate structures for use in fuzzing campaigns.

func NewTypeProvider

func NewTypeProvider(data []byte) (*TypeProvider, error)

NewTypeProvider constructs a new TypeProvider instance with the provided data and default parameters. Returns the newly constructed TypeProvider.

func (*TypeProvider) Fill

func (t *TypeProvider) Fill(i interface{}) error

Fill populates data into a variable at a provided pointer. This can be used for structs or basic types. Returns an error if one is encountered.

func (*TypeProvider) GetBool

func (t *TypeProvider) GetBool() (bool, error)

GetBool obtains a bool from the current position in the buffer. This advances the position by 1. Returns the read bool, or an error if the end of stream has been reached.

func (*TypeProvider) GetByte

func (t *TypeProvider) GetByte() (byte, error)

GetByte obtains a single byte from the current position in the buffer. This advances the position by 1. Returns the single read byte, or an error if the end of stream has been reached.

func (*TypeProvider) GetBytes

func (t *TypeProvider) GetBytes() ([]byte, error)

GetBytes obtains a number of bytes of length within the range settings provided in the TypeProvider. This advances the position by len(result) Returns the read bytes, or an error if the end of stream has been reached.

func (*TypeProvider) GetFixedString

func (t *TypeProvider) GetFixedString(length int) (string, error)

GetFixedString obtains a string of the requested length from the current position in the buffer. This advances the position the provided length. Returns a string of the requested length, or an error if the end of stream has been reached.

func (*TypeProvider) GetFloat32

func (t *TypeProvider) GetFloat32() (float32, error)

GetFloat32 obtains a float32 from the current position in the buffer. This advances the position by 4. Returns the read float32, or an error if the end of stream has been reached.

func (*TypeProvider) GetFloat64

func (t *TypeProvider) GetFloat64() (float64, error)

GetFloat64 obtains a float64 from the current position in the buffer. This advances the position by 8. Returns the read float64, or an error if the end of stream has been reached.

func (*TypeProvider) GetInt

func (t *TypeProvider) GetInt() (int, error)

GetInt obtains an int from the current position in the buffer. This advances the position by 8, reading an int64 and casting it to the architecture-dependent width. Returns the read int, or an error if the end of stream has been reached.

func (*TypeProvider) GetInt16

func (t *TypeProvider) GetInt16() (int16, error)

GetInt16 obtains an int16 from the current position in the buffer. This advances the position by 2. Returns the read int16, or an error if the end of stream has been reached.

func (*TypeProvider) GetInt32

func (t *TypeProvider) GetInt32() (int32, error)

GetInt32 obtains an int32 from the current position in the buffer. This advances the position by 4. Returns the read int32, or an error if the end of stream has been reached.

func (*TypeProvider) GetInt64

func (t *TypeProvider) GetInt64() (int64, error)

GetInt64 obtains an int64 from the current position in the buffer. This advances the position by 64. Returns the read int64, or an error if the end of stream has been reached.

func (*TypeProvider) GetInt8

func (t *TypeProvider) GetInt8() (int8, error)

GetInt8 obtains an int8 from the current position in the buffer. This advances the position by 1. Returns the read int8, or an error if the end of stream has been reached.

func (*TypeProvider) GetNBytes

func (t *TypeProvider) GetNBytes(length int) ([]byte, error)

GetNBytes obtains the requested number of bytes from the current position in the buffer. This advances the position the provided length. Returns the requested bytes, or an error if the end of stream has been reached.

func (*TypeProvider) GetParamsBiases

func (t *TypeProvider) GetParamsBiases() (float32, float32, float32, float32)

GetParamsBiases obtains the bias parameters for use with Fill. Returns four floats within range [0,1] indicating the probability of: nil maps, nil pointers, nil slices, and a field being skipped when using Fill.

func (*TypeProvider) GetParamsDepthLimit

func (t *TypeProvider) GetParamsDepthLimit() int

GetParamsDepthLimit gets the depth limit parameter used when filling nested structures recursively using Fill.

func (*TypeProvider) GetParamsFillUnexportedFields

func (t *TypeProvider) GetParamsFillUnexportedFields() bool

GetParamsFillUnexportedFields gets a parameter indicating whether unexported struct fields should be filled when using Fill.

func (*TypeProvider) GetParamsMapBounds

func (t *TypeProvider) GetParamsMapBounds() (int, int)

GetParamsMapBounds obtains the minimum and maximum map size parameters for use with Fill.

func (*TypeProvider) GetParamsSliceBounds

func (t *TypeProvider) GetParamsSliceBounds() (int, int)

GetParamsSliceBounds obtains the minimum and maximum slice size parameters for use with Fill.

func (*TypeProvider) GetParamsStringBounds

func (t *TypeProvider) GetParamsStringBounds() (int, int)

GetParamsStringBounds obtains the minimum and maximum string length parameters for use with Fill.

func (*TypeProvider) GetString

func (t *TypeProvider) GetString() (string, error)

GetString obtains a string of length within the range settings provided in the TypeProvider. This advances the position by len(result) Returns the read string, or an error if the end of stream has been reached.

func (*TypeProvider) GetUint

func (t *TypeProvider) GetUint() (uint, error)

GetUint obtains an uint from the current position in the buffer. This advances the position by 8, reading an uint64 and casting it to the architecture-dependent width. Returns the read uint, or an error if the end of stream has been reached.

func (*TypeProvider) GetUint16

func (t *TypeProvider) GetUint16() (uint16, error)

GetUint16 obtains an uint16 from the current position in the buffer. This advances the position by 2. Returns the read uint16, or an error if the end of stream has been reached.

func (*TypeProvider) GetUint32

func (t *TypeProvider) GetUint32() (uint32, error)

GetUint32 obtains an uint32 from the current position in the buffer. This advances the position by 4. Returns the read uint32, or an error if the end of stream has been reached.

func (*TypeProvider) GetUint64

func (t *TypeProvider) GetUint64() (uint64, error)

GetUint64 obtains an uint64 from the current position in the buffer. This advances the position by 8. Returns the read uint64, or an error if the end of stream has been reached.

func (*TypeProvider) GetUint8

func (t *TypeProvider) GetUint8() (uint8, error)

GetUint8 obtains an uint8 from the current position in the buffer. This advances the position by 1. Returns the read uint8, or an error if the end of stream has been reached.

func (*TypeProvider) Reset

func (t *TypeProvider) Reset() error

Reset resets the position to extract data from in the stream and reconstructs the random provider with the seed read from the first few bytes. This puts the TypeProvider in the same state as when it was created, unless the underlying TypeProviderConfig was changed.

func (*TypeProvider) SetParamsBiases

func (t *TypeProvider) SetParamsBiases(mapNilBias float32, ptrNilBias float32, sliceNilBias float32, skipFieldBias float32) error

SetParamsBiases sets bias parameters for this TypeProvider, indicating the probability of nil fills or fields being skipped. Returns an error if any bias value was not within the [0,1] range.

func (*TypeProvider) SetParamsBiasesCommon

func (t *TypeProvider) SetParamsBiasesCommon(nilBias float32, skipFieldBias float32) error

SetParamsBiasesCommon sets bias parameters for this TypeProvider, indicating the probability of nil fills or fields being skipped. This differs from SetParamsBiases as it sets all nil biases from a single common value. Returns an error if any bias value was not within the [0,1] range.

func (*TypeProvider) SetParamsDepthLimit

func (t *TypeProvider) SetParamsDepthLimit(depthLimit int) error

SetParamsDepthLimit sets the depth limit when filling nested structures recursively using Fill. Setting this value to zero triggers a special case indicating infinite depth. Returns an error if the depth limit is negative.

func (*TypeProvider) SetParamsFillUnexportedFields

func (t *TypeProvider) SetParamsFillUnexportedFields(fill bool)

SetParamsFillUnexportedFields sets a parameter indicating that unexported struct fields should be filled when using Fill.

func (*TypeProvider) SetParamsMapBounds

func (t *TypeProvider) SetParamsMapBounds(minSize int, maxSize int) error

SetParamsMapBounds sets the minimum and maximum map size parameters for use with Fill. Returns an error if any argument is negative or if a minSize is larger than maxSize.

func (*TypeProvider) SetParamsSliceBounds

func (t *TypeProvider) SetParamsSliceBounds(minSize int, maxSize int) error

SetParamsSliceBounds sets the minimum and maximum slice size parameters for use with Fill. Returns an error if any argument is negative or if a minSize is larger than maxSize.

func (*TypeProvider) SetParamsStringBounds

func (t *TypeProvider) SetParamsStringBounds(minSize int, maxSize int) error

SetParamsStringBounds sets the minimum and maximum string length parameters for use with Fill. Returns an error if any argument is negative or if a minSize is larger than maxSize.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL