go.mod: github.com/AdaLogics/go-fuzz-headers v0.0.0-20221118232415-3345c89a7c72

full diff: 443f56ff4b...3345c89a7c

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2022-11-20 21:59:44 +01:00
parent df4d07352d
commit 0f616e3549
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
8 changed files with 226 additions and 319 deletions

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/containerd/containerd
go 1.18 go 1.18
require ( require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20221103172237-443f56ff4ba8 github.com/AdaLogics/go-fuzz-headers v0.0.0-20221118232415-3345c89a7c72
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b
github.com/Microsoft/go-winio v0.6.0 github.com/Microsoft/go-winio v0.6.0
github.com/Microsoft/hcsshim v0.10.0-rc.1 github.com/Microsoft/hcsshim v0.10.0-rc.1

4
go.sum
View File

@ -44,8 +44,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20221103172237-443f56ff4ba8 h1:d+pBUmsteW5tM87xmVXHZ4+LibHRFn40SPAoZJOg2ak= github.com/AdaLogics/go-fuzz-headers v0.0.0-20221118232415-3345c89a7c72 h1:kq78byqmxX6R9uk4uN3HD2F5tkZJAZMauuLSkNPS8to=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20221103172237-443f56ff4ba8/go.mod h1:i9fr2JpcEcY/IHEvzCM3qXUZYOQHgR89dt4es1CgMhc= github.com/AdaLogics/go-fuzz-headers v0.0.0-20221118232415-3345c89a7c72/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b h1:RQhYYLDVbdN+fw4I+A90nMRcxg/tEg4KvHiDYOwY32g= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b h1:RQhYYLDVbdN+fw4I+A90nMRcxg/tEg4KvHiDYOwY32g=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b/go.mod h1:P/MhpyNnqWUWlF8b/ksNuhU2kywD3Qc5fzauL06Gez8= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b/go.mod h1:P/MhpyNnqWUWlF8b/ksNuhU2kywD3Qc5fzauL06Gez8=
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=

View File

@ -20,7 +20,7 @@ require (
) )
require ( require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20221103172237-443f56ff4ba8 github.com/AdaLogics/go-fuzz-headers v0.0.0-20221118232415-3345c89a7c72
github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774 github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774
) )

View File

@ -363,8 +363,8 @@ cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vf
cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20220824214621-3c06a36a6952/go.mod h1:i9fr2JpcEcY/IHEvzCM3qXUZYOQHgR89dt4es1CgMhc= github.com/AdaLogics/go-fuzz-headers v0.0.0-20220824214621-3c06a36a6952/go.mod h1:i9fr2JpcEcY/IHEvzCM3qXUZYOQHgR89dt4es1CgMhc=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20221103172237-443f56ff4ba8 h1:d+pBUmsteW5tM87xmVXHZ4+LibHRFn40SPAoZJOg2ak= github.com/AdaLogics/go-fuzz-headers v0.0.0-20221118232415-3345c89a7c72 h1:kq78byqmxX6R9uk4uN3HD2F5tkZJAZMauuLSkNPS8to=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20221103172237-443f56ff4ba8/go.mod h1:i9fr2JpcEcY/IHEvzCM3qXUZYOQHgR89dt4es1CgMhc= github.com/AdaLogics/go-fuzz-headers v0.0.0-20221118232415-3345c89a7c72/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b h1:RQhYYLDVbdN+fw4I+A90nMRcxg/tEg4KvHiDYOwY32g= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b h1:RQhYYLDVbdN+fw4I+A90nMRcxg/tEg4KvHiDYOwY32g=
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b/go.mod h1:P/MhpyNnqWUWlF8b/ksNuhU2kywD3Qc5fzauL06Gez8= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b/go.mod h1:P/MhpyNnqWUWlF8b/ksNuhU2kywD3Qc5fzauL06Gez8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=

View File

@ -18,9 +18,7 @@ import (
securejoin "github.com/cyphar/filepath-securejoin" securejoin "github.com/cyphar/filepath-securejoin"
) )
var ( var MaxTotalLen uint32 = 2000000
MaxTotalLen = uint32(2000000)
)
func SetMaxTotalLen(newLen uint32) { func SetMaxTotalLen(newLen uint32) {
MaxTotalLen = newLen MaxTotalLen = newLen
@ -28,6 +26,7 @@ func SetMaxTotalLen(newLen uint32) {
type ConsumeFuzzer struct { type ConsumeFuzzer struct {
data []byte data []byte
dataTotal uint32
CommandPart []byte CommandPart []byte
RestOfArray []byte RestOfArray []byte
NumberOfCalls int NumberOfCalls int
@ -41,22 +40,23 @@ func IsDivisibleBy(n int, divisibleby int) bool {
} }
func NewConsumer(fuzzData []byte) *ConsumeFuzzer { func NewConsumer(fuzzData []byte) *ConsumeFuzzer {
fuzzMap := make(map[reflect.Type]reflect.Value) return &ConsumeFuzzer{
f := &ConsumeFuzzer{data: fuzzData, position: 0, Funcs: fuzzMap} data: fuzzData,
return f dataTotal: uint32(len(fuzzData)),
Funcs: make(map[reflect.Type]reflect.Value),
}
} }
func (f *ConsumeFuzzer) Split(minCalls, maxCalls int) error { func (f *ConsumeFuzzer) Split(minCalls, maxCalls int) error {
if len(f.data) == 0 { if f.dataTotal == 0 {
return errors.New("Could not split") return errors.New("could not split")
} }
numberOfCalls := int(f.data[0]) numberOfCalls := int(f.data[0])
if numberOfCalls < minCalls || numberOfCalls > maxCalls { if numberOfCalls < minCalls || numberOfCalls > maxCalls {
return errors.New("Bad number of calls") return errors.New("bad number of calls")
} }
if len(f.data) < numberOfCalls+numberOfCalls+1 { if int(f.dataTotal) < numberOfCalls+numberOfCalls+1 {
return errors.New("Length of data does not match required parameters") return errors.New("length of data does not match required parameters")
} }
// Define part 2 and 3 of the data array // Define part 2 and 3 of the data array
@ -65,12 +65,12 @@ func (f *ConsumeFuzzer) Split(minCalls, maxCalls int) error {
// Just a small check. It is necessary // Just a small check. It is necessary
if len(commandPart) != numberOfCalls { if len(commandPart) != numberOfCalls {
return errors.New("Length of commandPart does not match number of calls") return errors.New("length of commandPart does not match number of calls")
} }
// Check if restOfArray is divisible by numberOfCalls // Check if restOfArray is divisible by numberOfCalls
if !IsDivisibleBy(len(restOfArray), numberOfCalls) { if !IsDivisibleBy(len(restOfArray), numberOfCalls) {
return errors.New("Length of commandPart does not match number of calls") return errors.New("length of commandPart does not match number of calls")
} }
f.CommandPart = commandPart f.CommandPart = commandPart
f.RestOfArray = restOfArray f.RestOfArray = restOfArray
@ -87,77 +87,55 @@ func (f *ConsumeFuzzer) DisallowUnexportedFields() {
} }
func (f *ConsumeFuzzer) GenerateStruct(targetStruct interface{}) error { func (f *ConsumeFuzzer) GenerateStruct(targetStruct interface{}) error {
v := reflect.ValueOf(targetStruct) e := reflect.ValueOf(targetStruct).Elem()
/*if !v.CanSet() { return f.fuzzStruct(e, false)
return errors.New("This interface cannot be set")
}*/
e := v.Elem()
err := f.fuzzStruct(e, false)
if err != nil {
return err
}
return nil
} }
func (f *ConsumeFuzzer) setCustom(v reflect.Value) error { func (f *ConsumeFuzzer) setCustom(v reflect.Value) error {
// First: see if we have a fuzz function for it. // First: see if we have a fuzz function for it.
doCustom, ok := f.Funcs[v.Type()] doCustom, ok := f.Funcs[v.Type()]
if !ok { if !ok {
return fmt.Errorf("Could not find a custom function") return fmt.Errorf("could not find a custom function")
} }
switch v.Kind() { switch v.Kind() {
case reflect.Ptr: case reflect.Ptr:
if v.IsNil() { if v.IsNil() {
if !v.CanSet() { if !v.CanSet() {
return fmt.Errorf("Could not use a custom function") return fmt.Errorf("could not use a custom function")
} }
v.Set(reflect.New(v.Type().Elem())) v.Set(reflect.New(v.Type().Elem()))
} }
case reflect.Map: case reflect.Map:
if v.IsNil() { if v.IsNil() {
if !v.CanSet() { if !v.CanSet() {
return fmt.Errorf("Could not use a custom function") return fmt.Errorf("could not use a custom function")
} }
v.Set(reflect.MakeMap(v.Type())) v.Set(reflect.MakeMap(v.Type()))
} }
default: default:
return fmt.Errorf("Could not use a custom function") return fmt.Errorf("could not use a custom function")
} }
verr := doCustom.Call([]reflect.Value{v, reflect.ValueOf(Continue{ verr := doCustom.Call([]reflect.Value{v, reflect.ValueOf(Continue{
F: f, F: f,
})}) })})
// check if we return an error // check if we return an error
if verr[0].IsNil() { if verr[0].IsNil() {
return nil return nil
} }
return fmt.Errorf("Could not use a custom function") return fmt.Errorf("could not use a custom function")
} }
func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value, customFunctions bool) error { func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value, customFunctions bool) error {
// We check if we should check for custom functions // We check if we should check for custom functions
if customFunctions { if customFunctions && e.IsValid() && e.CanAddr() {
if e.IsValid() {
if e.CanAddr() {
err := f.setCustom(e.Addr()) err := f.setCustom(e.Addr())
if err == nil { if err == nil {
return nil return nil
} }
} }
/* return f.setCustom(e)
_, ok := f.Funcs[e.Type()]
if ok {
if e.CanAddr() {
err := f.setCustom(e.Addr())
if err == nil {
return nil
}
}*/
//return f.setCustom(e)
}
}
switch e.Kind() { switch e.Kind() {
case reflect.Struct: case reflect.Struct:
@ -167,24 +145,14 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value, customFunctions bool) error
if f.fuzzUnexportedFields { if f.fuzzUnexportedFields {
v = reflect.NewAt(e.Field(i).Type(), unsafe.Pointer(e.Field(i).UnsafeAddr())).Elem() v = reflect.NewAt(e.Field(i).Type(), unsafe.Pointer(e.Field(i).UnsafeAddr())).Elem()
} }
err := f.fuzzStruct(v, customFunctions) if err := f.fuzzStruct(v, customFunctions); err != nil {
if err != nil {
return err return err
} }
} else { } else {
/*if e.Field(i).Kind() == reflect.Struct {
//e = reflect.NewAt(e.Type(), unsafe.Pointer(e.UnsafeAddr())).Elem()
//e.Field(i).Set(reflect.New(e.Field(i).Type()))
}*/
v = e.Field(i) v = e.Field(i)
//v = reflect.New(e.Field(i).Type()) if err := f.fuzzStruct(v, customFunctions); err != nil {
err := f.fuzzStruct(v, customFunctions)
if err != nil {
return err return err
} }
/*if e.Field(i).CanSet() {
e.Field(i).Set(v.Elem())
}*/
} }
} }
case reflect.String: case reflect.String:
@ -208,18 +176,16 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value, customFunctions bool) error
if err != nil { if err != nil {
return err return err
} }
var numOfElements uint32 numOfElements := randQty % maxElements
numOfElements = randQty % maxElements if (f.dataTotal - f.position) < numOfElements {
if (uint32(len(f.data)) - f.position) < numOfElements { numOfElements = f.dataTotal - f.position
numOfElements = uint32(len(f.data)) - f.position
} }
uu := reflect.MakeSlice(e.Type(), int(numOfElements), int(numOfElements)) uu := reflect.MakeSlice(e.Type(), int(numOfElements), int(numOfElements))
for i := 0; i < int(numOfElements); i++ { for i := 0; i < int(numOfElements); i++ {
err := f.fuzzStruct(uu.Index(i), customFunctions)
// If we have more than 10, then we can proceed with that. // If we have more than 10, then we can proceed with that.
if err != nil { if err := f.fuzzStruct(uu.Index(i), customFunctions); err != nil {
if i >= 10 { if i >= 10 {
if e.CanSet() { if e.CanSet() {
e.Set(uu) e.Set(uu)
@ -284,7 +250,7 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value, customFunctions bool) error
case reflect.Map: case reflect.Map:
if e.CanSet() { if e.CanSet() {
e.Set(reflect.MakeMap(e.Type())) e.Set(reflect.MakeMap(e.Type()))
maxElements := 50 const maxElements = 50
randQty, err := f.GetInt() randQty, err := f.GetInt()
if err != nil { if err != nil {
return err return err
@ -292,13 +258,11 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value, customFunctions bool) error
numOfElements := randQty % maxElements numOfElements := randQty % maxElements
for i := 0; i < numOfElements; i++ { for i := 0; i < numOfElements; i++ {
key := reflect.New(e.Type().Key()).Elem() key := reflect.New(e.Type().Key()).Elem()
err := f.fuzzStruct(key, customFunctions) if err := f.fuzzStruct(key, customFunctions); err != nil {
if err != nil {
return err return err
} }
val := reflect.New(e.Type().Elem()).Elem() val := reflect.New(e.Type().Elem()).Elem()
err = f.fuzzStruct(val, customFunctions) if err = f.fuzzStruct(val, customFunctions); err != nil {
if err != nil {
return err return err
} }
e.SetMapIndex(key, val) e.SetMapIndex(key, val)
@ -307,8 +271,7 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value, customFunctions bool) error
case reflect.Ptr: case reflect.Ptr:
if e.CanSet() { if e.CanSet() {
e.Set(reflect.New(e.Type().Elem())) e.Set(reflect.New(e.Type().Elem()))
err := f.fuzzStruct(e.Elem(), customFunctions) if err := f.fuzzStruct(e.Elem(), customFunctions); err != nil {
if err != nil {
return err return err
} }
return nil return nil
@ -321,43 +284,39 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value, customFunctions bool) error
if e.CanSet() { if e.CanSet() {
e.SetUint(uint64(b)) e.SetUint(uint64(b))
} }
default:
return nil
} }
return nil return nil
} }
func (f *ConsumeFuzzer) GetStringArray() (reflect.Value, error) { func (f *ConsumeFuzzer) GetStringArray() (reflect.Value, error) {
// The max size of the array: // The max size of the array:
max := uint32(20) const max uint32 = 20
arraySize := f.position arraySize := f.position
if arraySize > max { if arraySize > max {
arraySize = max arraySize = max
} }
elemType := reflect.TypeOf("string") stringArray := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf("string")), int(arraySize), int(arraySize))
stringArray := reflect.MakeSlice(reflect.SliceOf(elemType), int(arraySize), int(arraySize)) if f.position+arraySize >= f.dataTotal {
if f.position+arraySize >= uint32(len(f.data)) { return stringArray, errors.New("could not make string array")
return stringArray, errors.New("Could not make string array")
} }
for i := 0; i < int(arraySize); i++ { for i := 0; i < int(arraySize); i++ {
stringSize := uint32(f.data[f.position]) stringSize := uint32(f.data[f.position])
if f.position+stringSize >= f.dataTotal {
if f.position+stringSize >= uint32(len(f.data)) {
return stringArray, nil return stringArray, nil
} }
stringToAppend := string(f.data[f.position : f.position+stringSize]) stringToAppend := string(f.data[f.position : f.position+stringSize])
strVal := reflect.ValueOf(stringToAppend) strVal := reflect.ValueOf(stringToAppend)
stringArray = reflect.Append(stringArray, strVal) stringArray = reflect.Append(stringArray, strVal)
f.position = f.position + stringSize f.position += stringSize
} }
return stringArray, nil return stringArray, nil
} }
func (f *ConsumeFuzzer) GetInt() (int, error) { func (f *ConsumeFuzzer) GetInt() (int, error) {
if f.position >= uint32(len(f.data)) { if f.position >= f.dataTotal {
return 0, errors.New("Not enough bytes to create int") return 0, errors.New("not enough bytes to create int")
} }
returnInt := int(f.data[f.position]) returnInt := int(f.data[f.position])
f.position++ f.position++
@ -365,29 +324,23 @@ func (f *ConsumeFuzzer) GetInt() (int, error) {
} }
func (f *ConsumeFuzzer) GetByte() (byte, error) { func (f *ConsumeFuzzer) GetByte() (byte, error) {
if len(f.data) == 0 { if f.position >= f.dataTotal {
return 0x00, errors.New("Not enough bytes to get byte") return 0x00, errors.New("not enough bytes to get byte")
}
if f.position >= uint32(len(f.data)) {
return 0x00, errors.New("Not enough bytes to get byte")
} }
returnByte := f.data[f.position] returnByte := f.data[f.position]
f.position += 1 f.position++
return returnByte, nil return returnByte, nil
} }
func (f *ConsumeFuzzer) GetNBytes(numberOfBytes int) ([]byte, error) { func (f *ConsumeFuzzer) GetNBytes(numberOfBytes int) ([]byte, error) {
returnBytes := make([]byte, 0) if f.position >= f.dataTotal {
if len(f.data) == 0 { return nil, errors.New("not enough bytes to get byte")
return returnBytes, errors.New("Not enough bytes to get byte")
}
if f.position >= uint32(len(f.data)) {
return returnBytes, errors.New("Not enough bytes to get byte")
} }
returnBytes := make([]byte, 0, numberOfBytes)
for i := 0; i < numberOfBytes; i++ { for i := 0; i < numberOfBytes; i++ {
newByte, err := f.GetByte() newByte, err := f.GetByte()
if err != nil { if err != nil {
return returnBytes, err return nil, err
} }
returnBytes = append(returnBytes, newByte) returnBytes = append(returnBytes, newByte)
} }
@ -397,112 +350,104 @@ func (f *ConsumeFuzzer) GetNBytes(numberOfBytes int) ([]byte, error) {
func (f *ConsumeFuzzer) GetUint16() (uint16, error) { func (f *ConsumeFuzzer) GetUint16() (uint16, error) {
u16, err := f.GetNBytes(2) u16, err := f.GetNBytes(2)
if err != nil { if err != nil {
return uint16(0), err return 0, err
} }
littleEndian, err := f.GetBool() littleEndian, err := f.GetBool()
if err != nil { if err != nil {
return uint16(0), err return 0, err
} }
if littleEndian { if littleEndian {
u16LE := binary.LittleEndian.Uint16(u16) return binary.LittleEndian.Uint16(u16), nil
return u16LE, nil
} }
u16BE := binary.BigEndian.Uint16(u16) return binary.BigEndian.Uint16(u16), nil
return u16BE, nil
} }
func (f *ConsumeFuzzer) GetUint32() (uint32, error) { func (f *ConsumeFuzzer) GetUint32() (uint32, error) {
u32, err := f.GetNBytes(4) u32, err := f.GetNBytes(4)
if err != nil { if err != nil {
return uint32(0), err return 0, err
} }
littleEndian, err := f.GetBool() littleEndian, err := f.GetBool()
if err != nil { if err != nil {
return uint32(0), err return 0, err
} }
if littleEndian { if littleEndian {
u32LE := binary.LittleEndian.Uint32(u32) return binary.LittleEndian.Uint32(u32), nil
return u32LE, nil
} }
u32BE := binary.BigEndian.Uint32(u32) return binary.BigEndian.Uint32(u32), nil
return u32BE, nil
} }
func (f *ConsumeFuzzer) GetUint64() (uint64, error) { func (f *ConsumeFuzzer) GetUint64() (uint64, error) {
u64, err := f.GetNBytes(8) u64, err := f.GetNBytes(8)
if err != nil { if err != nil {
return uint64(0), err return 0, err
} }
littleEndian, err := f.GetBool() littleEndian, err := f.GetBool()
if err != nil { if err != nil {
return uint64(0), err return 0, err
} }
if littleEndian { if littleEndian {
u64LE := binary.LittleEndian.Uint64(u64) return binary.LittleEndian.Uint64(u64), nil
return u64LE, nil
} }
u64BE := binary.BigEndian.Uint64(u64) return binary.BigEndian.Uint64(u64), nil
return u64BE, nil
} }
func (f *ConsumeFuzzer) GetBytes() ([]byte, error) { func (f *ConsumeFuzzer) GetBytes() ([]byte, error) {
if len(f.data) == 0 || f.position >= uint32(len(f.data)) { if f.position >= f.dataTotal {
return nil, errors.New("Not enough bytes to create byte array") return nil, errors.New("not enough bytes to create byte array")
} }
length, err := f.GetUint32() length, err := f.GetUint32()
if err != nil { if err != nil {
return nil, errors.New("Not enough bytes to create byte array") return nil, errors.New("not enough bytes to create byte array")
} }
if f.position+length > MaxTotalLen { if f.position+length > MaxTotalLen {
return nil, errors.New("Created too large a string") return nil, errors.New("created too large a string")
} }
byteBegin := f.position - 1 byteBegin := f.position - 1
if byteBegin >= uint32(len(f.data)) { if byteBegin >= f.dataTotal {
return nil, errors.New("Not enough bytes to create byte array") return nil, errors.New("not enough bytes to create byte array")
} }
if length == 0 { if length == 0 {
return nil, errors.New("Zero-length is not supported") return nil, errors.New("zero-length is not supported")
} }
if byteBegin+length >= uint32(len(f.data)) { if byteBegin+length >= f.dataTotal {
return nil, errors.New("Not enough bytes to create byte array") return nil, errors.New("not enough bytes to create byte array")
} }
if byteBegin+length < byteBegin { if byteBegin+length < byteBegin {
return nil, errors.New("Nunmbers overflow. Returning") return nil, errors.New("numbers overflow")
} }
b := f.data[byteBegin : byteBegin+length]
f.position = byteBegin + length f.position = byteBegin + length
return b, nil return f.data[byteBegin:f.position], nil
} }
func (f *ConsumeFuzzer) GetString() (string, error) { func (f *ConsumeFuzzer) GetString() (string, error) {
if f.position >= uint32(len(f.data)) { if f.position >= f.dataTotal {
return "nil", errors.New("Not enough bytes to create string") return "nil", errors.New("not enough bytes to create string")
} }
length, err := f.GetUint32() length, err := f.GetUint32()
if err != nil { if err != nil {
return "nil", errors.New("Not enough bytes to create string") return "nil", errors.New("not enough bytes to create string")
} }
if f.position > MaxTotalLen { if f.position > MaxTotalLen {
return "nil", errors.New("Created too large a string") return "nil", errors.New("created too large a string")
} }
byteBegin := f.position - 1 byteBegin := f.position - 1
if byteBegin >= uint32(len(f.data)) { if byteBegin >= f.dataTotal {
return "nil", errors.New("Not enough bytes to create string") return "nil", errors.New("not enough bytes to create string")
} }
if byteBegin+length > uint32(len(f.data)) { if byteBegin+length > f.dataTotal {
return "nil", errors.New("Not enough bytes to create string") return "nil", errors.New("not enough bytes to create string")
} }
if byteBegin > byteBegin+length { if byteBegin > byteBegin+length {
return "nil", errors.New("Numbers overflow. Returning") return "nil", errors.New("numbers overflow")
} }
str := string(f.data[byteBegin : byteBegin+length])
f.position = byteBegin + length f.position = byteBegin + length
return str, nil return string(f.data[byteBegin:f.position]), nil
} }
func (f *ConsumeFuzzer) GetBool() (bool, error) { func (f *ConsumeFuzzer) GetBool() (bool, error) {
if f.position >= uint32(len(f.data)) { if f.position >= f.dataTotal {
return false, errors.New("Not enough bytes to create bool") return false, errors.New("not enough bytes to create bool")
} }
if IsDivisibleBy(int(f.data[f.position]), 2) { if IsDivisibleBy(int(f.data[f.position]), 2) {
f.position++ f.position++
@ -514,20 +459,13 @@ func (f *ConsumeFuzzer) GetBool() (bool, error) {
} }
func (f *ConsumeFuzzer) FuzzMap(m interface{}) error { func (f *ConsumeFuzzer) FuzzMap(m interface{}) error {
err := f.GenerateStruct(m) return f.GenerateStruct(m)
if err != nil {
return err
}
return nil
} }
func returnTarBytes(buf []byte) ([]byte, error) { func returnTarBytes(buf []byte) ([]byte, error) {
reader := bytes.NewReader(buf)
tr := tar.NewReader(reader)
// Count files // Count files
var fileCounter int var fileCounter int
fileCounter = 0 tr := tar.NewReader(bytes.NewReader(buf))
for { for {
_, err := tr.Next() _, err := tr.Next()
if err == io.EOF { if err == io.EOF {
@ -541,7 +479,7 @@ func returnTarBytes(buf []byte) ([]byte, error) {
if fileCounter > 4 { if fileCounter > 4 {
return buf, nil return buf, nil
} }
return nil, fmt.Errorf("Not enough files were created\n") return nil, fmt.Errorf("not enough files were created\n")
} }
func setTarHeaderFormat(hdr *tar.Header, f *ConsumeFuzzer) error { func setTarHeaderFormat(hdr *tar.Header, f *ConsumeFuzzer) error {
@ -609,94 +547,77 @@ func setTarHeaderTypeflag(hdr *tar.Header, f *ConsumeFuzzer) error {
} }
func (f *ConsumeFuzzer) createTarFileBody() ([]byte, error) { func (f *ConsumeFuzzer) createTarFileBody() ([]byte, error) {
if len(f.data) == 0 || f.position >= uint32(len(f.data)) {
return nil, errors.New("Not enough bytes to create byte array")
}
length, err := f.GetUint32() length, err := f.GetUint32()
if err != nil { if err != nil {
return nil, errors.New("Not enough bytes to create byte array") return nil, errors.New("not enough bytes to create byte array")
} }
// A bit of optimization to attempt to create a file body // A bit of optimization to attempt to create a file body
// when we don't have as many bytes left as "length" // when we don't have as many bytes left as "length"
remainingBytes := (uint32(len(f.data)) - f.position) remainingBytes := f.dataTotal - f.position
totalDataLen := uint32(len(f.data))
if uint32(len(f.data))-f.position < 50 {
if remainingBytes == 0 { if remainingBytes == 0 {
return nil, errors.New("Created too large a string") return nil, errors.New("created too large a string")
} }
if remainingBytes < 50 {
length = length % remainingBytes length = length % remainingBytes
} else if len(f.data) < 500 { } else if f.dataTotal < 500 {
if totalDataLen == 0 { length = length % f.dataTotal
return nil, errors.New("Created too large a string")
}
length = length % totalDataLen
} }
if f.position+length > MaxTotalLen { if f.position+length > MaxTotalLen {
return nil, errors.New("Created too large a string") return nil, errors.New("created too large a string")
} }
byteBegin := f.position - 1 byteBegin := f.position - 1
if byteBegin >= uint32(len(f.data)) { if byteBegin >= f.dataTotal {
return nil, errors.New("Not enough bytes to create byte array") return nil, errors.New("not enough bytes to create byte array")
} }
if length == 0 { if length == 0 {
return nil, errors.New("Zero-length is not supported") return nil, errors.New("zero-length is not supported")
} }
if byteBegin+length >= uint32(len(f.data)) { if byteBegin+length >= f.dataTotal {
return nil, errors.New("Not enough bytes to create byte array") return nil, errors.New("not enough bytes to create byte array")
} }
if byteBegin+length < byteBegin { if byteBegin+length < byteBegin {
return nil, errors.New("Nunmbers overflow. Returning") return nil, errors.New("numbers overflow")
} }
filebody := f.data[byteBegin : byteBegin+length]
f.position = byteBegin + length f.position = byteBegin + length
return filebody, nil return f.data[byteBegin:f.position], nil
} }
// Is similar to GetString(), but creates string based on the length // getTarFileName is similar to GetString(), but creates string based
// of the length of f.data to increase the likelihood of not overflowing // on the length of f.data to reduce the likelihood of overflowing
// f.data // f.data.
func (f *ConsumeFuzzer) getTarFilename() (string, error) { func (f *ConsumeFuzzer) getTarFilename() (string, error) {
if f.position >= uint32(len(f.data)) {
return "nil", errors.New("Not enough bytes to create string")
}
length, err := f.GetUint32() length, err := f.GetUint32()
if err != nil { if err != nil {
return "nil", errors.New("Not enough bytes to create string") return "nil", errors.New("not enough bytes to create string")
} }
// A bit of optimization to attempt to create a file name // A bit of optimization to attempt to create a file name
// when we don't have as many bytes left as "length" // when we don't have as many bytes left as "length"
remainingBytes := (uint32(len(f.data)) - f.position) remainingBytes := f.dataTotal - f.position
totalDataLen := uint32(len(f.data))
if uint32(len(f.data))-f.position < 50 {
if remainingBytes == 0 { if remainingBytes == 0 {
return "nil", errors.New("Created too large a string") return "nil", errors.New("created too large a string")
} }
if remainingBytes < 50 {
length = length % remainingBytes length = length % remainingBytes
} else if len(f.data) < 500 { } else if f.dataTotal < 500 {
if totalDataLen == 0 { length = length % f.dataTotal
return "nil", errors.New("Created too large a string")
}
length = length % totalDataLen
} }
if f.position > MaxTotalLen { if f.position > MaxTotalLen {
return "nil", errors.New("Created too large a string") return "nil", errors.New("created too large a string")
} }
byteBegin := f.position - 1 byteBegin := f.position - 1
if byteBegin >= uint32(len(f.data)) { if byteBegin >= f.dataTotal {
return "nil", errors.New("Not enough bytes to create string") return "nil", errors.New("not enough bytes to create string")
} }
if byteBegin+length > uint32(len(f.data)) { if byteBegin+length > f.dataTotal {
return "nil", errors.New("Not enough bytes to create string") return "nil", errors.New("not enough bytes to create string")
} }
if byteBegin > byteBegin+length { if byteBegin > byteBegin+length {
return "nil", errors.New("Numbers overflow. Returning") return "nil", errors.New("numbers overflow")
} }
str := string(f.data[byteBegin : byteBegin+length])
f.position = byteBegin + length f.position = byteBegin + length
return str, nil return string(f.data[byteBegin:f.position]), nil
} }
// TarBytes returns valid bytes for a tar archive // TarBytes returns valid bytes for a tar archive
@ -710,7 +631,7 @@ func (f *ConsumeFuzzer) TarBytes() ([]byte, error) {
tw := tar.NewWriter(&buf) tw := tar.NewWriter(&buf)
defer tw.Close() defer tw.Close()
maxNoOfFiles := 1000 const maxNoOfFiles = 1000
for i := 0; i < numberOfFiles%maxNoOfFiles; i++ { for i := 0; i < numberOfFiles%maxNoOfFiles; i++ {
filename, err := f.getTarFilename() filename, err := f.getTarFilename()
if err != nil { if err != nil {
@ -720,34 +641,27 @@ func (f *ConsumeFuzzer) TarBytes() ([]byte, error) {
if err != nil { if err != nil {
return returnTarBytes(buf.Bytes()) return returnTarBytes(buf.Bytes())
} }
hdr := &tar.Header{}
err = setTarHeaderTypeflag(hdr, f)
if err != nil {
return returnTarBytes(buf.Bytes())
}
sec, err := f.GetInt() sec, err := f.GetInt()
if err != nil { if err != nil {
return returnTarBytes(buf.Bytes()) return returnTarBytes(buf.Bytes())
} }
nsec, err := f.GetInt() nsec, err := f.GetInt()
if err != nil { if err != nil {
return returnTarBytes(buf.Bytes()) return returnTarBytes(buf.Bytes())
} }
hdr.ModTime = time.Unix(int64(sec), int64(nsec)) hdr := &tar.Header{
Name: filename,
hdr.Name = filename Size: int64(len(filebody)),
hdr.Size = int64(len(filebody)) Mode: 0o600,
hdr.Mode = 0600 ModTime: time.Unix(int64(sec), int64(nsec)),
}
err = setTarHeaderFormat(hdr, f) if err := setTarHeaderTypeflag(hdr, f); err != nil {
if err != nil { return returnTarBytes(buf.Bytes())
}
if err := setTarHeaderFormat(hdr, f); err != nil {
return returnTarBytes(buf.Bytes()) return returnTarBytes(buf.Bytes())
} }
if err := tw.WriteHeader(hdr); err != nil { if err := tw.WriteHeader(hdr); err != nil {
return returnTarBytes(buf.Bytes()) return returnTarBytes(buf.Bytes())
} }
@ -758,13 +672,11 @@ func (f *ConsumeFuzzer) TarBytes() ([]byte, error) {
return returnTarBytes(buf.Bytes()) return returnTarBytes(buf.Bytes())
} }
// Creates pseudo-random files in rootDir. // CreateFiles creates pseudo-random files in rootDir.
// Will create subdirs and place the files there. // It creates subdirs and places the files there.
// It is the callers responsibility to ensure that // It is the callers responsibility to ensure that
// rootDir exists. // rootDir exists.
func (f *ConsumeFuzzer) CreateFiles(rootDir string) error { func (f *ConsumeFuzzer) CreateFiles(rootDir string) error {
var noOfCreatedFiles int
noOfCreatedFiles = 0
numberOfFiles, err := f.GetInt() numberOfFiles, err := f.GetInt()
if err != nil { if err != nil {
return err return err
@ -774,40 +686,35 @@ func (f *ConsumeFuzzer) CreateFiles(rootDir string) error {
return errors.New("maxNumberOfFiles is nil") return errors.New("maxNumberOfFiles is nil")
} }
var noOfCreatedFiles int
for i := 0; i < maxNumberOfFiles; i++ { for i := 0; i < maxNumberOfFiles; i++ {
// The file to create: // The file to create:
fileName, err := f.GetString() fileName, err := f.GetString()
if err != nil { if err != nil {
if noOfCreatedFiles > 0 { if noOfCreatedFiles > 0 {
// If files have been created, we don't return // If files have been created, we don't return an error.
// an error
break break
} else { } else {
return errors.New("Could not get fileName") return errors.New("could not get fileName")
} }
} }
var fullFilePath string fullFilePath, err := securejoin.SecureJoin(rootDir, fileName)
fullFilePath, err = securejoin.SecureJoin(rootDir, fileName)
if err != nil { if err != nil {
return err return err
} }
// Find the subdirectory of the file // Find the subdirectory of the file
subDir := filepath.Dir(fileName) if subDir := filepath.Dir(fileName); subDir != "" && subDir != "." {
if subDir != "" && subDir != "." { // create the dir first; avoid going outside the root dir
// create the dir first
// Avoid going outside the root dir
if strings.Contains(subDir, "../") || (len(subDir) > 0 && subDir[0] == 47) || strings.Contains(subDir, "\\") { if strings.Contains(subDir, "../") || (len(subDir) > 0 && subDir[0] == 47) || strings.Contains(subDir, "\\") {
continue continue
} }
dirPath := filepath.Join(rootDir, subDir)
dirPath, err := securejoin.SecureJoin(rootDir, subDir) dirPath, err := securejoin.SecureJoin(rootDir, subDir)
if err != nil { if err != nil {
continue continue
} }
if _, err := os.Stat(dirPath); os.IsNotExist(err) { if _, err := os.Stat(dirPath); os.IsNotExist(err) {
err2 := os.MkdirAll(dirPath, 0777) err2 := os.MkdirAll(dirPath, 0o777)
if err2 != nil { if err2 != nil {
continue continue
} }
@ -823,7 +730,7 @@ func (f *ConsumeFuzzer) CreateFiles(rootDir string) error {
if noOfCreatedFiles > 0 { if noOfCreatedFiles > 0 {
break break
} else { } else {
return errors.New("Could not create the symlink") return errors.New("could not create the symlink")
} }
} }
if createSymlink { if createSymlink {
@ -831,7 +738,10 @@ func (f *ConsumeFuzzer) CreateFiles(rootDir string) error {
if err != nil { if err != nil {
return err return err
} }
os.Symlink(symlinkTarget, fullFilePath) err = os.Symlink(symlinkTarget, fullFilePath)
if err != nil {
return err
}
// stop loop here, since a symlink needs no further action // stop loop here, since a symlink needs no further action
noOfCreatedFiles++ noOfCreatedFiles++
continue continue
@ -842,43 +752,35 @@ func (f *ConsumeFuzzer) CreateFiles(rootDir string) error {
if noOfCreatedFiles > 0 { if noOfCreatedFiles > 0 {
break break
} else { } else {
return errors.New("Could not create the file") return errors.New("could not create the file")
} }
} }
createdFile, err := os.Create(fullFilePath) err = os.WriteFile(fullFilePath, fileContents, 0o666)
if err != nil { if err != nil {
createdFile.Close()
continue continue
} }
_, err = createdFile.Write(fileContents)
if err != nil {
createdFile.Close()
continue
}
createdFile.Close()
noOfCreatedFiles++ noOfCreatedFiles++
} }
} }
return nil return nil
} }
// Returns a string that can only consists of characters that are // GetStringFrom returns a string that can only consist of characters
// included in possibleChars. Will return an error if the created // included in possibleChars. It returns an error if the created string
// string does not have the specified length // does not have the specified length.
func (f *ConsumeFuzzer) GetStringFrom(possibleChars string, length int) (string, error) { func (f *ConsumeFuzzer) GetStringFrom(possibleChars string, length int) (string, error) {
returnString := "" if (f.dataTotal - f.position) < uint32(length) {
if (uint32(len(f.data)) - f.position) < uint32(length) { return "", errors.New("not enough bytes to create a string")
return returnString, errors.New("Not enough bytes to create a string")
} }
output := make([]byte, 0, length)
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
charIndex, err := f.GetInt() charIndex, err := f.GetInt()
if err != nil { if err != nil {
return returnString, err return string(output), err
} }
charToAdd := string(possibleChars[charIndex%len(possibleChars)]) output = append(output, possibleChars[charIndex%len(possibleChars)])
returnString = fmt.Sprintf(returnString + charToAdd)
} }
return returnString, nil return string(output), nil
} }
func (f *ConsumeFuzzer) GetRune() ([]rune, error) { func (f *ConsumeFuzzer) GetRune() ([]rune, error) {
@ -892,11 +794,11 @@ func (f *ConsumeFuzzer) GetRune() ([]rune, error) {
func (f *ConsumeFuzzer) GetFloat32() (float32, error) { func (f *ConsumeFuzzer) GetFloat32() (float32, error) {
u32, err := f.GetNBytes(4) u32, err := f.GetNBytes(4)
if err != nil { if err != nil {
return float32(0.0), err return 0, err
} }
littleEndian, err := f.GetBool() littleEndian, err := f.GetBool()
if err != nil { if err != nil {
return float32(0.0), err return 0, err
} }
if littleEndian { if littleEndian {
u32LE := binary.LittleEndian.Uint32(u32) u32LE := binary.LittleEndian.Uint32(u32)
@ -909,11 +811,11 @@ func (f *ConsumeFuzzer) GetFloat32() (float32, error) {
func (f *ConsumeFuzzer) GetFloat64() (float64, error) { func (f *ConsumeFuzzer) GetFloat64() (float64, error) {
u64, err := f.GetNBytes(8) u64, err := f.GetNBytes(8)
if err != nil { if err != nil {
return float64(0.0), err return 0, err
} }
littleEndian, err := f.GetBool() littleEndian, err := f.GetBool()
if err != nil { if err != nil {
return float64(0.0), err return 0, err
} }
if littleEndian { if littleEndian {
u64LE := binary.LittleEndian.Uint64(u64) u64LE := binary.LittleEndian.Uint64(u64)
@ -924,9 +826,5 @@ func (f *ConsumeFuzzer) GetFloat64() (float64, error) {
} }
func (f *ConsumeFuzzer) CreateSlice(targetSlice interface{}) error { func (f *ConsumeFuzzer) CreateSlice(targetSlice interface{}) error {
err := f.GenerateStruct(targetSlice) return f.GenerateStruct(targetSlice)
if err != nil {
return err
}
return nil
} }

View File

@ -35,23 +35,14 @@ func (f *ConsumeFuzzer) AddFuncs(fuzzFuncs []interface{}) {
} }
func (f *ConsumeFuzzer) GenerateWithCustom(targetStruct interface{}) error { func (f *ConsumeFuzzer) GenerateWithCustom(targetStruct interface{}) error {
v := reflect.ValueOf(targetStruct) e := reflect.ValueOf(targetStruct).Elem()
e := v.Elem()
return f.fuzzStruct(e, true) return f.fuzzStruct(e, true)
} }
func (c Continue) GenerateStruct(targetStruct interface{}) error { func (c Continue) GenerateStruct(targetStruct interface{}) error {
err := c.F.GenerateStruct(targetStruct) return c.F.GenerateStruct(targetStruct)
if err != nil {
return err
}
return nil
} }
func (c Continue) GenerateStructWithCustom(targetStruct interface{}) error { func (c Continue) GenerateStructWithCustom(targetStruct interface{}) error {
err := c.F.GenerateWithCustom(targetStruct) return c.F.GenerateWithCustom(targetStruct)
if err != nil {
return err
}
return nil
} }

View File

@ -16,7 +16,7 @@ func getKeyword(f *ConsumeFuzzer) (string, error) {
return k, nil return k, nil
} }
} }
return keywords[0], fmt.Errorf("Could not get a kw") return keywords[0], fmt.Errorf("could not get a kw")
} }
// Simple utility function to check if a string // Simple utility function to check if a string
@ -101,7 +101,8 @@ var keywords = []string{
"vitess_migration", "vitess_migrations", "vitess_replication_status", "vitess_migration", "vitess_migrations", "vitess_replication_status",
"vitess_shards", "vitess_tablets", "vschema", "warnings", "when", "vitess_shards", "vitess_tablets", "vschema", "warnings", "when",
"where", "while", "window", "with", "without", "work", "write", "xor", "where", "while", "window", "with", "without", "work", "write", "xor",
"year", "year_month", "zerofill"} "year", "year_month", "zerofill",
}
// Keywords that could get an additional keyword // Keywords that could get an additional keyword
var needCustomString = []string{ var needCustomString = []string{
@ -131,11 +132,15 @@ var alterTableTokens = [][]string{
} }
var alterTokens = [][]string{ var alterTokens = [][]string{
{"DATABASE", "SCHEMA", "DEFINER = ", "EVENT", "FUNCTION", "INSTANCE", {
"LOGFILE GROUP", "PROCEDURE", "SERVER"}, "DATABASE", "SCHEMA", "DEFINER = ", "EVENT", "FUNCTION", "INSTANCE",
"LOGFILE GROUP", "PROCEDURE", "SERVER",
},
{"CUSTOM_FUZZ_STRING"}, {"CUSTOM_FUZZ_STRING"},
{"ON SCHEDULE", "ON COMPLETION PRESERVE", "ON COMPLETION NOT PRESERVE", {
"ADD UNDOFILE", "OPTIONS"}, "ON SCHEDULE", "ON COMPLETION PRESERVE", "ON COMPLETION NOT PRESERVE",
"ADD UNDOFILE", "OPTIONS",
},
{"RENAME TO", "INITIAL_SIZE = "}, {"RENAME TO", "INITIAL_SIZE = "},
{"ENABLE", "DISABLE", "DISABLE ON SLAVE", "ENGINE"}, {"ENABLE", "DISABLE", "DISABLE ON SLAVE", "ENGINE"},
{"COMMENT"}, {"COMMENT"},
@ -150,9 +155,11 @@ var setTokens = [][]string{
var dropTokens = [][]string{ var dropTokens = [][]string{
{"TEMPORARY", "UNDO"}, {"TEMPORARY", "UNDO"},
{"DATABASE", "SCHEMA", "EVENT", "INDEX", "LOGFILE GROUP", {
"DATABASE", "SCHEMA", "EVENT", "INDEX", "LOGFILE GROUP",
"PROCEDURE", "FUNCTION", "SERVER", "SPATIAL REFERENCE SYSTEM", "PROCEDURE", "FUNCTION", "SERVER", "SPATIAL REFERENCE SYSTEM",
"TABLE", "TABLESPACE", "TRIGGER", "VIEW"}, "TABLE", "TABLESPACE", "TRIGGER", "VIEW",
},
{"IF EXISTS"}, {"IF EXISTS"},
{"CUSTOM_FUZZ_STRING"}, {"CUSTOM_FUZZ_STRING"},
{"ON", "ENGINE = ", "RESTRICT", "CASCADE"}, {"ON", "ENGINE = ", "RESTRICT", "CASCADE"},
@ -172,15 +179,21 @@ var truncateTokens = [][]string{
var createTokens = [][]string{ var createTokens = [][]string{
{"OR REPLACE", "TEMPORARY", "UNDO"}, // For create spatial reference system {"OR REPLACE", "TEMPORARY", "UNDO"}, // For create spatial reference system
{"UNIQUE", "FULLTEXT", "SPATIAL", "ALGORITHM = UNDEFINED", "ALGORITHM = MERGE", {
"ALGORITHM = TEMPTABLE"}, "UNIQUE", "FULLTEXT", "SPATIAL", "ALGORITHM = UNDEFINED", "ALGORITHM = MERGE",
{"DATABASE", "SCHEMA", "EVENT", "FUNCTION", "INDEX", "LOGFILE GROUP", "ALGORITHM = TEMPTABLE",
},
{
"DATABASE", "SCHEMA", "EVENT", "FUNCTION", "INDEX", "LOGFILE GROUP",
"PROCEDURE", "SERVER", "SPATIAL REFERENCE SYSTEM", "TABLE", "TABLESPACE", "PROCEDURE", "SERVER", "SPATIAL REFERENCE SYSTEM", "TABLE", "TABLESPACE",
"TRIGGER", "VIEW"}, "TRIGGER", "VIEW",
},
{"IF NOT EXISTS"}, {"IF NOT EXISTS"},
{"CUSTOM_FUZZ_STRING"}, {"CUSTOM_FUZZ_STRING"},
} }
/*
// For future use.
var updateTokens = [][]string{ var updateTokens = [][]string{
{"LOW_PRIORITY"}, {"LOW_PRIORITY"},
{"IGNORE"}, {"IGNORE"},
@ -189,6 +202,8 @@ var updateTokens = [][]string{
{"ORDER BY"}, {"ORDER BY"},
{"LIMIT"}, {"LIMIT"},
} }
*/
var replaceTokens = [][]string{ var replaceTokens = [][]string{
{"LOW_PRIORITY", "DELAYED"}, {"LOW_PRIORITY", "DELAYED"},
{"INTO"}, {"INTO"},
@ -196,6 +211,7 @@ var replaceTokens = [][]string{
{"CUSTOM_FUZZ_STRING"}, {"CUSTOM_FUZZ_STRING"},
{"VALUES", "VALUE"}, {"VALUES", "VALUE"},
} }
var loadTokens = [][]string{ var loadTokens = [][]string{
{"DATA"}, {"DATA"},
{"LOW_PRIORITY", "CONCURRENT", "LOCAL"}, {"LOW_PRIORITY", "CONCURRENT", "LOCAL"},
@ -271,22 +287,24 @@ var alter_table_options = []string{
"COMPACT", "SECONDARY_ENGINE_ATTRIBUTE", "STATS_AUTO_RECALC", "STATS_PERSISTENT", "COMPACT", "SECONDARY_ENGINE_ATTRIBUTE", "STATS_AUTO_RECALC", "STATS_PERSISTENT",
"STATS_SAMPLE_PAGES", "ZLIB", "LZ4", "ENGINE_ATTRIBUTE", "KEY_BLOCK_SIZE", "MAX_ROWS", "STATS_SAMPLE_PAGES", "ZLIB", "LZ4", "ENGINE_ATTRIBUTE", "KEY_BLOCK_SIZE", "MAX_ROWS",
"MIN_ROWS", "PACK_KEYS", "PASSWORD", "COMPRESSION", "CONNECTION", "DIRECTORY", "MIN_ROWS", "PACK_KEYS", "PASSWORD", "COMPRESSION", "CONNECTION", "DIRECTORY",
"DELAY_KEY_WRITE", "ENCRYPTION", "STORAGE", "DISK", "MEMORY", "UNION"} "DELAY_KEY_WRITE", "ENCRYPTION", "STORAGE", "DISK", "MEMORY", "UNION",
}
// Creates an 'alter table' statement. 'alter table' is an exception // Creates an 'alter table' statement. 'alter table' is an exception
// in that it has its own function. The majority of statements // in that it has its own function. The majority of statements
// are created by 'createStmt()'. // are created by 'createStmt()'.
func createAlterTableStmt(f *ConsumeFuzzer) (string, error) { func createAlterTableStmt(f *ConsumeFuzzer) (string, error) {
var stmt strings.Builder
stmt.WriteString("ALTER TABLE ")
maxArgs, err := f.GetInt() maxArgs, err := f.GetInt()
if err != nil { if err != nil {
return "", err return "", err
} }
maxArgs = maxArgs % 30 maxArgs = maxArgs % 30
if maxArgs == 0 { if maxArgs == 0 {
return "", fmt.Errorf("Could not create alter table stmt") return "", fmt.Errorf("could not create alter table stmt")
} }
var stmt strings.Builder
stmt.WriteString("ALTER TABLE ")
for i := 0; i < maxArgs; i++ { for i := 0; i < maxArgs; i++ {
// Calculate if we get existing token or custom string // Calculate if we get existing token or custom string
tokenType, err := f.GetInt() tokenType, err := f.GetInt()
@ -298,13 +316,13 @@ func createAlterTableStmt(f *ConsumeFuzzer) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
stmt.WriteString(fmt.Sprintf(" %s", customString)) stmt.WriteString(" " + customString)
} else { } else {
tokenIndex, err := f.GetInt() tokenIndex, err := f.GetInt()
if err != nil { if err != nil {
return "", err return "", err
} }
stmt.WriteString(fmt.Sprintf(" %s", alter_table_options[tokenIndex%len(alter_table_options)])) stmt.WriteString(" " + alter_table_options[tokenIndex%len(alter_table_options)])
} }
} }
return stmt.String(), nil return stmt.String(), nil
@ -316,7 +334,7 @@ func chooseToken(tokens []string, f *ConsumeFuzzer) (string, error) {
return "", err return "", err
} }
var token strings.Builder var token strings.Builder
token.WriteString(fmt.Sprintf(" %s", tokens[index%len(tokens)])) token.WriteString(tokens[index%len(tokens)])
if token.String() == "CUSTOM_FUZZ_STRING" { if token.String() == "CUSTOM_FUZZ_STRING" {
customFuzzString, err := f.GetString() customFuzzString, err := f.GetString()
if err != nil { if err != nil {
@ -331,7 +349,7 @@ func chooseToken(tokens []string, f *ConsumeFuzzer) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
token.WriteString(fmt.Sprintf(" %s", customFuzzString)) token.WriteString(" " + customFuzzString)
} }
return token.String(), nil return token.String(), nil
} }
@ -398,21 +416,19 @@ func createStmt(f *ConsumeFuzzer) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
query.WriteString(fmt.Sprintf(" %s", queryArgs)) query.WriteString(" " + queryArgs)
return query.String(), nil return query.String(), nil
} }
// Creates the arguments of a statements. In a select statement // Creates the arguments of a statements. In a select statement
// that would be everything after "select". // that would be everything after "select".
func createStmtArgs(tokenslice [][]string, f *ConsumeFuzzer) (string, error) { func createStmtArgs(tokenslice [][]string, f *ConsumeFuzzer) (string, error) {
var query strings.Builder var query, token strings.Builder
var token strings.Builder
// We go through the tokens in the tokenslice, // We go through the tokens in the tokenslice,
// create the respective token and add it to // create the respective token and add it to
// "query" // "query"
for _, tokens := range tokenslice { for _, tokens := range tokenslice {
// For extra randomization, the fuzzer can // For extra randomization, the fuzzer can
// choose to not include this token. // choose to not include this token.
includeThisToken, err := f.GetBool() includeThisToken, err := f.GetBool()
@ -429,7 +445,7 @@ func createStmtArgs(tokenslice [][]string, f *ConsumeFuzzer) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
query.WriteString(fmt.Sprintf(" %s", chosenToken)) query.WriteString(" " + chosenToken)
} else { } else {
token.WriteString(tokens[0]) token.WriteString(tokens[0])
@ -440,7 +456,7 @@ func createStmtArgs(tokenslice [][]string, f *ConsumeFuzzer) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
query.WriteString(fmt.Sprintf(" %s", customFuzzString)) query.WriteString(" " + customFuzzString)
continue continue
} }
@ -470,7 +486,7 @@ func createQuery(f *ConsumeFuzzer) (string, error) {
} }
maxLen := queryLen % 60 maxLen := queryLen % 60
if maxLen == 0 { if maxLen == 0 {
return "", fmt.Errorf("Could not create a query") return "", fmt.Errorf("could not create a query")
} }
var query strings.Builder var query strings.Builder
for i := 0; i < maxLen; i++ { for i := 0; i < maxLen; i++ {
@ -484,23 +500,25 @@ func createQuery(f *ConsumeFuzzer) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
query.WriteString(fmt.Sprintf(" %s", keyword)) query.WriteString(" " + keyword)
} else { } else {
customString, err := f.GetString() customString, err := f.GetString()
if err != nil { if err != nil {
return "", err return "", err
} }
query.WriteString(fmt.Sprintf(" %s", customString)) query.WriteString(" " + customString)
} }
} }
if query.String() == "" { if query.String() == "" {
return "", fmt.Errorf("Could not create a query") return "", fmt.Errorf("could not create a query")
} }
return query.String(), nil return query.String(), nil
} }
// This is the API that users will interact with. // GetSQLString is the API that users interact with.
//
// Usage: // Usage:
//
// f := NewConsumer(data) // f := NewConsumer(data)
// sqlString, err := f.GetSQLString() // sqlString, err := f.GetSQLString()
func (f *ConsumeFuzzer) GetSQLString() (string, error) { func (f *ConsumeFuzzer) GetSQLString() (string, error) {

4
vendor/modules.txt vendored
View File

@ -1,7 +1,7 @@
# cloud.google.com/go/compute/metadata v0.2.1 # cloud.google.com/go/compute/metadata v0.2.1
## explicit; go 1.19 ## explicit; go 1.19
# github.com/AdaLogics/go-fuzz-headers v0.0.0-20221103172237-443f56ff4ba8 # github.com/AdaLogics/go-fuzz-headers v0.0.0-20221118232415-3345c89a7c72
## explicit; go 1.13 ## explicit; go 1.18
github.com/AdaLogics/go-fuzz-headers github.com/AdaLogics/go-fuzz-headers
# github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b # github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20220912195655-e1f97a00006b
## explicit; go 1.18 ## explicit; go 1.18