From 9ec32a9e7b2a39103c905d57e270d99463e6aa99 Mon Sep 17 00:00:00 2001 From: Or Neeman Date: Thu, 18 Feb 2021 03:19:49 -0600 Subject: [PATCH] rlp: handle case of normal EOF in Stream.readFull (#22336) io.Reader may return n > 0 and io.EOF at the end of the input stream. readFull did not handle this correctly, looking only at the error. This fixes it to check for n == len(buf) as well. --- rlp/decode.go | 8 +++++++- rlp/decode_test.go | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/rlp/decode.go b/rlp/decode.go index 5f3f5eedfd..79b7ef0626 100644 --- a/rlp/decode.go +++ b/rlp/decode.go @@ -952,7 +952,13 @@ func (s *Stream) readFull(buf []byte) (err error) { n += nn } if err == io.EOF { - err = io.ErrUnexpectedEOF + if n < len(buf) { + err = io.ErrUnexpectedEOF + } else { + // Readers are allowed to give EOF even though the read succeeded. + // In such cases, we discard the EOF, like io.ReadFull() does. + err = nil + } } return err } diff --git a/rlp/decode_test.go b/rlp/decode_test.go index 167e9974b9..d94c3969b2 100644 --- a/rlp/decode_test.go +++ b/rlp/decode_test.go @@ -665,6 +665,26 @@ func TestDecodeWithByteReader(t *testing.T) { }) } +func testDecodeWithEncReader(t *testing.T, n int) { + s := strings.Repeat("0", n) + _, r, _ := EncodeToReader(s) + var decoded string + err := Decode(r, &decoded) + if err != nil { + t.Errorf("Unexpected decode error with n=%v: %v", n, err) + } + if decoded != s { + t.Errorf("Decode mismatch with n=%v", n) + } +} + +// This is a regression test checking that decoding from encReader +// works for RLP values of size 8192 bytes or more. +func TestDecodeWithEncReader(t *testing.T) { + testDecodeWithEncReader(t, 8188) // length with header is 8191 + testDecodeWithEncReader(t, 8189) // length with header is 8192 +} + // plainReader reads from a byte slice but does not // implement ReadByte. It is also not recognized by the // size validation. This is useful to test how the decoder