diff --git a/generator.go b/generator.go index 08eedf0..42c4b18 100644 --- a/generator.go +++ b/generator.go @@ -2,14 +2,18 @@ package main import ( "errors" + "fmt" + "math" "reflect" "unsafe" ) type Generator struct { - data []byte - dataSize uint32 - position uint32 + data []byte + dataSize uint32 + position uint32 + mapStruct map[string]interface{} + arrayStruct []interface{} } func NewGenerator(fuzzData []byte) *Generator { @@ -43,6 +47,79 @@ func (g *Generator) fillAny(any reflect.Value) error { return err } + case reflect.String: + str, err := g.GenerateString() + if err != nil { + return err + } + any.SetString(str) + + case reflect.Float32: + newFloat, err := g.GenerateFloat32() + if err != nil { + return err + } + any.SetFloat(float64(newFloat)) + + case reflect.Float64: + newFloat, err := g.GenerateFloat64() + if err != nil { + return err + } + any.SetFloat(float64(newFloat)) + + case reflect.Complex64: + newFloatReal, err := g.GenerateFloat32() + if err != nil { + return err + } + newFloatImag, err := g.GenerateFloat32() + if err != nil { + return err + } + any.SetComplex(complex(float64(newFloatReal), float64(newFloatImag))) + + case reflect.Complex128: + newFloatReal, err := g.GenerateFloat64() + if err != nil { + return err + } + newFloatImag, err := g.GenerateFloat64() + if err != nil { + return err + } + any.SetComplex(complex(newFloatReal, newFloatImag)) + + case reflect.Map: + any.Set(reflect.MakeMap(any.Type())) + + mapLen, err := g.GenerateUInt32() + if err != nil { + return err + } + + for i := uint32(0); i < mapLen; i++ { + key := fmt.Sprintf("key%d", i) + mapValue := reflect.New(any.Type().Elem()) + err := g.fillAny(mapValue.Elem()) + if err != nil { + return err + } + any.SetMapIndex(reflect.ValueOf(key), mapValue.Elem()) + } + + case reflect.Array: + any.Set(reflect.New(any.Type()).Elem()) + arrayLen := any.Len() + for i := 0; i < arrayLen; i++ { + arrayValue := reflect.New(any.Type().Elem()) + err := g.fillAny(arrayValue.Elem()) + if err != nil { + return err + } + any.Index(i).Set(arrayValue.Elem()) + } + case reflect.Bool: newBool, err := g.GenerateBool() if err != nil { @@ -135,6 +212,86 @@ func (g *Generator) GenerateInt() (int, error) { return result, nil } +func (g *Generator) GenerateUInt32() (uint32, error) { + if g.position+3 >= g.dataSize { + return 0, errors.New("the data bytes are over") + } + result := uint32(0) + for i := 0; i < 4; i++ { + result = result<<8 | uint32(g.data[g.position]) + g.position++ + } + return result, nil +} + +func (g *Generator) GenerateString() (string, error) { + maxStrLength := uint32(2000000) + + if g.position >= g.dataSize { + return "nil", errors.New("the data bytes are over") + } + + length, err := g.GenerateUInt32() + if err != nil { + return "nil", errors.New("the data bytes are over") + } + + if g.position > maxStrLength { + return "nil", errors.New("the string length too large") + } + + startBytePos := g.position + if startBytePos >= g.dataSize { + return "nil", errors.New("the data bytes are over") + } + + if startBytePos+length > g.dataSize { + return "nil", errors.New("the data bytes are over") + } + + if startBytePos > startBytePos+length { + return "nil", errors.New("overflow") + } + + g.position = startBytePos + length + result := string(g.data[startBytePos:g.position]) + + return result, nil +} + +func (g *Generator) GenerateFloat32() (float32, error) { + if g.position+3 >= g.dataSize { + return 0, errors.New("the data bytes are over") + } + + bits := uint32(0) + for i := 0; i < 4; i++ { + bits = bits<<8 | uint32(g.data[g.position]) + g.position++ + } + + floatBits := uint32(math.Float32bits(math.Float32frombits(bits))) + result := math.Float32frombits(floatBits) + + return result, nil +} + +func (g *Generator) GenerateFloat64() (float64, error) { + if g.position+7 >= g.dataSize { + return 0, errors.New("the data bytes are over") + } + + bits := uint64(0) + for i := 0; i < 8; i++ { + bits = bits<<8 | uint64(g.data[g.position]) + g.position++ + } + + result := math.Float64frombits(bits) + + return result, nil +} + func (g *Generator) GenerateBool() (bool, error) { if g.position >= g.dataSize { return false, errors.New("the data bytes are over") @@ -165,18 +322,6 @@ func (g *Generator) GenerateUInt16() (uint16, error) { return result, nil } -func (g *Generator) GenerateUInt32() (uint32, error) { - if g.position+3 >= g.dataSize { - return 0, errors.New("the data bytes are over") - } - result := uint32(0) - for i := 0; i < 4; i++ { - result = result<<8 | uint32(g.data[g.position]) - g.position++ - } - return result, nil -} - func (g *Generator) GenerateUInt64() (uint64, error) { if g.position+7 >= g.dataSize { return 0, errors.New("the data bytes are over") @@ -187,4 +332,4 @@ func (g *Generator) GenerateUInt64() (uint64, error) { g.position++ } return result, nil -} +} \ No newline at end of file diff --git a/main.go b/main.go index 81897f8..55bf77d 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,19 @@ type Struct2 struct { Field2 Struct1 } +type Struct3 struct { + Field1 string + Field2 float32 + Field3 float64 + Field4 complex64 + Field5 complex128 +} + +type Struct4 struct { + Field1 [5]int + Field2 map[string]int +} + func main() { }