aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gerrand <adg@golang.org>2013-07-29 18:00:58 +1000
committerAndrew Gerrand <adg@golang.org>2013-07-29 18:00:58 +1000
commit018854d24aee8615c62c1126af71e2b6cccd0b05 (patch)
treec97980e21df259b17e1e6192e99ea2988cf3e5ab
parent2041d55aac66d54765d2a4cfd267986c8f6d7c2a (diff)
downloadgo-018854d24aee8615c62c1126af71e2b6cccd0b05.tar.gz
go-018854d24aee8615c62c1126af71e2b6cccd0b05.zip
[release-branch.go1.1] bufio: check buffer availability before reading in ReadFrom
This change was applied by hand, as bufio has seen some refactoring since 1.1 was branched. The only difference between this and the original patch is the offset of the change, and s/flush/Flush/. ««« CL 11801043 / 3ffbc06b4874 bufio: check buffer availability before reading in ReadFrom Fixes issue 5947 . R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/11801043 »»» Update #5928 R=golang-dev, r CC=golang-dev https://golang.org/cl/12002043
-rw-r--r--src/pkg/bufio/bufio.go17
-rw-r--r--src/pkg/bufio/bufio_test.go22
2 files changed, 33 insertions, 6 deletions
diff --git a/src/pkg/bufio/bufio.go b/src/pkg/bufio/bufio.go
index df3501f2ca..10e12d42be 100644
--- a/src/pkg/bufio/bufio.go
+++ b/src/pkg/bufio/bufio.go
@@ -585,23 +585,28 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
}
var m int
for {
+ if b.Available() == 0 {
+ if err1 := b.Flush(); err1 != nil {
+ return n, err1
+ }
+ }
m, err = r.Read(b.buf[b.n:])
if m == 0 {
break
}
b.n += m
n += int64(m)
- if b.Available() == 0 {
- if err1 := b.Flush(); err1 != nil {
- return n, err1
- }
- }
if err != nil {
break
}
}
if err == io.EOF {
- err = nil
+ // If we filled the buffer exactly, flush pre-emptively.
+ if b.Available() == 0 {
+ err = b.Flush()
+ } else {
+ err = nil
+ }
}
return n, err
}
diff --git a/src/pkg/bufio/bufio_test.go b/src/pkg/bufio/bufio_test.go
index 79ed0f178e..9fcbfda68d 100644
--- a/src/pkg/bufio/bufio_test.go
+++ b/src/pkg/bufio/bufio_test.go
@@ -847,6 +847,10 @@ func TestWriterReadFrom(t *testing.T) {
t.Errorf("ws[%d],rs[%d]: w.ReadFrom(r) = %d, %v, want %d, nil", wi, ri, n, err, len(input))
continue
}
+ if err := w.Flush(); err != nil {
+ t.Errorf("Flush returned %v", err)
+ continue
+ }
if got, want := b.String(), string(input); got != want {
t.Errorf("ws[%d], rs[%d]:\ngot %q\nwant %q\n", wi, ri, got, want)
}
@@ -1003,6 +1007,24 @@ func TestReaderClearError(t *testing.T) {
}
}
+// Test for golang.org/issue/5947
+func TestWriterReadFromWhileFull(t *testing.T) {
+ buf := new(bytes.Buffer)
+ w := NewWriterSize(buf, 10)
+
+ // Fill buffer exactly.
+ n, err := w.Write([]byte("0123456789"))
+ if n != 10 || err != nil {
+ t.Fatalf("Write returned (%v, %v), want (10, nil)", n, err)
+ }
+
+ // Use ReadFrom to read in some data.
+ n2, err := w.ReadFrom(strings.NewReader("abcdef"))
+ if n2 != 6 || err != nil {
+ t.Fatalf("ReadFrom returned (%v, %v), want (6, nil)", n, err)
+ }
+}
+
// An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have.
type onlyReader struct {
r io.Reader