Created
January 8, 2011 05:48
-
-
Save swdunlop/770585 to your computer and use it in GitHub Desktop.
A fuzzer for Go structures that uses reflection to identify and alter fields.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package blur | |
import "rand" | |
import "os" | |
import "reflect" | |
type Blurrer interface { | |
Blur() (interface{}, os.Error) | |
} | |
func Gen8() uint8 { | |
return uint8(rand.Intn(1 << 8)) | |
} | |
func Gen16() uint16 { | |
return uint16(rand.Intn(1 << 16)) | |
} | |
func Gen32() uint32 { | |
return uint32(rand.Int63n(1 << 32)) | |
} | |
func Gen64() uint64 { | |
return uint64((rand.Int63() << 1)) + uint64(rand.Intn(2)) | |
} | |
func Blur(x interface{}) os.Error { | |
return blurValue(reflect.NewValue(x)) | |
} | |
func blurValue(val reflect.Value) os.Error { | |
if !val.CanSet() { | |
return nil | |
} | |
x := val.Interface() | |
iface, ok := x.(Blurrer) | |
if ok { | |
x, err := iface.Blur() | |
if err != nil { | |
return err | |
} | |
val.SetValue(reflect.NewValue(x)) | |
} | |
switch val.Type().Kind() { | |
case reflect.Struct: | |
return blurStruct(val.(*reflect.StructValue)) | |
case reflect.Slice: | |
return blurSlice(val.(*reflect.SliceValue)) | |
case reflect.Array: | |
return blurArray(val.(*reflect.ArrayValue)) | |
case reflect.Ptr: | |
return blurValue(val.(*reflect.PtrValue).Elem()) | |
case reflect.Uint8: | |
u := val.(*reflect.UintValue) | |
u.Set(uint64(Gen8())) | |
case reflect.Uint16: | |
u := val.(*reflect.UintValue) | |
u.Set(uint64(Gen16())) | |
case reflect.Uint32: | |
u := val.(*reflect.UintValue) | |
u.Set(uint64(Gen32())) | |
case reflect.Uint64: | |
u := val.(*reflect.UintValue) | |
u.Set(uint64(Gen64())) | |
} | |
//TODO: support blurring signed | |
//TODO: support blurring strings | |
return nil | |
} | |
func blurStruct(val *reflect.StructValue) os.Error { | |
sz := val.NumField() | |
for i := 0; i < sz; i++ { | |
err := blurValue(val.Field(i)) | |
if err != nil { | |
return err | |
} | |
} | |
return nil | |
} | |
func blurSlice(val *reflect.SliceValue) os.Error { | |
sz := val.Len() | |
for i := 0; i < sz; i++ { | |
err := blurValue(val.Elem(i)) | |
if err != nil { | |
return err | |
} | |
} | |
return nil | |
} | |
func blurArray(val *reflect.ArrayValue) os.Error { | |
sz := val.Len() | |
for i := 0; i < sz; i++ { | |
err := blurValue(val.Elem(i)) | |
if err != nil { | |
return err | |
} | |
} | |
return nil | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package blur | |
import "testing" | |
import "fmt" | |
import "rand" | |
import "time" | |
type sample struct { | |
Alpha [8]byte | |
Beta uint16 | |
Charlie uint64 | |
} | |
func init() { | |
rand.Seed(time.Seconds()) | |
} | |
func TestBlur(t *testing.T) { | |
var s sample | |
fmt.Println("BEFORE: ", s) | |
err := Blur(&s) | |
if err != nil { | |
t.Error(err) | |
} | |
fmt.Println("AFTER: ", s) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
GOROOT ?= /opt/go | |
include $(GOROOT)/src/Make.inc | |
TARG=blur | |
GOFILES=blur.go | |
include $(GOROOT)/src/Make.pkg |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is useful with Go-style structure marshal libraries to produce syntactically correct but semantically random test data for fuzzing.