From 48c0cef6dc9e7c95edaffb261250f99732686466 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 29 Oct 2019 13:27:00 +0700 Subject: [PATCH] bufio: return the underlying error in ReadFrom if not nil If a previous Write returned an error, any subsequent Write or ReadFrom must return that error before any operations. However, only Write behaved correctly and this change fixes that problem by making sure that ReadFrom firstly checks for the underlying error. Fixes #35194 Change-Id: I31356a9e8bd945bc0168b2e3be470f3ae69d4813 Reviewed-on: https://go-review.googlesource.com/c/go/+/204000 Run-TryBot: Cuong Manh Le Run-TryBot: Brad Fitzpatrick Reviewed-by: Brad Fitzpatrick Reviewed-by: Emmanuel Odeke Reviewed-by: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/bufio/bufio.go | 3 +++ src/bufio/bufio_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go index d1d542a484..f0810be3a4 100644 --- a/src/bufio/bufio.go +++ b/src/bufio/bufio.go @@ -706,6 +706,9 @@ func (b *Writer) WriteString(s string) (int, error) { // supports the ReadFrom method, and b has no buffered data yet, // this calls the underlying ReadFrom without buffering. func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) { + if b.err != nil { + return 0, b.err + } if b.Buffered() == 0 { if w, ok := b.wr.(io.ReaderFrom); ok { n, err = w.ReadFrom(r) diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go index 3e085fd5d0..9a9f102f15 100644 --- a/src/bufio/bufio_test.go +++ b/src/bufio/bufio_test.go @@ -1555,6 +1555,32 @@ func TestWriterReadFromMustSetUnderlyingError(t *testing.T) { } } +type writeErrorOnlyWriter struct{} + +func (w writeErrorOnlyWriter) Write(p []byte) (n int, err error) { + return 0, errors.New("writeErrorOnlyWriter error") +} + +// Ensure that previous Write errors are immediately returned +// on any ReadFrom. See golang.org/issue/35194. +func TestWriterReadFromMustReturnUnderlyingError(t *testing.T) { + var wr = NewWriter(writeErrorOnlyWriter{}) + s := "test1" + wantBuffered := len(s) + if _, err := wr.WriteString(s); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if err := wr.Flush(); err == nil { + t.Error("expected flush error, got nil") + } + if _, err := wr.ReadFrom(strings.NewReader("test2")); err == nil { + t.Fatal("expected error, got nil") + } + if buffered := wr.Buffered(); buffered != wantBuffered { + t.Fatalf("Buffered = %v; want %v", buffered, wantBuffered) + } +} + func BenchmarkReaderCopyOptimal(b *testing.B) { // Optimal case is where the underlying reader implements io.WriterTo srcBuf := bytes.NewBuffer(make([]byte, 8192)) -- 2.50.0