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 {