Skip to content

Commit 8e6cf5f

Browse files
osocuriosorobpike
authored andcommitted
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/3509 Reviewed-by: Rob Pike <[email protected]>
1 parent b28802d commit 8e6cf5f

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

src/encoding/gob/codec_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,3 +1473,22 @@ func TestFuzzOneByte(t *testing.T) {
14731473
}
14741474
}
14751475
}
1476+
1477+
// Don't crash, just give error with invalid type id.
1478+
// Issue 9649.
1479+
func TestErrorInvalidTypeId(t *testing.T) {
1480+
data := []byte{0x01, 0x00, 0x01, 0x00}
1481+
d := NewDecoder(bytes.NewReader(data))
1482+
// When running d.Decode(&foo) the first time the decoder stops
1483+
// after []byte{0x01, 0x00} and reports an errBadType. Running
1484+
// d.Decode(&foo) again on exactly the same input sequence should
1485+
// give another errBadType, but instead caused a panic because
1486+
// decoderMap wasn't cleaned up properly after the first error.
1487+
for i := 0; i < 2; i++ {
1488+
var foo struct{}
1489+
err := d.Decode(&foo)
1490+
if err != errBadType {
1491+
t.Fatal("decode: expected %s, got %s", errBadType, err)
1492+
}
1493+
}
1494+
}

src/encoding/gob/decode.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,7 @@ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err
10511051
// compileDec compiles the decoder engine for a value. If the value is not a struct,
10521052
// it calls out to compileSingle.
10531053
func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) {
1054+
defer catchError(&err)
10541055
rt := ut.base
10551056
srt := rt
10561057
if srt.Kind() != reflect.Struct || ut.externalDec != 0 {
@@ -1163,8 +1164,9 @@ func (dec *Decoder) decodeValue(wireId typeId, value reflect.Value) {
11631164
value = decAlloc(value)
11641165
engine := *enginePtr
11651166
if st := base; st.Kind() == reflect.Struct && ut.externalDec == 0 {
1167+
wt := dec.wireType[wireId]
11661168
if engine.numInstr == 0 && st.NumField() > 0 &&
1167-
dec.wireType[wireId] != nil && len(dec.wireType[wireId].StructT.Field) > 0 {
1169+
wt != nil && len(wt.StructT.Field) > 0 {
11681170
name := base.Name()
11691171
errorf("type mismatch: no fields matched compiling decoder for %s", name)
11701172
}

0 commit comments

Comments
 (0)