aboutsummaryrefslogtreecommitdiff
path: root/src/encoding
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2022-09-22 21:17:05 -0700
committerGopher Robot <gobot@golang.org>2022-09-25 01:18:43 +0000
commita0441c7ae3dea57a0553c9ea77e184c34b7da40f (patch)
treefb5c5f7313d43568152335a5570da5665057dede /src/encoding
parent336ce966e439a269fe5088cc7564181c5b866b61 (diff)
downloadgo-a0441c7ae3dea57a0553c9ea77e184c34b7da40f.tar.xz
encoding/gob: use saferio.SliceCap when decoding a slice
This avoids allocating an overly large slice for corrupt input. Change the saferio.SliceCap function to take a pointer to the element type, so that we can handle slices of interface types. This revealed that a couple of existing calls were actually incorrect, passing the slice type rather than the element type. No test case because the problem can only happen for invalid data. Let the fuzzer find cases like this. Fixes #55338 Change-Id: I3c1724183cc275d4981379773b0b8faa01a9cbd2 Reviewed-on: https://go-review.googlesource.com/c/go/+/433296 Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Daniel Martí <mvdan@mvdan.cc> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
Diffstat (limited to 'src/encoding')
-rw-r--r--src/encoding/gob/decode.go19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go
index 470e357b10..480832ca4f 100644
--- a/src/encoding/gob/decode.go
+++ b/src/encoding/gob/decode.go
@@ -9,6 +9,7 @@ package gob
import (
"encoding"
"errors"
+ "internal/saferio"
"io"
"math"
"math/bits"
@@ -514,10 +515,22 @@ func (dec *Decoder) decodeArrayHelper(state *decoderState, value reflect.Value,
}
instr := &decInstr{elemOp, 0, nil, ovfl}
isPtr := value.Type().Elem().Kind() == reflect.Pointer
+ ln := value.Len()
for i := 0; i < length; i++ {
if state.b.Len() == 0 {
errorf("decoding array or slice: length exceeds input size (%d elements)", length)
}
+ if i >= ln {
+ // This is a slice that we only partially allocated.
+ // Grow it using append, up to length.
+ value = reflect.Append(value, reflect.Zero(value.Type().Elem()))
+ cp := value.Cap()
+ if cp > length {
+ cp = length
+ }
+ value.SetLen(cp)
+ ln = cp
+ }
v := value.Index(i)
if isPtr {
v = decAlloc(v)
@@ -618,7 +631,11 @@ func (dec *Decoder) decodeSlice(state *decoderState, value reflect.Value, elemOp
errorf("%s slice too big: %d elements of %d bytes", typ.Elem(), u, size)
}
if value.Cap() < n {
- value.Set(reflect.MakeSlice(typ, n, n))
+ safe := saferio.SliceCap(reflect.Zero(reflect.PtrTo(typ.Elem())).Interface(), uint64(n))
+ if safe < 0 {
+ errorf("%s slice too big: %d elements of %d bytes", typ.Elem(), u, size)
+ }
+ value.Set(reflect.MakeSlice(typ, safe, safe))
} else {
value.SetLen(n)
}