From 0844ff8eef81e124c1fecba82dd5843745427fa4 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Tue, 7 Jul 2020 22:18:17 -0700 Subject: [PATCH] os: fix regression with handling of nil *File Use of a nil *File as an argument should not result in a panic, but result in the ErrInvalid error being returned. Fix the copy_file_range implementation to preserve this semantic. Fixes #40115 Change-Id: Iad5ac39664a3efb7964cf55685be636940a8db13 Reviewed-on: https://go-review.googlesource.com/c/go/+/241417 Reviewed-by: Ian Lance Taylor Reviewed-by: Damien Neil Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/os/readfrom_linux.go | 5 +++++ src/os/readfrom_linux_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/os/readfrom_linux.go b/src/os/readfrom_linux.go index ed275e1ba6..63ea45cf65 100644 --- a/src/os/readfrom_linux.go +++ b/src/os/readfrom_linux.go @@ -32,6 +32,11 @@ func (f *File) readFrom(r io.Reader) (written int64, handled bool, err error) { if !ok { return 0, false, nil } + if src.checkValid("ReadFrom") != nil { + // Avoid returning the error as we report handled as false, + // leave further error handling as the responsibility of the caller. + return 0, false, nil + } written, handled, err = pollCopyFileRange(&f.pfd, &src.pfd, remain) if lr != nil { diff --git a/src/os/readfrom_linux_test.go b/src/os/readfrom_linux_test.go index b6f5cb7034..00faf39fe5 100644 --- a/src/os/readfrom_linux_test.go +++ b/src/os/readfrom_linux_test.go @@ -8,6 +8,7 @@ import ( "bytes" "internal/poll" "io" + "io/ioutil" "math/rand" . "os" "path/filepath" @@ -170,6 +171,35 @@ func TestCopyFileRange(t *testing.T) { mustContainData(t, dst, data) }) }) + t.Run("Nil", func(t *testing.T) { + var nilFile *File + anyFile, err := ioutil.TempFile("", "") + if err != nil { + t.Fatal(err) + } + defer Remove(anyFile.Name()) + defer anyFile.Close() + + if _, err := io.Copy(nilFile, nilFile); err != ErrInvalid { + t.Errorf("io.Copy(nilFile, nilFile) = %v, want %v", err, ErrInvalid) + } + if _, err := io.Copy(anyFile, nilFile); err != ErrInvalid { + t.Errorf("io.Copy(anyFile, nilFile) = %v, want %v", err, ErrInvalid) + } + if _, err := io.Copy(nilFile, anyFile); err != ErrInvalid { + t.Errorf("io.Copy(nilFile, anyFile) = %v, want %v", err, ErrInvalid) + } + + if _, err := nilFile.ReadFrom(nilFile); err != ErrInvalid { + t.Errorf("nilFile.ReadFrom(nilFile) = %v, want %v", err, ErrInvalid) + } + if _, err := anyFile.ReadFrom(nilFile); err != ErrInvalid { + t.Errorf("anyFile.ReadFrom(nilFile) = %v, want %v", err, ErrInvalid) + } + if _, err := nilFile.ReadFrom(anyFile); err != ErrInvalid { + t.Errorf("nilFile.ReadFrom(anyFile) = %v, want %v", err, ErrInvalid) + } + }) } func testCopyFileRange(t *testing.T, size int64, limit int64) { -- 2.50.0