]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/gob: clean up decoderMap after errBadType
authorHÃ¥vard Haugen <havard.haugen@gmail.com>
Wed, 28 Jan 2015 22:07:05 +0000 (23:07 +0100)
committerRob Pike <r@golang.org>
Wed, 8 Apr 2015 21:28:24 +0000 (21:28 +0000)
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/3509
Reviewed-by: Rob Pike <r@golang.org>
src/encoding/gob/codec_test.go
src/encoding/gob/decode.go

index 56a7298fa5583603fa22c68423850830c714eba0..c2583bfee337d18fbe4971dbbff005419805b5c8 100644 (file)
@@ -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)
+               }
+       }
+}
index f1c597086d4e0995bd1b6bd06025253725dca35b..3f34cbac570200cfc638bf49b6e2ec27649588e6 100644 (file)
@@ -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)
                }