From 12e8ffc18e84a76f8e01457852c456a3b28ec55a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 27 Sep 2021 14:27:59 -0700 Subject: [PATCH] io: avoid integer overflow in NewSectionReader Fixes #48620 Change-Id: I37a5909ad27dc4a170929cb2e2ed1045cf524d59 Reviewed-on: https://go-review.googlesource.com/c/go/+/352629 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Brad Fitzpatrick TryBot-Result: Go Bot --- src/io/io.go | 11 ++++++++++- src/io/io_test.go | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/io/io.go b/src/io/io.go index 4e49a782dce..cb2a37e4270 100644 --- a/src/io/io.go +++ b/src/io/io.go @@ -479,7 +479,16 @@ func (l *LimitedReader) Read(p []byte) (n int, err error) { // NewSectionReader returns a SectionReader that reads from r // starting at offset off and stops with EOF after n bytes. func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader { - return &SectionReader{r, off, off, off + n} + var remaining int64 + const maxint64 = 1<<63 - 1 + if off <= maxint64-n { + remaining = n + off + } else { + // Overflow, with no way to return error. + // Assume we can read up to an offset of 1<<63 - 1. + remaining = maxint64 + } + return &SectionReader{r, off, off, remaining} } // SectionReader implements Read, Seek, and ReadAt on a section diff --git a/src/io/io_test.go b/src/io/io_test.go index 5b355e8c55b..30884604809 100644 --- a/src/io/io_test.go +++ b/src/io/io_test.go @@ -430,6 +430,20 @@ func TestSectionReader_Size(t *testing.T) { } } +func TestSectionReader_Max(t *testing.T) { + r := strings.NewReader("abcdef") + const maxint64 = 1<<63 - 1 + sr := NewSectionReader(r, 3, maxint64) + n, err := sr.Read(make([]byte, 3)) + if n != 3 || err != nil { + t.Errorf("Read = %v %v, want 3, nil", n, err) + } + n, err = sr.Read(make([]byte, 3)) + if n != 0 || err != EOF { + t.Errorf("Read = %v, %v, want 0, EOF", n, err) + } +} + // largeWriter returns an invalid count that is larger than the number // of bytes provided (issue 39978). type largeWriter struct {