diff options
author | Felix Lange <fjl@twurst.com> | 2015-04-28 16:28:15 +0800 |
---|---|---|
committer | Felix Lange <fjl@twurst.com> | 2015-04-28 16:28:15 +0800 |
commit | dd49c8e43d394b78d97a4f7cf7a74ddadcda5323 (patch) | |
tree | acd3014c829b468c9762938e8a84827207dfa6be /rlp/decode.go | |
parent | b6ec1c720fc65d8bac36bd2e28bf1df1de1ffe5b (diff) | |
download | dexon-dd49c8e43d394b78d97a4f7cf7a74ddadcda5323.tar.gz dexon-dd49c8e43d394b78d97a4f7cf7a74ddadcda5323.tar.zst dexon-dd49c8e43d394b78d97a4f7cf7a74ddadcda5323.zip |
rlp: fix list bounds check overflow (found by go-fuzz)
The list size checking overflowed if the size information
for a value was bigger than the list. This is resolved by
always performing the check before reading.
Diffstat (limited to 'rlp/decode.go')
-rw-r--r-- | rlp/decode.go | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/rlp/decode.go b/rlp/decode.go index 6952ecaea..0c660426f 100644 --- a/rlp/decode.go +++ b/rlp/decode.go @@ -820,6 +820,16 @@ func (s *Stream) Kind() (kind Kind, size uint64, err error) { func (s *Stream) readKind() (kind Kind, size uint64, err error) { b, err := s.readByte() if err != nil { + if len(s.stack) == 0 { + // At toplevel, Adjust the error to actual EOF. io.EOF is + // used by callers to determine when to stop decoding. + switch err { + case io.ErrUnexpectedEOF: + err = io.EOF + case ErrValueTooLarge: + err = io.EOF + } + } return 0, 0, err } s.byteval = 0 @@ -876,9 +886,6 @@ func (s *Stream) readUint(size byte) (uint64, error) { return 0, nil case 1: b, err := s.readByte() - if err == io.EOF { - err = io.ErrUnexpectedEOF - } return uint64(b), err default: start := int(8 - size) @@ -899,10 +906,9 @@ func (s *Stream) readUint(size byte) (uint64, error) { } func (s *Stream) readFull(buf []byte) (err error) { - if s.limited && s.remaining < uint64(len(buf)) { - return ErrValueTooLarge + if err := s.willRead(uint64(len(buf))); err != nil { + return err } - s.willRead(uint64(len(buf))) var nn, n int for n < len(buf) && err == nil { nn, err = s.r.Read(buf[n:]) @@ -915,23 +921,32 @@ func (s *Stream) readFull(buf []byte) (err error) { } func (s *Stream) readByte() (byte, error) { - if s.limited && s.remaining == 0 { - return 0, io.EOF + if err := s.willRead(1); err != nil { + return 0, err } - s.willRead(1) b, err := s.r.ReadByte() - if len(s.stack) > 0 && err == io.EOF { + if err == io.EOF { err = io.ErrUnexpectedEOF } return b, err } -func (s *Stream) willRead(n uint64) { +func (s *Stream) willRead(n uint64) error { s.kind = -1 // rearm Kind - if s.limited { - s.remaining -= n - } + if len(s.stack) > 0 { + // check list overflow + tos := s.stack[len(s.stack)-1] + if n > tos.size-tos.pos { + return ErrElemTooLarge + } s.stack[len(s.stack)-1].pos += n } + if s.limited { + if n > s.remaining { + return ErrValueTooLarge + } + s.remaining -= n + } + return nil } |