Commit 8e6cf5f7 authored by Håvard Haugen's avatar Håvard Haugen Committed by Rob Pike

encoding/gob: clean up decoderMap after errBadType

When decoding an invalid typeId the associated *decEngine was not
removed from decoderMap. If the decoder was run again on the same input
a nil *decEngine was found in the map and assumed to be initialized,
resulting in a panic.

Fixes #9649

Change-Id: I5bb51808362a21c09228c2705a658f073e5b59b3
Reviewed-on: https://go-review.googlesource.com/3509Reviewed-by: 's avatarRob Pike <r@golang.org>
parent b28802d2
......@@ -1473,3 +1473,22 @@ func TestFuzzOneByte(t *testing.T) {
}
}
}
// Don't crash, just give error with invalid type id.
// Issue 9649.
func TestErrorInvalidTypeId(t *testing.T) {
data := []byte{0x01, 0x00, 0x01, 0x00}
d := NewDecoder(bytes.NewReader(data))
// When running d.Decode(&foo) the first time the decoder stops
// after []byte{0x01, 0x00} and reports an errBadType. Running
// d.Decode(&foo) again on exactly the same input sequence should
// give another errBadType, but instead caused a panic because
// decoderMap wasn't cleaned up properly after the first error.
for i := 0; i < 2; i++ {
var foo struct{}
err := d.Decode(&foo)
if err != errBadType {
t.Fatal("decode: expected %s, got %s", errBadType, err)
}
}
}
......@@ -1051,6 +1051,7 @@ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err
// compileDec compiles the decoder engine for a value. If the value is not a struct,
// it calls out to compileSingle.
func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) {
defer catchError(&err)
rt := ut.base
srt := rt
if srt.Kind() != reflect.Struct || ut.externalDec != 0 {
......@@ -1163,8 +1164,9 @@ func (dec *Decoder) decodeValue(wireId typeId, value reflect.Value) {
value = decAlloc(value)
engine := *enginePtr
if st := base; st.Kind() == reflect.Struct && ut.externalDec == 0 {
wt := dec.wireType[wireId]
if engine.numInstr == 0 && st.NumField() > 0 &&
dec.wireType[wireId] != nil && len(dec.wireType[wireId].StructT.Field) > 0 {
wt != nil && len(wt.StructT.Field) > 0 {
name := base.Name()
errorf("type mismatch: no fields matched compiling decoder for %s", name)
}
......
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