Commit 1f0f459a authored by David Symonds's avatar David Symonds

encoding/gob: more hardening for lengths of input strings.

Fixes #3160.

R=r
CC=golang-dev
https://golang.org/cl/5716046
parent 984780a5
...@@ -1455,11 +1455,14 @@ func TestFuzz(t *testing.T) { ...@@ -1455,11 +1455,14 @@ func TestFuzz(t *testing.T) {
func TestFuzzRegressions(t *testing.T) { func TestFuzzRegressions(t *testing.T) {
// An instance triggering a type name of length ~102 GB. // An instance triggering a type name of length ~102 GB.
testFuzz(t, 1328492090837718000, 100, new(float32)) testFuzz(t, 1328492090837718000, 100, new(float32))
// An instance triggering a type name of 1.6 GB.
// Commented out because it takes 5m to run.
//testFuzz(t, 1330522872628565000, 100, new(int))
} }
func testFuzz(t *testing.T, seed int64, n int, input ...interface{}) { func testFuzz(t *testing.T, seed int64, n int, input ...interface{}) {
t.Logf("seed=%d n=%d\n", seed, n)
for _, e := range input { for _, e := range input {
t.Logf("seed=%d n=%d e=%T", seed, n, e)
rng := rand.New(rand.NewSource(seed)) rng := rand.New(rand.NewSource(seed))
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
encFuzzDec(rng, e) encFuzzDec(rng, e)
......
...@@ -392,12 +392,12 @@ func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) { ...@@ -392,12 +392,12 @@ func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) {
} }
p = *(*unsafe.Pointer)(p) p = *(*unsafe.Pointer)(p)
} }
n := int(state.decodeUint()) n := state.decodeUint()
if n < 0 { if n > uint64(state.b.Len()) {
errorf("negative length decoding []byte") errorf("length of []byte exceeds input size (%d bytes)", n)
} }
slice := (*[]uint8)(p) slice := (*[]uint8)(p)
if cap(*slice) < n { if uint64(cap(*slice)) < n {
*slice = make([]uint8, n) *slice = make([]uint8, n)
} else { } else {
*slice = (*slice)[0:n] *slice = (*slice)[0:n]
...@@ -417,7 +417,11 @@ func decString(i *decInstr, state *decoderState, p unsafe.Pointer) { ...@@ -417,7 +417,11 @@ func decString(i *decInstr, state *decoderState, p unsafe.Pointer) {
} }
p = *(*unsafe.Pointer)(p) p = *(*unsafe.Pointer)(p)
} }
b := make([]byte, state.decodeUint()) n := state.decodeUint()
if n > uint64(state.b.Len()) {
errorf("string length exceeds input size (%d bytes)", n)
}
b := make([]byte, n)
state.b.Read(b) state.b.Read(b)
// It would be a shame to do the obvious thing here, // It would be a shame to do the obvious thing here,
// *(*string)(p) = string(b) // *(*string)(p) = string(b)
...@@ -647,7 +651,11 @@ func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) { ...@@ -647,7 +651,11 @@ func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) {
// decodeSlice decodes a slice and stores the slice header through p. // decodeSlice decodes a slice and stores the slice header through p.
// Slices are encoded as an unsigned length followed by the elements. // 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) { func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) {
n := int(uintptr(state.decodeUint())) 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 { if indir > 0 {
up := unsafe.Pointer(p) up := unsafe.Pointer(p)
if *(*unsafe.Pointer)(up) == nil { if *(*unsafe.Pointer)(up) == nil {
...@@ -702,6 +710,9 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p ui ...@@ -702,6 +710,9 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p ui
*(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData() *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData()
return return
} }
if len(name) > 1024 {
errorf("name too long (%d bytes): %.20q...", len(name), name)
}
// The concrete type must be registered. // The concrete type must be registered.
typ, ok := nameToConcreteType[name] typ, ok := nameToConcreteType[name]
if !ok { if !ok {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment