1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
package fuzz
import (
"encoding/binary"
"fmt"
"reflect"
)
func Operations(b []byte, check func(), fns ...interface{}) {
choose := func(n int) (int, bool) {
if len(b) < 1 {
return 0, false
}
if n > 255 {
panic("")
}
choice := int(b[0])
if choice >= n {
return 0, false
}
b = b[1:]
return choice, true
}
takeByte := func() (byte, bool) {
if len(b) < 1 {
return 0, false
}
x := b[0]
b = b[1:]
return x, true
}
takeUint16 := func() (uint16, bool) {
if len(b) < 2 {
return 0, false
}
x := uint16(binary.BigEndian.Uint16(b[:2]))
b = b[2:]
return x, true
}
takeInt := func() (int, bool) {
if len(b) < 8 {
return 0, false
}
x := int(binary.BigEndian.Uint64(b[:8]))
b = b[8:]
return x, true
}
takeBool := func() (bool, bool) {
b, ok := takeByte()
return b != 0, ok
}
Loop:
for {
check()
i, ok := choose(len(fns))
if !ok {
break
}
fnV := reflect.ValueOf(fns[i])
args := make([]reflect.Value, fnV.Type().NumIn())
for j := range args {
argType := fnV.Type().In(j)
switch argType.Kind() {
case reflect.Int:
x, ok := takeInt()
if !ok {
break Loop
}
args[j] = reflect.ValueOf(x)
case reflect.Uint8:
x, ok := takeByte()
if !ok {
break Loop
}
args[j] = reflect.ValueOf(x)
case reflect.Uint16:
x, ok := takeUint16()
if !ok {
break Loop
}
args[j] = reflect.ValueOf(x)
case reflect.Bool:
x, ok := takeBool()
if !ok {
break Loop
}
args[j] = reflect.ValueOf(x)
default:
panic(fmt.Sprintf("arg type %s not supported", argType.Kind()))
}
}
fnV.Call(args)
}
}
|