]> Cypherpunks repositories - gostls13.git/commitdiff
bufio: read from underlying reader at most once in Read
authorRuss Cox <rsc@golang.org>
Tue, 18 Oct 2016 01:08:48 +0000 (21:08 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 18 Oct 2016 12:56:55 +0000 (12:56 +0000)
Fixes #17059.

Change-Id: I5c7ee46604399f7dc3c3c49f964cbb1aa6c0d621
Reviewed-on: https://go-review.googlesource.com/31320
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/bufio/bufio.go
src/bufio/bufio_test.go

index 1e7872d50ba62e94c5dda6fc0bed64fb670e308a..e1e8fb2272076e7f29550e8dc1b23e345471a55f 100644 (file)
@@ -206,10 +206,18 @@ func (b *Reader) Read(p []byte) (n int, err error) {
                        }
                        return n, b.readErr()
                }
-               b.fill() // buffer is empty
-               if b.r == b.w {
+               // One read.
+               // Do not use b.fill, which will loop.
+               b.r = 0
+               b.w = 0
+               n, b.err = b.rd.Read(b.buf)
+               if n < 0 {
+                       panic(errNegativeRead)
+               }
+               if n == 0 {
                        return 0, b.readErr()
                }
+               b.w += n
        }
 
        // copy as much as we can
index 858048696e4ed15789c445523925b54989953566..ef0f6c834e86230f9f7d63c3dfd407022afdb8a7 100644 (file)
@@ -1236,6 +1236,27 @@ func TestWriterReadFromErrNoProgress(t *testing.T) {
        }
 }
 
+func TestReadZero(t *testing.T) {
+       for _, size := range []int{100, 2} {
+               t.Run(fmt.Sprintf("bufsize=%d", size), func(t *testing.T) {
+                       r := io.MultiReader(strings.NewReader("abc"), &emptyThenNonEmptyReader{r: strings.NewReader("def"), n: 1})
+                       br := NewReaderSize(r, size)
+                       want := func(s string, wantErr error) {
+                               p := make([]byte, 50)
+                               n, err := br.Read(p)
+                               if err != wantErr || n != len(s) || string(p[:n]) != s {
+                                       t.Fatalf("read(%d) = %q, %v, want %q, %v", len(p), string(p[:n]), err, s, wantErr)
+                               }
+                               t.Logf("read(%d) = %q, %v", len(p), string(p[:n]), err)
+                       }
+                       want("abc", nil)
+                       want("", nil)
+                       want("def", nil)
+                       want("", io.EOF)
+               })
+       }
+}
+
 func TestReaderReset(t *testing.T) {
        r := NewReader(strings.NewReader("foo foo"))
        buf := make([]byte, 3)