Commit 0794dce0 authored by Russ Cox's avatar Russ Cox

bufio: read from underlying reader at most once in Read

Fixes #17059.

Change-Id: I5c7ee46604399f7dc3c3c49f964cbb1aa6c0d621
Reviewed-on: https://go-review.googlesource.com/31320Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 3d1ae4b7
...@@ -206,10 +206,18 @@ func (b *Reader) Read(p []byte) (n int, err error) { ...@@ -206,10 +206,18 @@ func (b *Reader) Read(p []byte) (n int, err error) {
} }
return n, b.readErr() return n, b.readErr()
} }
b.fill() // buffer is empty // One read.
if b.r == b.w { // 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() return 0, b.readErr()
} }
b.w += n
} }
// copy as much as we can // copy as much as we can
......
...@@ -1236,6 +1236,27 @@ func TestWriterReadFromErrNoProgress(t *testing.T) { ...@@ -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) { func TestReaderReset(t *testing.T) {
r := NewReader(strings.NewReader("foo foo")) r := NewReader(strings.NewReader("foo foo"))
buf := make([]byte, 3) buf := make([]byte, 3)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment