From: Rob Pike Date: Thu, 12 Jul 2012 17:23:54 +0000 (-0700) Subject: encoding/gob: fix check for short input in slice decode X-Git-Tag: go1.1rc2~2815 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=1fa32d21a947dbe00217baa5ff22a27dd54fbb9f;p=gostls13.git encoding/gob: fix check for short input in slice decode R=golang-dev, dsymonds, r, nigeltao CC=golang-dev https://golang.org/cl/6374059 --- diff --git a/src/pkg/encoding/gob/decode.go b/src/pkg/encoding/gob/decode.go index e32a178aba..8690b35d71 100644 --- a/src/pkg/encoding/gob/decode.go +++ b/src/pkg/encoding/gob/decode.go @@ -562,6 +562,9 @@ func (dec *Decoder) ignoreSingle(engine *decEngine) { func (dec *Decoder) decodeArrayHelper(state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) { instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl} for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding array or slice: length exceeds input size (%d elements)", length) + } up := unsafe.Pointer(p) if elemIndir > 1 { up = decIndirect(up, elemIndir) @@ -652,9 +655,6 @@ func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) { // Slices are encoded as an unsigned length followed by the elements. func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) { nr := state.decodeUint() - if nr > uint64(state.b.Len()) { - errorf("length of slice exceeds input size (%d elements)", nr) - } n := int(nr) if indir > 0 { up := unsafe.Pointer(p) diff --git a/src/pkg/encoding/gob/encoder_test.go b/src/pkg/encoding/gob/encoder_test.go index 35ca6cacea..b684772c69 100644 --- a/src/pkg/encoding/gob/encoder_test.go +++ b/src/pkg/encoding/gob/encoder_test.go @@ -813,3 +813,32 @@ func TestMutipleEncodingsOfBadType(t *testing.T) { t.Errorf("expected error about no exported fields; got %v", err) } } + +// There was an error check comparing the length of the input with the +// length of the slice being decoded. It was wrong because the next +// thing in the input might be a type definition, which would lead to +// an incorrect length check. This test reproduces the corner case. + +type Z struct { +} + +func Test29ElementSlice(t *testing.T) { + Register(Z{}) + src := make([]interface{}, 100) // Size needs to be bigger than size of type definition. + for i := range src { + src[i] = Z{} + } + buf := new(bytes.Buffer) + err := NewEncoder(buf).Encode(src) + if err != nil { + t.Fatalf("encode: %v", err) + return + } + + var dst []interface{} + err = NewDecoder(buf).Decode(&dst) + if err != nil { + t.Errorf("decode: %v", err) + return + } +}