Merge pull request 'sf/base-type-impl' (#1) from sf/base-type-impl into master
Reviewed-on: #1
This commit is contained in:
commit
525e73b00c
2 changed files with 174 additions and 16 deletions
177
generator.go
177
generator.go
|
@ -2,14 +2,18 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Generator struct {
|
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")
|
||||||
|
@ -187,4 +332,4 @@ func (g *Generator) GenerateUInt64() (uint64, error) {
|
||||||
g.position++
|
g.position++
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
13
main.go
13
main.go
|
@ -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() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue