Merge pull request 'sf/base-type-impl' (#1) from sf/base-type-impl into master

Reviewed-on: #1
This commit is contained in:
Evgeny Bukreev 2024-05-07 12:43:11 +00:00
commit 525e73b00c
2 changed files with 174 additions and 16 deletions

View file

@ -2,6 +2,8 @@ package main
import ( import (
"errors" "errors"
"fmt"
"math"
"reflect" "reflect"
"unsafe" "unsafe"
) )
@ -10,6 +12,8 @@ type Generator struct {
data []byte data []byte
dataSize uint32 dataSize uint32
position uint32 position uint32
mapStruct map[string]interface{}
arrayStruct []interface{}
} }
func NewGenerator(fuzzData []byte) *Generator { func NewGenerator(fuzzData []byte) *Generator {
@ -43,6 +47,79 @@ func (g *Generator) fillAny(any reflect.Value) error {
return err 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: case reflect.Bool:
newBool, err := g.GenerateBool() newBool, err := g.GenerateBool()
if err != nil { if err != nil {
@ -135,6 +212,86 @@ func (g *Generator) GenerateInt() (int, error) {
return result, nil 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) { func (g *Generator) GenerateBool() (bool, error) {
if g.position >= g.dataSize { if g.position >= g.dataSize {
return false, errors.New("the data bytes are over") return false, errors.New("the data bytes are over")
@ -165,18 +322,6 @@ func (g *Generator) GenerateUInt16() (uint16, error) {
return result, nil 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) { func (g *Generator) GenerateUInt64() (uint64, error) {
if g.position+7 >= g.dataSize { if g.position+7 >= g.dataSize {
return 0, errors.New("the data bytes are over") return 0, errors.New("the data bytes are over")

13
main.go
View file

@ -13,6 +13,19 @@ type Struct2 struct {
Field2 Struct1 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() { func main() {
} }