]> Cypherpunks repositories - gostls13.git/commitdiff
bufio: fix UnreadSlice followed by UnreadRune
authorEgon Elbre <egonelbre@gmail.com>
Fri, 18 Jul 2014 16:25:59 +0000 (09:25 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 18 Jul 2014 16:25:59 +0000 (09:25 -0700)
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

src/pkg/bufio/bufio.go
src/pkg/bufio/bufio_test.go
src/pkg/bufio/scan.go

index 61ef26191008e74c1d4ba0cde5885f825bb8791c..d3c68fe6fe539e975f668c6d7e6af66c7348af79 100644 (file)
@@ -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
index be43a80023ffcd9079788719c475daaf816b3d5c..4f3bc1036400d5b9dbc30163cea19e4b0427a377 100644 (file)
@@ -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) {
index 97ae1090956e65502c9f0346c60cf5d99a877262..c5714f331ef52b5e25812d1f4b48eade42325cd8 100644 (file)
@@ -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
 )