diff options
Diffstat (limited to 'libgo/go/encoding')
-rw-r--r-- | libgo/go/encoding/binary/varint.go | 2 | ||||
-rw-r--r-- | libgo/go/encoding/gob/decode.go | 6 | ||||
-rw-r--r-- | libgo/go/encoding/gob/doc.go | 2 | ||||
-rw-r--r-- | libgo/go/encoding/gob/encoder_test.go | 29 | ||||
-rw-r--r-- | libgo/go/encoding/gob/type.go | 18 | ||||
-rw-r--r-- | libgo/go/encoding/json/encode.go | 2 |
6 files changed, 52 insertions, 7 deletions
diff --git a/libgo/go/encoding/binary/varint.go b/libgo/go/encoding/binary/varint.go index b756afdd040..719018b6033 100644 --- a/libgo/go/encoding/binary/varint.go +++ b/libgo/go/encoding/binary/varint.go @@ -123,7 +123,7 @@ func ReadUvarint(r io.ByteReader) (uint64, error) { panic("unreachable") } -// ReadVarint reads an encoded unsigned integer from r and returns it as a uint64. +// ReadVarint reads an encoded unsigned integer from r and returns it as an int64. func ReadVarint(r io.ByteReader) (int64, error) { ux, err := ReadUvarint(r) // ok to continue in presence of error x := int64(ux >> 1) diff --git a/libgo/go/encoding/gob/decode.go b/libgo/go/encoding/gob/decode.go index e32a178aba3..8690b35d714 100644 --- a/libgo/go/encoding/gob/decode.go +++ b/libgo/go/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/libgo/go/encoding/gob/doc.go b/libgo/go/encoding/gob/doc.go index 821d9a3fe8e..6d77c171f41 100644 --- a/libgo/go/encoding/gob/doc.go +++ b/libgo/go/encoding/gob/doc.go @@ -118,7 +118,7 @@ elements using the standard gob encoding for their type, recursively. Maps are sent as an unsigned count followed by that many key, element pairs. Empty but non-nil maps are sent, so if the sender has allocated -a map, the receiver will allocate a map even no elements are +a map, the receiver will allocate a map even if no elements are transmitted. Structs are sent as a sequence of (field number, field value) pairs. The field diff --git a/libgo/go/encoding/gob/encoder_test.go b/libgo/go/encoding/gob/encoder_test.go index c4947cbb8d3..db824d99917 100644 --- a/libgo/go/encoding/gob/encoder_test.go +++ b/libgo/go/encoding/gob/encoder_test.go @@ -736,3 +736,32 @@ func TestPtrToMapOfMap(t *testing.T) { t.Fatalf("expected %v got %v", data, newData) } } + +// 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 + } +} diff --git a/libgo/go/encoding/gob/type.go b/libgo/go/encoding/gob/type.go index 0dd7a0a770e..a8ee2fa4a5a 100644 --- a/libgo/go/encoding/gob/type.go +++ b/libgo/go/encoding/gob/type.go @@ -749,12 +749,28 @@ func Register(value interface{}) { rt := reflect.TypeOf(value) name := rt.String() - // But for named types (or pointers to them), qualify with import path. + // But for named types (or pointers to them), qualify with import path (but see inner comment). // Dereference one pointer looking for a named type. star := "" if rt.Name() == "" { if pt := rt; pt.Kind() == reflect.Ptr { star = "*" + // NOTE: The following line should be rt = pt.Elem() to implement + // what the comment above claims, but fixing it would break compatibility + // with existing gobs. + // + // Given package p imported as "full/p" with these definitions: + // package p + // type T1 struct { ... } + // this table shows the intended and actual strings used by gob to + // name the types: + // + // Type Correct string Actual string + // + // T1 full/p.T1 full/p.T1 + // *T1 *full/p.T1 *p.T1 + // + // The missing full path cannot be fixed without breaking existing gob decoders. rt = pt } } diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go index b6e1cb16e5a..d2c1c4424c7 100644 --- a/libgo/go/encoding/json/encode.go +++ b/libgo/go/encoding/json/encode.go @@ -55,7 +55,7 @@ import ( // nil pointer or interface value, and any array, slice, map, or string of // length zero. The object's default key string is the struct field name // but can be specified in the struct field's tag value. The "json" key in -// struct field's tag value is the key name, followed by an optional comma +// the struct field's tag value is the key name, followed by an optional comma // and options. Examples: // // // Field is ignored by this package. |