From: Egon Elbre Date: Fri, 18 Jul 2014 16:25:59 +0000 (-0700) Subject: bufio: fix UnreadSlice followed by UnreadRune X-Git-Tag: go1.4beta1~1062 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=0b2da60fb8a5f883ee29fe794e4976df55fe902c;p=gostls13.git bufio: fix UnreadSlice followed by UnreadRune Also, fix a write check in writeBuf and make some bounds checks simpler. LGTM=gri R=golang-codereviews, adg, gri, r, minux CC=golang-codereviews https://golang.org/cl/113060043 --- diff --git a/src/pkg/bufio/bufio.go b/src/pkg/bufio/bufio.go index 61ef261910..d3c68fe6fe 100644 --- a/src/pkg/bufio/bufio.go +++ b/src/pkg/bufio/bufio.go @@ -30,8 +30,8 @@ var ( // Reader implements buffering for an io.Reader object. type Reader struct { buf []byte - rd io.Reader - r, w int + rd io.Reader // reader provided by the client + r, w int // buf read and write positions err error lastByte int lastRuneSize int @@ -131,18 +131,17 @@ func (b *Reader) Peek(n int) ([]byte, error) { for b.w-b.r < n && b.err == nil { b.fill() // b.w-b.r < len(b.buf) => buffer is not full } - m := b.w - b.r - if m > n { - m = n - } + var err error - if m < n { + if avail := b.w - b.r; avail < n { + // not enough data in buffer + n = avail err = b.readErr() if err == nil { err = ErrBufferFull } } - return b.buf[b.r : b.r+m], err + return b.buf[b.r : b.r+n], err } // Read reads data into p. @@ -173,15 +172,13 @@ func (b *Reader) Read(p []byte) (n int, err error) { return n, b.readErr() } b.fill() // buffer is empty - if b.w == b.r { + if b.r == b.w { return 0, b.readErr() } } - if n > b.w-b.r { - n = b.w - b.r - } - copy(p[0:n], b.buf[b.r:]) + // copy as much as we can + n = copy(p, b.buf[b.r:b.w]) b.r += n b.lastByte = int(b.buf[b.r-1]) b.lastRuneSize = -1 @@ -288,7 +285,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { } // Buffer full? - if n := b.Buffered(); n >= len(b.buf) { + if b.Buffered() >= len(b.buf) { b.r = b.w line = b.buf err = ErrBufferFull @@ -301,6 +298,7 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { // Handle last byte, if any. if i := len(line) - 1; i >= 0 { b.lastByte = int(line[i]) + b.lastRuneSize = -1 } return @@ -458,11 +456,13 @@ func (b *Reader) WriteTo(w io.Writer) (n int64, err error) { return n, b.readErr() } +var errNegativeWrite = errors.New("bufio: writer returned negative count from Write") + // writeBuf writes the Reader's buffer to the writer. func (b *Reader) writeBuf(w io.Writer) (int64, error) { n, err := w.Write(b.buf[b.r:b.w]) - if n < b.r-b.w { - panic(errors.New("bufio: writer did not write all data")) + if n < 0 { + panic(errNegativeWrite) } b.r += n return int64(n), err diff --git a/src/pkg/bufio/bufio_test.go b/src/pkg/bufio/bufio_test.go index be43a80023..4f3bc10364 100644 --- a/src/pkg/bufio/bufio_test.go +++ b/src/pkg/bufio/bufio_test.go @@ -463,6 +463,18 @@ func TestUnreadRuneError(t *testing.T) { if r.UnreadRune() == nil { t.Error("expected error after UnreadByte (3)") } + // Test error after ReadSlice. + _, _, err = r.ReadRune() // reset state + if err != nil { + t.Error("unexpected error on ReadRune (4):", err) + } + _, err = r.ReadSlice(0) + if err != io.EOF { + t.Error("unexpected error on ReadSlice (4):", err) + } + if r.UnreadRune() == nil { + t.Error("expected error after ReadSlice (4)") + } } func TestUnreadRuneAtEOF(t *testing.T) { diff --git a/src/pkg/bufio/scan.go b/src/pkg/bufio/scan.go index 97ae109095..c5714f331e 100644 --- a/src/pkg/bufio/scan.go +++ b/src/pkg/bufio/scan.go @@ -64,8 +64,9 @@ var ( ) const ( - // Maximum size used to buffer a token. The actual maximum token size - // may be smaller as the buffer may need to include, for instance, a newline. + // MaxScanTokenSize is the maximum size used to buffer a token. + // The actual maximum token size may be smaller as the buffer + // may need to include, for instance, a newline. MaxScanTokenSize = 64 * 1024 )