binary: prevent runaway alloc
This commit is contained in:
parent
b02f088cc7
commit
b3b6bfb312
|
@ -1,21 +1,35 @@
|
||||||
package binary
|
package binary
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
. "github.com/tendermint/tendermint/common"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ByteSliceChunk = 1024
|
||||||
|
)
|
||||||
|
|
||||||
func WriteByteSlice(bz []byte, w io.Writer, n *int64, err *error) {
|
func WriteByteSlice(bz []byte, w io.Writer, n *int64, err *error) {
|
||||||
WriteUvarint(uint(len(bz)), w, n, err)
|
WriteUvarint(uint(len(bz)), w, n, err)
|
||||||
WriteTo(bz, w, n, err)
|
WriteTo(bz, w, n, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadByteSlice(r io.Reader, n *int64, err *error) []byte {
|
func ReadByteSlice(r io.Reader, n *int64, err *error) []byte {
|
||||||
length := ReadUvarint(r, n, err)
|
length := int(ReadUvarint(r, n, err))
|
||||||
if *err != nil {
|
if *err != nil {
|
||||||
return 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
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,10 @@ import (
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ReflectSliceChunk = 1024
|
||||||
|
)
|
||||||
|
|
||||||
type TypeInfo struct {
|
type TypeInfo struct {
|
||||||
Type reflect.Type // The type
|
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)
|
log.Debug("Read byteslice", "bytes", byteslice)
|
||||||
rv.Set(reflect.ValueOf(byteslice))
|
rv.Set(reflect.ValueOf(byteslice))
|
||||||
} else {
|
} else {
|
||||||
|
var sliceRv reflect.Value
|
||||||
// Read length
|
// Read length
|
||||||
length := int(ReadUvarint(r, n, err))
|
length := int(ReadUvarint(r, n, err))
|
||||||
log.Debug(Fmt("Read length: %v", length))
|
log.Debug(Fmt("Read length: %v", length))
|
||||||
sliceRv := reflect.MakeSlice(rt, length, length)
|
sliceRv = reflect.MakeSlice(rt, 0, 0)
|
||||||
// Read elems
|
// read one ReflectSliceChunk at a time and append
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i*ReflectSliceChunk < length; i++ {
|
||||||
elemRv := sliceRv.Index(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)
|
readReflect(elemRv, elemRt, r, n, err)
|
||||||
|
if *err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
sliceRv = reflect.AppendSlice(sliceRv, tmpSliceRv)
|
||||||
|
}
|
||||||
|
|
||||||
rv.Set(sliceRv)
|
rv.Set(sliceRv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
. "github.com/tendermint/tendermint/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SimpleStruct struct {
|
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