diff --git a/decoder.go b/decoder.go index 6109539..c093fd6 100644 --- a/decoder.go +++ b/decoder.go @@ -245,12 +245,18 @@ func (dec *Decoder) ReadLength() (length int, err error) { if err != nil { return 0, err } + if val > math.MaxInt { + return 0, io.ErrUnexpectedEOF + } length = int(val) case EncodingBorsh: val, err := dec.ReadUint32(LE) if err != nil { return 0, err } + if uint64(val) > math.MaxInt { + return 0, io.ErrUnexpectedEOF + } length = int(val) case EncodingCompactU16: val, err := DecodeCompactU16LengthFromByteReader(dec) diff --git a/decoder_bin.go b/decoder_bin.go index 0c5e056..d4b12d9 100644 --- a/decoder_bin.go +++ b/decoder_bin.go @@ -20,6 +20,7 @@ package bin import ( "encoding/binary" "fmt" + "io" "reflect" "go.uber.org/zap" @@ -169,18 +170,21 @@ func (dec *Decoder) decodeBin(rv reflect.Value, opt *option) (err error) { if opt.hasSizeOfSlice() { l = opt.getSizeOfSlice() } else { - // TODO: what type is length? Is it really Uvarint64? - length, err := dec.ReadUvarint64() + length, err := dec.ReadLength() if err != nil { return err } - l = int(length) + l = length } if traceEnabled { zlog.Debug("reading slice", zap.Int("len", l), typeField("type", rv)) } + if l > dec.Remaining() { + return io.ErrUnexpectedEOF + } + rv.Set(reflect.MakeSlice(rt, l, l)) for i := 0; i < l; i++ { if err = dec.decodeBin(rv.Index(i), nil); err != nil { @@ -194,8 +198,7 @@ func (dec *Decoder) decodeBin(rv reflect.Value, opt *option) (err error) { } case reflect.Map: - // TODO: what type is length? Is it really Uvarint64? - l, err := dec.ReadUvarint64() + l, err := dec.ReadLength() if err != nil { return err } diff --git a/decoder_borsh.go b/decoder_borsh.go index fa2c4b1..4da42b5 100644 --- a/decoder_borsh.go +++ b/decoder_borsh.go @@ -20,6 +20,7 @@ package bin import ( "errors" "fmt" + "io" "reflect" "go.uber.org/zap" @@ -200,6 +201,9 @@ func (dec *Decoder) decodeBorsh(rv reflect.Value, opt *option) (err error) { // Empty slices are left nil return } + if l > dec.Remaining() { + return io.ErrUnexpectedEOF + } rv.Set(reflect.MakeSlice(rt, l, l)) for i := 0; i < l; i++ { diff --git a/decoder_compact-u16.go b/decoder_compact-u16.go index a4f7ec9..a7d4519 100644 --- a/decoder_compact-u16.go +++ b/decoder_compact-u16.go @@ -19,6 +19,7 @@ package bin import ( "fmt" + "io" "reflect" "go.uber.org/zap" @@ -179,6 +180,10 @@ func (dec *Decoder) decodeCompactU16(rv reflect.Value, opt *option) (err error) zlog.Debug("reading slice", zap.Int("len", l), typeField("type", rv)) } + if l > dec.Remaining() { + return io.ErrUnexpectedEOF + } + rv.Set(reflect.MakeSlice(rt, l, l)) for i := 0; i < l; i++ { if err = dec.decodeCompactU16(rv.Index(i), nil); err != nil { diff --git a/decoder_test.go b/decoder_test.go index bf9c1f4..a148e98 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -599,7 +599,16 @@ func TestDecoder_Slice_Err(t *testing.T) { decoder = NewBinDecoder(buf) err = decoder.Decode(&s) - assert.EqualError(t, err, "decode: uint64 required [8] bytes, remaining [0]") + assert.EqualError(t, err, "unexpected EOF") +} + +func TestDecoder_Slice_InvalidLen(t *testing.T) { + buf := []byte{0xd7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01} + + decoder := NewBinDecoder(buf) + var s []string + err := decoder.Decode(&s) + assert.EqualError(t, err, "unexpected EOF") } func TestDecoder_Int64(t *testing.T) {