mirror of
https://github.com/golang/go
synced 2024-11-11 22:50:22 -07:00
bufio: fix potential endless loop in ReadByte
Fixes #7745. LGTM=bradfitz, r R=r, bradfitz CC=golang-codereviews https://golang.org/cl/86220044
This commit is contained in:
parent
8bd9242f7c
commit
b38fba21f0
@ -88,15 +88,22 @@ func (b *Reader) fill() {
|
||||
b.r = 0
|
||||
}
|
||||
|
||||
// Read new data.
|
||||
n, err := b.rd.Read(b.buf[b.w:])
|
||||
if n < 0 {
|
||||
panic(errNegativeRead)
|
||||
}
|
||||
b.w += n
|
||||
if err != nil {
|
||||
b.err = err
|
||||
// Read new data: try a limited number of times.
|
||||
for i := maxConsecutiveEmptyReads; i > 0; i-- {
|
||||
n, err := b.rd.Read(b.buf[b.w:])
|
||||
if n < 0 {
|
||||
panic(errNegativeRead)
|
||||
}
|
||||
b.w += n
|
||||
if err != nil {
|
||||
b.err = err
|
||||
return
|
||||
}
|
||||
if n > 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
b.err = io.ErrNoProgress
|
||||
}
|
||||
|
||||
func (b *Reader) readErr() error {
|
||||
@ -151,6 +158,9 @@ func (b *Reader) Read(p []byte) (n int, err error) {
|
||||
// Large read, empty buffer.
|
||||
// Read directly into p to avoid copy.
|
||||
n, b.err = b.rd.Read(p)
|
||||
if n < 0 {
|
||||
panic(errNegativeRead)
|
||||
}
|
||||
if n > 0 {
|
||||
b.lastByte = int(p[n-1])
|
||||
b.lastRuneSize = -1
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/iotest"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
@ -174,6 +175,34 @@ func TestReader(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type zeroReader struct{}
|
||||
|
||||
func (zeroReader) Read(p []byte) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func TestZeroReader(t *testing.T) {
|
||||
var z zeroReader
|
||||
r := NewReader(z)
|
||||
|
||||
c := make(chan error)
|
||||
go func() {
|
||||
_, err := r.ReadByte()
|
||||
c <- err
|
||||
}()
|
||||
|
||||
select {
|
||||
case err := <-c:
|
||||
if err == nil {
|
||||
t.Error("error expected")
|
||||
} else if err != io.ErrNoProgress {
|
||||
t.Error("unexpected error:", err)
|
||||
}
|
||||
case <-time.After(time.Second):
|
||||
t.Error("test timed out (endless loop in ReadByte?)")
|
||||
}
|
||||
}
|
||||
|
||||
// A StringReader delivers its data one string segment at a time via Read.
|
||||
type StringReader struct {
|
||||
data []string
|
||||
|
Loading…
Reference in New Issue
Block a user