binary: prevent runaway alloc
This commit is contained in:
parent
b02f088cc7
commit
b3b6bfb312
|
@ -1,21 +1,35 @@
|
|||
package binary
|
||||
|
||||
import (
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
ByteSliceChunk = 1024
|
||||
)
|
||||
|
||||
func WriteByteSlice(bz []byte, w io.Writer, n *int64, err *error) {
|
||||
WriteUvarint(uint(len(bz)), w, n, err)
|
||||
WriteTo(bz, w, n, err)
|
||||
}
|
||||
|
||||
func ReadByteSlice(r io.Reader, n *int64, err *error) []byte {
|
||||
length := ReadUvarint(r, n, err)
|
||||
length := int(ReadUvarint(r, n, err))
|
||||
if *err != nil {
|
||||
return nil
|
||||
}
|
||||
buf := make([]byte, int(length))
|
||||
ReadFull(buf, r, n, err)
|
||||
|
||||
var buf, tmpBuf []byte
|
||||
// read one ByteSliceChunk at a time and append
|
||||
for i := 0; i*ByteSliceChunk < length; i++ {
|
||||
tmpBuf = make([]byte, MinInt(ByteSliceChunk, length-i*ByteSliceChunk))
|
||||
ReadFull(tmpBuf, r, n, err)
|
||||
if *err != nil {
|
||||
return nil
|
||||
}
|
||||
buf = append(buf, tmpBuf...)
|
||||
}
|
||||
return buf
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@ import (
|
|||
. "github.com/tendermint/tendermint/common"
|
||||
)
|
||||
|
||||
const (
|
||||
ReflectSliceChunk = 1024
|
||||
)
|
||||
|
||||
type TypeInfo struct {
|
||||
Type reflect.Type // The type
|
||||
|
||||
|
@ -221,15 +225,25 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *
|
|||
log.Debug("Read byteslice", "bytes", byteslice)
|
||||
rv.Set(reflect.ValueOf(byteslice))
|
||||
} else {
|
||||
var sliceRv reflect.Value
|
||||
// Read length
|
||||
length := int(ReadUvarint(r, n, err))
|
||||
log.Debug(Fmt("Read length: %v", length))
|
||||
sliceRv := reflect.MakeSlice(rt, length, length)
|
||||
// Read elems
|
||||
for i := 0; i < length; i++ {
|
||||
elemRv := sliceRv.Index(i)
|
||||
readReflect(elemRv, elemRt, r, n, err)
|
||||
sliceRv = reflect.MakeSlice(rt, 0, 0)
|
||||
// read one ReflectSliceChunk at a time and append
|
||||
for i := 0; i*ReflectSliceChunk < length; i++ {
|
||||
l := MinInt(ReflectSliceChunk, length-i*ReflectSliceChunk)
|
||||
tmpSliceRv := reflect.MakeSlice(rt, l, l)
|
||||
for j := 0; j < l; j++ {
|
||||
elemRv := tmpSliceRv.Index(j)
|
||||
readReflect(elemRv, elemRt, r, n, err)
|
||||
if *err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
sliceRv = reflect.AppendSlice(sliceRv, tmpSliceRv)
|
||||
}
|
||||
|
||||
rv.Set(sliceRv)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
)
|
||||
|
||||
type SimpleStruct struct {
|
||||
|
@ -447,3 +449,17 @@ func TestJSONFieldNames(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func TestBadAlloc(t *testing.T) {
|
||||
n, err := new(int64), new(error)
|
||||
instance := new([]byte)
|
||||
data := RandBytes(ByteSliceChunk * 100)
|
||||
b := new(bytes.Buffer)
|
||||
// this slice of data claims to be much bigger than it really is
|
||||
WriteUvarint(uint(10000000000000000), b, n, err)
|
||||
b.Write(data)
|
||||
res := ReadBinary(instance, b, n, err)
|
||||
fmt.Println(res, *err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue