1
0
mirror of https://github.com/golang/go synced 2024-11-17 13:35:08 -07:00

encoding/gob: use saferio to read large buffer

Avoid allocating large amounts of memory for corrupt input.

No test case because the problem can only happen for invalid data.
Let the fuzzer find cases like this.

Fixes #53369

Change-Id: I67c5e75bf181ad84988d6d6da12507df0e6df8e8
Reviewed-on: https://go-review.googlesource.com/c/go/+/413979
Reviewed-by: Joseph Tsai <joetsai@digital-static.net>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Joedian Reid <joedian@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Ian Lance Taylor 2022-06-24 17:00:24 -07:00 committed by Gopher Robot
parent f324355d1f
commit dee9adc0f7
3 changed files with 14 additions and 17 deletions

View File

@ -57,17 +57,6 @@ func (d *decBuffer) Drop(n int) {
d.offset += n d.offset += n
} }
// Size grows the buffer to exactly n bytes, so d.Bytes() will
// return a slice of length n. Existing data is first discarded.
func (d *decBuffer) Size(n int) {
d.Reset()
if cap(d.data) < n {
d.data = make([]byte, n)
} else {
d.data = d.data[0:n]
}
}
func (d *decBuffer) ReadByte() (byte, error) { func (d *decBuffer) ReadByte() (byte, error) {
if d.offset >= len(d.data) { if d.offset >= len(d.data) {
return 0, io.EOF return 0, io.EOF
@ -85,6 +74,12 @@ func (d *decBuffer) Bytes() []byte {
return d.data[d.offset:] return d.data[d.offset:]
} }
// SetBytes sets the buffer to the bytes, discarding any existing data.
func (d *decBuffer) SetBytes(data []byte) {
d.data = data
d.offset = 0
}
func (d *decBuffer) Reset() { func (d *decBuffer) Reset() {
d.data = d.data[0:0] d.data = d.data[0:0]
d.offset = 0 d.offset = 0

View File

@ -7,6 +7,7 @@ package gob
import ( import (
"bufio" "bufio"
"errors" "errors"
"internal/saferio"
"io" "io"
"reflect" "reflect"
"sync" "sync"
@ -98,8 +99,9 @@ func (dec *Decoder) readMessage(nbytes int) {
panic("non-empty decoder buffer") panic("non-empty decoder buffer")
} }
// Read the data // Read the data
dec.buf.Size(nbytes) var buf []byte
_, dec.err = io.ReadFull(dec.r, dec.buf.Bytes()) buf, dec.err = saferio.ReadData(dec.r, uint64(nbytes))
dec.buf.SetBytes(buf)
if dec.err == io.EOF { if dec.err == io.EOF {
dec.err = io.ErrUnexpectedEOF dec.err = io.ErrUnexpectedEOF
} }

View File

@ -187,6 +187,9 @@ var depsRules = `
text/scanner, text/scanner,
text/tabwriter; text/tabwriter;
io, reflect
< internal/saferio;
# encodings # encodings
# core ones do not use fmt. # core ones do not use fmt.
io, strconv io, strconv
@ -200,7 +203,7 @@ var depsRules = `
fmt !< encoding/base32, encoding/base64; fmt !< encoding/base32, encoding/base64;
FMT, encoding/base32, encoding/base64 FMT, encoding/base32, encoding/base64, internal/saferio
< encoding/ascii85, encoding/csv, encoding/gob, encoding/hex, < encoding/ascii85, encoding/csv, encoding/gob, encoding/hex,
encoding/json, encoding/pem, encoding/xml, mime; encoding/json, encoding/pem, encoding/xml, mime;
@ -239,9 +242,6 @@ var depsRules = `
encoding/binary, regexp encoding/binary, regexp
< index/suffixarray; < index/suffixarray;
io, reflect
< internal/saferio;
# executable parsing # executable parsing
FMT, encoding/binary, compress/zlib, internal/saferio FMT, encoding/binary, compress/zlib, internal/saferio
< runtime/debug < runtime/debug