diff --git a/fuzz.go b/fuzz.go new file mode 100644 index 0000000..e710631 --- /dev/null +++ b/fuzz.go @@ -0,0 +1,14 @@ +// +build gofuzz + +package stalecucumber + +import ( + "bytes" +) + +func Fuzz(data []byte) int { + if _, err := Unpickle(bytes.NewReader(data)); err != nil { + return 0 + } + return 1 +} diff --git a/fuzz_test.go b/fuzz_test.go new file mode 100644 index 0000000..3eb2056 --- /dev/null +++ b/fuzz_test.go @@ -0,0 +1,20 @@ +package stalecucumber + +import ( + "strings" + "testing" +) + +func TestFuzzCrashers(t *testing.T) { + + var crashers = []string{ + "}}(s", //protocol_0 SETITEM hash of unhashable + "((d}d", //protocol_0.go opcode_DICT hash of unhashable + "}(}(a}u", //protocol_1 SETITEMS hash of unhashable + "(p0\nj0000", //pickle_machine flushMemoBuffer index out of range + } + + for _, f := range crashers { + Unpickle(strings.NewReader(f)) + } +} diff --git a/protocol_0.go b/protocol_0.go index 07c956b..e77dcfd 100644 --- a/protocol_0.go +++ b/protocol_0.go @@ -3,6 +3,7 @@ package stalecucumber import "strconv" import "fmt" import "math/big" +import "errors" //import "unicode/utf8" import "unicode/utf16" @@ -354,7 +355,19 @@ Build a dict out of the topmost stack slice, after markobject. Stack before: [mark, stackslice] Stack after: [dict] **/ -func (pm *PickleMachine) opcode_DICT() error { +func (pm *PickleMachine) opcode_DICT() (err error) { + defer func() { + if r := recover(); r != nil { + switch x := r.(type) { + case string: + err = errors.New(x) + case error: + err = x + default: + err = errors.New("Unknown panic") + } + } + }() markIndex, err := pm.findMark() if err != nil { return err @@ -391,7 +404,19 @@ Add a key+value pair to an existing dict. Stack before: [dict, any, any] Stack after: [dict] **/ -func (pm *PickleMachine) opcode_SETITEM() error { +func (pm *PickleMachine) opcode_SETITEM() (err error) { + defer func() { + if r := recover(); r != nil { + switch x := r.(type) { + case string: + err = errors.New(x) + case error: + err = x + default: + err = errors.New("Unknown panic") + } + } + }() v, err := pm.pop() if err != nil { return err diff --git a/protocol_1.go b/protocol_1.go index 16b6f8c..80fb526 100644 --- a/protocol_1.go +++ b/protocol_1.go @@ -1,6 +1,7 @@ package stalecucumber import "fmt" +import "errors" /** Opcode: BININT (0x4a) @@ -272,7 +273,19 @@ Add an arbitrary number of key+value pairs to an existing dict. Stack before: [dict, mark, stackslice] Stack after: [dict] **/ -func (pm *PickleMachine) opcode_SETITEMS() error { +func (pm *PickleMachine) opcode_SETITEMS() (err error) { + defer func() { + if r := recover(); r != nil { + switch x := r.(type) { + case string: + err = errors.New(x) + case error: + err = x + default: + err = errors.New("Unknown panic") + } + } + }() markIndex, err := pm.findMark() if err != nil { return err @@ -333,9 +346,21 @@ Read an object from the memo and push it on the stack. Stack before: [] Stack after: [any] **/ -func (pm *PickleMachine) opcode_BINGET() error { +func (pm *PickleMachine) opcode_BINGET() (err error) { + defer func() { + if r := recover(); r != nil { + switch x := r.(type) { + case string: + err = errors.New(x) + case error: + err = x + default: + err = errors.New("Unknown panic") + } + } + }() var index uint8 - err := pm.readBinaryInto(&index, false) + err = pm.readBinaryInto(&index, false) if err != nil { return err } @@ -362,9 +387,21 @@ Read an object from the memo and push it on the stack. Stack before: [] Stack after: [any] **/ -func (pm *PickleMachine) opcode_LONG_BINGET() error { +func (pm *PickleMachine) opcode_LONG_BINGET() (err error) { + defer func() { + if r := recover(); r != nil { + switch x := r.(type) { + case string: + err = errors.New(x) + case error: + err = x + default: + err = errors.New("Unknown panic") + } + } + }() var index int32 - err := pm.readBinaryInto(&index, false) + err = pm.readBinaryInto(&index, false) if err != nil { return err }