From b878d8db66faf9f8d9b2ff394123cdde21d93f8d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 24 Mar 2020 20:09:11 -0700 Subject: [PATCH] bufio: don't panic when Scanner sees an impossible Read count Fixes #38053 Change-Id: Ib0f9777f37eeaa07eb8ecb6df3e97e9d4b46dcd8 Reviewed-on: https://go-review.googlesource.com/c/go/+/225357 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Rob Pike --- src/bufio/scan.go | 4 +++ src/bufio/scan_test.go | 55 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/bufio/scan.go b/src/bufio/scan.go index 4e787c4b0a..976b5994eb 100644 --- a/src/bufio/scan.go +++ b/src/bufio/scan.go @@ -211,6 +211,10 @@ func (s *Scanner) Scan() bool { // be extra careful: Scanner is for safe, simple jobs. for loop := 0; ; { n, err := s.r.Read(s.buf[s.end:len(s.buf)]) + if n < 0 || n > len(s.buf)-s.end { + n = 0 + err = errors.New("bufio.Scanner: Read returned impossible count") + } s.end += n if err != nil { s.setErr(err) diff --git a/src/bufio/scan_test.go b/src/bufio/scan_test.go index 2568225688..ceb813ae8d 100644 --- a/src/bufio/scan_test.go +++ b/src/bufio/scan_test.go @@ -537,3 +537,58 @@ func TestHugeBuffer(t *testing.T) { t.Fatal("after scan:", s.Err()) } } + +// negativeEOFReader returns an invalid -1 at the end, as though it +// were wrapping the read system call. +type negativeEOFReader int + +func (r *negativeEOFReader) Read(p []byte) (int, error) { + if *r > 0 { + c := int(*r) + if c > len(p) { + c = len(p) + } + for i := 0; i < c; i++ { + p[i] = 'a' + } + p[c-1] = '\n' + *r -= negativeEOFReader(c) + return c, nil + } + return -1, io.EOF +} + +// Test that the scanner doesn't panic on a reader that returns a +// negative count of bytes read (issue 38053). +func TestNegativeEOFReader(t *testing.T) { + r := negativeEOFReader(10) + scanner := NewScanner(&r) + c := 0 + for scanner.Scan() { + c++ + if c > 1 { + t.Error("read too many lines") + break + } + } + if scanner.Err() == nil { + t.Error("scanner.Err returned nil, expected an error") + } +} + +// largeReader returns an invalid count that is larger than the number +// of bytes requested. +type largeReader struct{} + +func (largeReader) Read(p []byte) (int, error) { + return len(p) + 1, nil +} + +func TestLargeReader(t *testing.T) { + scanner := NewScanner(largeReader{}) + for scanner.Scan() { + } + if scanner.Err() == nil { + t.Error("scanner.Err returned nil, expected an error") + } +} -- 2.50.0