Skip to content

Commit 0c8fe34

Browse files
committed
encoding/gob: more cleanups handling slice length
Fix the other places the slice length was being believed, and refactor the code to use a single function to unify the check. Fixes #10273. Change-Id: Ia62b25203fbe87c95d71a70ebc1db8d202eaa4a4 Reviewed-on: https://go-review.googlesource.com/8511 Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent d3252a2 commit 0c8fe34

File tree

2 files changed

+38
-20
lines changed

2 files changed

+38
-20
lines changed

src/encoding/gob/decode.go

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,17 @@ func (state *decoderState) decodeInt() int64 {
182182
return int64(x >> 1)
183183
}
184184

185+
// getLength decodes the next uint and makes sure it is a possible
186+
// size for a data item that follows, which means it must fit in a
187+
// non-negative int and fit in the buffer.
188+
func (state *decoderState) getLength() (int, bool) {
189+
n := int(state.decodeUint())
190+
if n < 0 || state.b.Len() < n || tooBig <= n {
191+
return 0, false
192+
}
193+
return n, true
194+
}
195+
185196
// decOp is the signature of a decoding operator for a given type.
186197
type decOp func(i *decInstr, state *decoderState, v reflect.Value)
187198

@@ -363,16 +374,9 @@ func decComplex128(i *decInstr, state *decoderState, value reflect.Value) {
363374
// describing the data.
364375
// uint8 slices are encoded as an unsigned count followed by the raw bytes.
365376
func decUint8Slice(i *decInstr, state *decoderState, value reflect.Value) {
366-
u := state.decodeUint()
367-
n := int(u)
368-
if n < 0 || uint64(n) != u {
369-
errorf("length of %s exceeds input size (%d bytes)", value.Type(), u)
370-
}
371-
if n > state.b.Len() {
372-
errorf("%s data too long for buffer: %d", value.Type(), n)
373-
}
374-
if n > tooBig {
375-
errorf("byte slice too big: %d", n)
377+
n, ok := state.getLength()
378+
if !ok {
379+
errorf("bad %s slice length: %d", value.Type(), n)
376380
}
377381
if value.Cap() < n {
378382
value.Set(reflect.MakeSlice(value.Type(), n, n))
@@ -388,13 +392,9 @@ func decUint8Slice(i *decInstr, state *decoderState, value reflect.Value) {
388392
// describing the data.
389393
// Strings are encoded as an unsigned count followed by the raw bytes.
390394
func decString(i *decInstr, state *decoderState, value reflect.Value) {
391-
u := state.decodeUint()
392-
n := int(u)
393-
if n < 0 || uint64(n) != u || n > state.b.Len() {
394-
errorf("length of %s exceeds input size (%d bytes)", value.Type(), u)
395-
}
396-
if n > state.b.Len() {
397-
errorf("%s data too long for buffer: %d", value.Type(), n)
395+
n, ok := state.getLength()
396+
if !ok {
397+
errorf("bad %s slice length: %d", value.Type(), n)
398398
}
399399
// Read the data.
400400
data := make([]byte, n)
@@ -406,7 +406,11 @@ func decString(i *decInstr, state *decoderState, value reflect.Value) {
406406

407407
// ignoreUint8Array skips over the data for a byte slice value with no destination.
408408
func ignoreUint8Array(i *decInstr, state *decoderState, value reflect.Value) {
409-
b := make([]byte, state.decodeUint())
409+
n, ok := state.getLength()
410+
if !ok {
411+
errorf("slice length too large")
412+
}
413+
b := make([]byte, n)
410414
state.b.Read(b)
411415
}
412416

@@ -688,8 +692,8 @@ func (dec *Decoder) ignoreInterface(state *decoderState) {
688692
error_(dec.err)
689693
}
690694
// At this point, the decoder buffer contains a delimited value. Just toss it.
691-
n := int(state.decodeUint())
692-
if n < 0 || state.b.Len() < n {
695+
n, ok := state.getLength()
696+
if !ok {
693697
errorf("bad interface encoding: length too large for buffer")
694698
}
695699
state.b.Drop(n)

src/encoding/gob/encoder_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,3 +968,17 @@ func TestErrorBadDrop(t *testing.T) {
968968
t.Fatalf("decode: expected interface encoding error, got %s", err.Error())
969969
}
970970
}
971+
972+
// Don't crash, just give error with corrupted slice.
973+
// Issue 10273.
974+
func TestErrorBadSliceLength(t *testing.T) {
975+
data := []byte{0x13, 0x0a, 0x00, 0xfb, 0x5d, 0xad, 0x0b, 0xf8, 0xff, 0x02, 0x02, 0x63, 0xe7, 0x00, 0x02, 0xfa, 0x28, 0x02, 0x02, 0x02, 0xa8, 0x98, 0x59}
976+
d := NewDecoder(bytes.NewReader(data))
977+
err := d.Decode(nil)
978+
if err == nil {
979+
t.Fatal("decode: no error")
980+
}
981+
if !strings.Contains(err.Error(), "slice length too large") {
982+
t.Fatalf("decode: expected slice length too large error, got %s", err.Error())
983+
}
984+
}

0 commit comments

Comments
 (0)