From d9421cec00a5e171699b00966bebc85a36593bf2 Mon Sep 17 00:00:00 2001 From: Alexander Yastrebov Date: Sat, 16 Oct 2021 02:19:20 +0000 Subject: [PATCH] net/http/internal: return unexpected EOF on incomplete chunk read MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Fixes #48861 Change-Id: I3f55bfbdc4f2cf5b33d1ab2d76e01335bb497c6f GitHub-Last-Rev: 0ecd790b87ddd31d0cf08e8f2726f918a2edd1fb GitHub-Pull-Request: golang/go#48903 Reviewed-on: https://go-review.googlesource.com/c/go/+/355029 Trust: Damien Neil Trust: Daniel Martí Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Damien Neil --- src/net/http/internal/chunked.go | 7 +++++++ src/net/http/internal/chunked_test.go | 28 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go index 923e6a6d2c..37a72e9031 100644 --- a/src/net/http/internal/chunked.go +++ b/src/net/http/internal/chunked.go @@ -81,6 +81,11 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err error) { cr.err = errors.New("malformed chunked encoding") break } + } else { + if cr.err == io.EOF { + cr.err = io.ErrUnexpectedEOF + } + break } cr.checkEnd = false } @@ -109,6 +114,8 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err error) { // bytes to verify they are "\r\n". if cr.n == 0 && cr.err == nil { cr.checkEnd = true + } else if cr.err == io.EOF { + cr.err = io.ErrUnexpectedEOF } } return n, cr.err diff --git a/src/net/http/internal/chunked_test.go b/src/net/http/internal/chunked_test.go index 08152ed1e2..5e29a786dd 100644 --- a/src/net/http/internal/chunked_test.go +++ b/src/net/http/internal/chunked_test.go @@ -11,6 +11,7 @@ import ( "io" "strings" "testing" + "testing/iotest" ) func TestChunk(t *testing.T) { @@ -211,3 +212,30 @@ func TestChunkReadPartial(t *testing.T) { } } + +// Issue 48861: ChunkedReader should report incomplete chunks +func TestIncompleteChunk(t *testing.T) { + const valid = "4\r\nabcd\r\n" + "5\r\nabc\r\n\r\n" + "0\r\n" + + for i := 0; i < len(valid); i++ { + incomplete := valid[:i] + r := NewChunkedReader(strings.NewReader(incomplete)) + if _, err := io.ReadAll(r); err != io.ErrUnexpectedEOF { + t.Errorf("expected io.ErrUnexpectedEOF for %q, got %v", incomplete, err) + } + } + + r := NewChunkedReader(strings.NewReader(valid)) + if _, err := io.ReadAll(r); err != nil { + t.Errorf("unexpected error for %q: %v", valid, err) + } +} + +func TestChunkEndReadError(t *testing.T) { + readErr := fmt.Errorf("chunk end read error") + + r := NewChunkedReader(io.MultiReader(strings.NewReader("4\r\nabcd"), iotest.ErrReader(readErr))) + if _, err := io.ReadAll(r); err != readErr { + t.Errorf("expected %v, got %v", readErr, err) + } +} -- 2.48.1