go: fix some panics in unpickle
Fix a few cases where PickleLoads panics on invalid pickles instead of returning an error. I found all of these with go-fuzz. It's super cool. https://github.com/dvyukov/go-fuzz Change-Id: I7e73df4afc077977570fa8706e84846a69ffae7d
This commit is contained in:
parent
82fb8e8a7b
commit
bcdc810dd5
@ -359,6 +359,19 @@ func TestShortPickles(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPicklesFromFuzz(t *testing.T) {
|
||||
// These were former crash cases found by go-fuzz.
|
||||
tests := []string{
|
||||
"(M00d", "\x88\x88a", "}}}s", "((a", "}}a", "G00000000G00000000a",
|
||||
"M00M00a", "((td", "T\x0e\x00\x00\x0000000000000000Na", "}))s",
|
||||
"NM00a", "())d", "}(}u", "}((d}u", "(d(M00u",
|
||||
}
|
||||
for _, test := range tests {
|
||||
_, err := PickleLoads([]byte(test))
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPickleUnpicklelablePanics(t *testing.T) {
|
||||
catchFunc := func() {
|
||||
e := recover()
|
||||
|
@ -188,6 +188,15 @@ func pythonString(src string) (string, error) {
|
||||
return strconv.Unquote(string(dst))
|
||||
}
|
||||
|
||||
func isHashable(i interface{}) bool {
|
||||
switch i.(type) {
|
||||
case string, uint8, uint16, uint32, uint64, int8, int16, int32, int64, float32, float64:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func PickleLoads(data []byte) (interface{}, error) {
|
||||
state := newState(16, data)
|
||||
for op, err := state.readByte(); err == nil; op, err = state.readByte() {
|
||||
@ -261,6 +270,9 @@ func PickleLoads(data []byte) (interface{}, error) {
|
||||
if err1 != nil || err2 != nil {
|
||||
return nil, errors.New("Incomplete pickle (SETITEM): stack empty")
|
||||
}
|
||||
if !isHashable(key) {
|
||||
return nil, errors.New("Invalid pickle (SETITEM): invalid key type")
|
||||
}
|
||||
top, err := state.peek()
|
||||
if err != nil {
|
||||
return nil, errors.New("Invalid pickle (SETITEM): stack empty")
|
||||
@ -275,6 +287,9 @@ func PickleLoads(data []byte) (interface{}, error) {
|
||||
if err != nil {
|
||||
return nil, errors.New("Invalid pickle (SETITEMS): unable to find mark")
|
||||
}
|
||||
if len(vals)%2 != 0 {
|
||||
return nil, errors.New("Invalid pickle (SETITEMS): odd numbered mark")
|
||||
}
|
||||
top, err := state.peek()
|
||||
if err != nil {
|
||||
return nil, errors.New("Invalid pickle (SETITEMS): stack empty")
|
||||
@ -284,6 +299,9 @@ func PickleLoads(data []byte) (interface{}, error) {
|
||||
return nil, errors.New("Incomplete pickle (SETITEMS): stack top isn't a map")
|
||||
}
|
||||
for j := 0; j < len(vals); j += 2 {
|
||||
if !isHashable(vals[j]) {
|
||||
return nil, errors.New("Invalid pickle (SETITEMS): invalid key type")
|
||||
}
|
||||
dict[vals[j]] = vals[j+1]
|
||||
}
|
||||
|
||||
@ -294,8 +312,14 @@ func PickleLoads(data []byte) (interface{}, error) {
|
||||
if err != nil {
|
||||
return nil, errors.New("Invalid pickle (DICT): unable to find mark")
|
||||
}
|
||||
if len(vals)%2 != 0 {
|
||||
return nil, errors.New("Invalid pickle (DICT): odd numbered mark")
|
||||
}
|
||||
dict := make(map[interface{}]interface{}, len(vals)/2)
|
||||
for j := 0; j < len(vals); j += 2 {
|
||||
if !isHashable(vals[j]) {
|
||||
return nil, errors.New("Invalid pickle (DICT): invalid key type")
|
||||
}
|
||||
dict[vals[j]] = vals[j+1]
|
||||
}
|
||||
state.push(dict)
|
||||
@ -315,7 +339,11 @@ func PickleLoads(data []byte) (interface{}, error) {
|
||||
if err1 != nil || err2 != nil {
|
||||
return nil, errors.New("Incomplete pickle (APPEND): stack empty")
|
||||
}
|
||||
state.push(append(list.([]interface{}), value))
|
||||
if list, ok := list.([]interface{}); !ok {
|
||||
return nil, errors.New("Invalid pickle (APPEND): stack top not list")
|
||||
} else {
|
||||
state.push(append(list, value))
|
||||
}
|
||||
case 'e': // APPENDS
|
||||
items, err := state.mark()
|
||||
if err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user