Commit 572d0a6a authored by Kamil Kisiel's avatar Kamil Kisiel

Fix Go stack overflows resulting from printing types generated by malformed data.

For example:

runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x100a3d, 0xe)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/runtime/panic.go:566 +0x95
runtime.newstack()
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/runtime/stack.go:1061 +0x416
runtime.morestack()
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/runtime/asm_amd64.s:366 +0x7f

goroutine 1 [running]:
runtime.resolveNameOff(0xdeec0, 0x1916, 0x260e6ecb713)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/runtime/type.go:168 fp=0xc4400f02c0 sp=0xc4400f02b8
reflect.resolveNameOff(0xdeec0, 0x1916, 0x0)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/runtime/runtime1.go:493 +0x33 fp=0xc4400f02e8 sp=0xc4400f02c0
reflect.(*rtype).nameOff(0xdeec0, 0xc400001916, 0x0)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/reflect/type.go:663 +0x4b fp=0xc4400f0310 sp=0xc4400f02e8
reflect.(*rtype).String(0xdeec0, 0xc42000e9e0, 0x98)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/reflect/type.go:733 +0x4e fp=0xc4400f0350 sp=0xc4400f0310
fmt.(*pp).badVerb(0xc4200180c0, 0x74)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:324 +0x590 fp=0xc4400f03e8 sp=0xc4400f0350
fmt.(*pp).fmtString(0xc4200180c0, 0x0, 0x0, 0x74)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:441 +0x119 fp=0xc4400f0420 sp=0xc4400f03e8
fmt.(*pp).printValue(0xc4200180c0, 0xdeec0, 0xc42000e9e0, 0x98, 0x74, 0x108419)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:715 +0x294d fp=0xc4400f0610 sp=0xc4400f0420
fmt.(*pp).printValue(0xc4200180c0, 0xea6e0, 0xc42000e9e0, 0x99, 0xc400000074, 0x108418)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:764 +0x2ec6 fp=0xc4400f0800 sp=0xc4400f0610
fmt.(*pp).printValue(0xc4200180c0, 0xe5960, 0xc42000a5d0, 0x194, 0x74, 0x108417)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:777 +0x24a3 fp=0xc4400f09f0 sp=0xc4400f0800
fmt.(*pp).printValue(0xc4200180c0, 0xdd140, 0xc42000ea00, 0x97, 0xc400000074, 0x108416)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:824 +0xf51 fp=0xc4400f0be0 sp=0xc4400f09f0
fmt.(*pp).printValue(0xc4200180c0, 0xe5960, 0xc42000ea30, 0x194, 0x74, 0x108415)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:777 +0x24a3 fp=0xc4400f0dd0 sp=0xc4400f0be0
fmt.(*pp).printValue(0xc4200180c0, 0xdd140, 0xc42000ea40, 0x97, 0xc400000074, 0x108414)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:824 +0xf51 fp=0xc4400f0fc0 sp=0xc4400f0dd0
fmt.(*pp).printValue(0xc4200180c0, 0xe5960, 0xc4200105a0, 0x194, 0x74, 0x108413)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:777 +0x24a3 fp=0xc4400f11b0 sp=0xc4400f0fc0
fmt.(*pp).printValue(0xc4200180c0, 0xdd140, 0xc42000ea80, 0x97, 0xc400000074, 0x108412)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:824 +0xf51 fp=0xc4400f13a0 sp=0xc4400f11b0
fmt.(*pp).printValue(0xc4200180c0, 0xe5960, 0xc4200105b0, 0x194, 0x74, 0x108411)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:777 +0x24a3 fp=0xc4400f1590 sp=0xc4400f13a0
fmt.(*pp).printValue(0xc4200180c0, 0xdd140, 0xc42000ea80, 0x97, 0xc400000074, 0x108410)
        /var/folders/dx/9jnx9d2j2kg8n35xgcsxjfyr0000gn/T/go-fuzz-build069870222/goroot/src/fmt/print.go:824 +0xf51 fp=0xc4400f1780 sp=0xc4400f1590

... etc
parent 80ae5a1a
...@@ -87,6 +87,7 @@ var errNotImplemented = errors.New("unimplemented opcode") ...@@ -87,6 +87,7 @@ var errNotImplemented = errors.New("unimplemented opcode")
var ErrInvalidPickleVersion = errors.New("invalid pickle version") var ErrInvalidPickleVersion = errors.New("invalid pickle version")
var errNoMarker = errors.New("no marker in stack") var errNoMarker = errors.New("no marker in stack")
var errStackUnderflow = errors.New("pickle: stack underflow") var errStackUnderflow = errors.New("pickle: stack underflow")
var errMalformedData = errors.New("pickle: malformed data")
type OpcodeError struct { type OpcodeError struct {
Key byte Key byte
...@@ -613,7 +614,7 @@ func (d *Decoder) loadAppend() error { ...@@ -613,7 +614,7 @@ func (d *Decoder) loadAppend() error {
l := l.([]interface{}) l := l.([]interface{})
d.stack[len(d.stack)-1] = append(l, v) d.stack[len(d.stack)-1] = append(l, v)
default: default:
return fmt.Errorf("loadAppend expected a list, got %t", l) return errMalformedData
} }
return nil return nil
} }
...@@ -678,7 +679,7 @@ func (d *Decoder) loadAppends() error { ...@@ -678,7 +679,7 @@ func (d *Decoder) loadAppends() error {
} }
d.stack = append(d.stack[:k-1], l) d.stack = append(d.stack[:k-1], l)
default: default:
return fmt.Errorf("loadAppends expected a list, got %t", l) return errMalformedData
} }
return nil return nil
} }
...@@ -829,7 +830,7 @@ func (d *Decoder) loadSetItem() error { ...@@ -829,7 +830,7 @@ func (d *Decoder) loadSetItem() error {
m := m.(map[interface{}]interface{}) m := m.(map[interface{}]interface{})
m[k] = v m[k] = v
default: default:
return fmt.Errorf("loadSetItem expected a map, got %t", m) return errMalformedData
} }
return nil return nil
} }
...@@ -851,7 +852,7 @@ func (d *Decoder) loadSetItems() error { ...@@ -851,7 +852,7 @@ func (d *Decoder) loadSetItems() error {
} }
d.stack = append(d.stack[:k-1], m) d.stack = append(d.stack[:k-1], m)
default: default:
return fmt.Errorf("loadSetItems expected a map, got %t", m) return errMalformedData
} }
return nil return nil
} }
......
...@@ -255,3 +255,15 @@ func TestMemoOpCode(t *testing.T) { ...@@ -255,3 +255,15 @@ func TestMemoOpCode(t *testing.T) {
} }
} }
func TestFuzzCrashers(t *testing.T) {
crashers := []string{
"(dS''\n(lc\n\na2a2a22aasS''\na",
}
for _, c := range crashers {
buf := bytes.NewBufferString(c)
dec := NewDecoder(buf)
dec.Decode()
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment