From 591d4a47aefc74d96ec283abada57868a37d1f19 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Thu, 18 Apr 2013 17:37:21 -0700 Subject: [PATCH] bufio.Scan: don't stop after Read returns 0, nil But stop eventually if the reader misbehaves. R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/8757045 --- src/pkg/bufio/scan.go | 29 +++++++++++++++++++---------- src/pkg/bufio/scan_test.go | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/pkg/bufio/scan.go b/src/pkg/bufio/scan.go index cebe92d331..2e1a2e9997 100644 --- a/src/pkg/bufio/scan.go +++ b/src/pkg/bufio/scan.go @@ -103,8 +103,7 @@ func (s *Scanner) Text() string { // Scan advances the Scanner to the next token, which will then be // available through the Bytes or Text method. It returns false when the -// scan stops, either by reaching the end of the input, a zero-length -// read from the input, or an error. +// scan stops, either by reaching the end of the input or an error. // After Scan returns false, the Err method will return any error that // occurred during scanning, except that if it was io.EOF, Err // will return nil. @@ -159,15 +158,25 @@ func (s *Scanner) Scan() bool { s.start = 0 continue } - // Finally we can read some input. - n, err := s.r.Read(s.buf[s.end:len(s.buf)]) - if err != nil { - s.setErr(err) - } - if n == 0 { // Don't loop forever if Reader doesn't deliver EOF. - s.setErr(io.EOF) + // Finally we can read some input. Make sure we don't get stuck with + // a misbehaving Reader. Officially we don't need to do this, but let's + // be extra careful: Scanner is for safe, simple jobs. + for loop := 0; ; { + n, err := s.r.Read(s.buf[s.end:len(s.buf)]) + s.end += n + if err != nil { + s.setErr(err) + break + } + if n > 0 { + break + } + loop++ + if loop > 100 { + s.setErr(io.ErrNoProgress) + break + } } - s.end += n } } diff --git a/src/pkg/bufio/scan_test.go b/src/pkg/bufio/scan_test.go index 1b112f46da..c1483b2685 100644 --- a/src/pkg/bufio/scan_test.go +++ b/src/pkg/bufio/scan_test.go @@ -386,3 +386,21 @@ func TestNonEOFWithEmptyRead(t *testing.T) { t.Errorf("unexpected error: %v", err) } } + +// Test that Scan finishes if we have endless empty reads. +type endlessZeros struct{} + +func (endlessZeros) Read(p []byte) (int, error) { + return 0, nil +} + +func TestBadReader(t *testing.T) { + scanner := NewScanner(endlessZeros{}) + for scanner.Scan() { + t.Fatal("read should fail") + } + err := scanner.Err() + if err != io.ErrNoProgress { + t.Errorf("unexpected error: %v", err) + } +} -- 2.48.1