From f0d9ccb8da4c2f0b8f900c970073eb4c980dcc38 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 10 Dec 2012 17:25:31 -0500 Subject: [PATCH] bufio: minor fixes * note end-of-line and EOF behavior for ReadLine * diagnose broken Readers Fixes #3825. Fixes #4276. R=golang-dev, dave CC=golang-dev https://golang.org/cl/6907060 --- src/pkg/bufio/bufio.go | 8 ++++++++ src/pkg/bufio/bufio_test.go | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/pkg/bufio/bufio.go b/src/pkg/bufio/bufio.go index cd51585f84..4b690192c6 100644 --- a/src/pkg/bufio/bufio.go +++ b/src/pkg/bufio/bufio.go @@ -64,6 +64,8 @@ func NewReader(rd io.Reader) *Reader { return NewReaderSize(rd, defaultBufSize) } +var errNegativeRead = errors.New("bufio: reader returned negative count from Read") + // fill reads a new chunk into the buffer. func (b *Reader) fill() { // Slide existing data to beginning. @@ -75,6 +77,9 @@ func (b *Reader) fill() { // Read new data. n, e := b.rd.Read(b.buf[b.w:]) + if n < 0 { + panic(errNegativeRead) + } b.w += n if e != nil { b.err = e @@ -282,6 +287,9 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { // of the line. The returned buffer is only valid until the next call to // ReadLine. ReadLine either returns a non-nil line or it returns an error, // never both. +// +// The text returned from ReadLine does not include the line end ("\r\n" or "\n"). +// No indication or error is given if the input ends without a final line end. func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) { line, err = b.ReadSlice('\n') if err == ErrBufferFull { diff --git a/src/pkg/bufio/bufio_test.go b/src/pkg/bufio/bufio_test.go index 75d9edf8b1..564621150e 100644 --- a/src/pkg/bufio/bufio_test.go +++ b/src/pkg/bufio/bufio_test.go @@ -939,6 +939,29 @@ func (w *writeCountingDiscard) Write(p []byte) (int, error) { return len(p), nil } +type negativeReader int + +func (r *negativeReader) Read([]byte) (int, error) { return -1, nil } + +func TestNegativeRead(t *testing.T) { + // should panic with a description pointing at the reader, not at itself. + // (should NOT panic with slice index error, for example.) + b := NewReader(new(negativeReader)) + defer func() { + switch err := recover().(type) { + case nil: + t.Fatal("read did not panic") + case error: + if !strings.Contains(err.Error(), "reader returned negative count from Read") { + t.Fatal("wrong panic: %v", err) + } + default: + t.Fatalf("unexpected panic value: %T(%v)", err, err) + } + }() + b.Read(make([]byte, 100)) +} + // An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have. type onlyReader struct { r io.Reader