aboutsummaryrefslogtreecommitdiff
path: root/src/bufio
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-03-24 20:09:11 -0700
committerIan Lance Taylor <iant@golang.org>2020-03-25 19:16:39 +0000
commitb878d8db66faf9f8d9b2ff394123cdde21d93f8d (patch)
treebcb5fb7c855109415b5dc41497648d926d7082f5 /src/bufio
parentfcb8f8384ac62eb029926bb1f3602825fa61b261 (diff)
downloadgo-b878d8db66faf9f8d9b2ff394123cdde21d93f8d.tar.xz
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 <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rob Pike <r@golang.org>
Diffstat (limited to 'src/bufio')
-rw-r--r--src/bufio/scan.go4
-rw-r--r--src/bufio/scan_test.go55
2 files changed, 59 insertions, 0 deletions
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")
+ }
+}