From 1af6e9044268a3d741d17bb9ec1984ae819b0b40 Mon Sep 17 00:00:00 2001 From: Frederic BIDON Date: Thu, 7 Dec 2023 17:00:55 +0100 Subject: [PATCH] added check to prevent HasContent() to panic after the reader is closed * fixes #268 Signed-off-by: Frederic BIDON --- request.go | 7 +++++++ request_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/request.go b/request.go index 8c322af..3b9e983 100644 --- a/request.go +++ b/request.go @@ -16,6 +16,7 @@ package runtime import ( "bufio" + "errors" "io" "net/http" "strings" @@ -96,10 +97,16 @@ func (p *peekingReader) Read(d []byte) (int, error) { if p == nil { return 0, io.EOF } + if p.underlying == nil { + return 0, io.ErrUnexpectedEOF + } return p.underlying.Read(d) } func (p *peekingReader) Close() error { + if p.underlying == nil { + return errors.New("reader already closed") + } p.underlying = nil if p.orig != nil { return p.orig.Close() diff --git a/request_test.go b/request_test.go index ac5bb55..4617591 100644 --- a/request_test.go +++ b/request_test.go @@ -137,6 +137,39 @@ func TestPeekingReader(t *testing.T) { require.Equal(t, 1, cbr.peeks) require.Equal(t, 2, cbr.reads) require.Equal(t, 0, cbr.br.Buffered()) + + t.Run("closing a closed peekingReader", func(t *testing.T) { + const content = "content" + r := newPeekingReader(io.NopCloser(strings.NewReader(content))) + require.NoError(t, r.Close()) + + require.NotPanics(t, func() { + err := r.Close() + require.Error(t, err) + }) + }) + + t.Run("reading from a closed peekingReader", func(t *testing.T) { + const content = "content" + r := newPeekingReader(io.NopCloser(strings.NewReader(content))) + require.NoError(t, r.Close()) + + require.NotPanics(t, func() { + _, err := io.ReadAll(r) + require.Error(t, err) + require.ErrorIs(t, err, io.ErrUnexpectedEOF) + }) + }) + + t.Run("reading from a nil peekingReader", func(t *testing.T) { + var r *peekingReader + require.NotPanics(t, func() { + buf := make([]byte, 10) + _, err := r.Read(buf) + require.Error(t, err) + require.ErrorIs(t, err, io.EOF) + }) + }) } func TestJSONRequest(t *testing.T) {