diff --git a/src/io/io.go b/src/io/io.go index 7a5d7d1a3e..a6544ac7ce 100644 --- a/src/io/io.go +++ b/src/io/io.go @@ -413,8 +413,10 @@ func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) { if nr > 0 { nw, ew := dst.Write(buf[0:nr]) if nw < 0 || nr < nw { - err = ErrBadWriteCount - break + nw = 0 + if ew == nil { + ew = ErrBadWriteCount + } } written += int64(nw) if ew != nil { diff --git a/src/io/io_test.go b/src/io/io_test.go index 170513dcc0..f3476610ba 100644 --- a/src/io/io_test.go +++ b/src/io/io_test.go @@ -429,3 +429,33 @@ func TestSectionReader_Size(t *testing.T) { } } } + +// largeWriter returns an invalid count that is larger than the number +// of bytes requested (issue 39978). +type largeWriter struct { + err error +} + +func (w largeWriter) Write(p []byte) (int, error) { + return len(p) + 1, w.err +} + +func TestCopyLargeWriter(t *testing.T) { + want := ErrBadWriteCount + rb := new(Buffer) + wb := largeWriter{} + rb.WriteString("hello, world.") + if _, err := Copy(wb, rb); err != want { + t.Errorf("Copy Error: got %v, want %v", err, want) + } +} + +func TestCopyLargeWriterError(t *testing.T) { + want := errors.New("largerWriteError") + rb := new(Buffer) + wb := largeWriter{err: want} + rb.WriteString("hello, world.") + if _, err := Copy(wb, rb); err != want { + t.Errorf("Copy Error: got %v, want %v", err, want) + } +}