diff options
-rw-r--r-- | src/encoding/gob/codec_test.go | 19 | ||||
-rw-r--r-- | src/encoding/gob/decode.go | 4 |
2 files changed, 22 insertions, 1 deletions
diff --git a/src/encoding/gob/codec_test.go b/src/encoding/gob/codec_test.go index 56a7298fa5..c2583bfee3 100644 --- a/src/encoding/gob/codec_test.go +++ b/src/encoding/gob/codec_test.go @@ -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) + } + } +} diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go index f1c597086d..3f34cbac57 100644 --- a/src/encoding/gob/decode.go +++ b/src/encoding/gob/decode.go @@ -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) } |