]> Cypherpunks repositories - gostls13.git/commitdiff
internal/poll: avoid overflow in sendfile limit, simplify Solaris
authorDamien Neil <dneil@google.com>
Tue, 29 Oct 2024 18:46:25 +0000 (11:46 -0700)
committerGopher Robot <gobot@golang.org>
Wed, 30 Oct 2024 20:15:22 +0000 (20:15 +0000)
Avoid integer overflow when passing a number of bytes to sendfile.

Also, Solaris might not support passing a 0 length to read to
the end of a file, but it does support passing a very large length.
So just do that instead of looking up the source file size.

Change-Id: Ibf750892938d9e2bafb1256c6e380c88899495f4
Reviewed-on: https://go-review.googlesource.com/c/go/+/623315
TryBot-Bypass: Ian Lance Taylor <iant@golang.org>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/internal/poll/sendfile_unix.go
src/os/copy_test.go

index eaa48f39db405fc9e2fc759a7cd1c41bb073646b..dc81c4ad897a2bcc904a62c10df90b23e2e4c48a 100644 (file)
@@ -30,9 +30,8 @@ import (
 func SendFile(dstFD *FD, src int, size int64) (n int64, err error, handled bool) {
        if runtime.GOOS == "linux" {
                // Linux's sendfile doesn't require any setup:
-               // It sends from the current position of the source file,
-               // updates the position of the source after sending,
-               // and sends everything when the size is 0.
+               // It sends from the current position of the source file and
+               // updates the position of the source after sending.
                return sendFile(dstFD, src, nil, size)
        }
 
@@ -46,28 +45,9 @@ func SendFile(dstFD *FD, src int, size int64) (n int64, err error, handled bool)
                return 0, err, false
        }
 
-       mustReposition := false
-       switch runtime.GOOS {
-       case "solaris", "illumos":
-               // Solaris/illumos requires us to pass a length to send,
-               // rather than accepting 0 as "send everything".
-               //
-               // Seek to the end of the source file to find its length.
-               if size == 0 {
-                       end, err := ignoringEINTR2(func() (int64, error) {
-                               return syscall.Seek(src, 0, io.SeekEnd)
-                       })
-                       if err != nil {
-                               return 0, err, false
-                       }
-                       size = end - start
-                       mustReposition = true
-               }
-       }
-
        pos := start
        n, err, handled = sendFile(dstFD, src, &pos, size)
-       if n > 0 || mustReposition {
+       if n > 0 {
                ignoringEINTR2(func() (int64, error) {
                        return syscall.Seek(src, start+n, io.SeekStart)
                })
@@ -91,9 +71,13 @@ func sendFile(dstFD *FD, src int, offset *int64, size int64) (written int64, err
 
        dst := dstFD.Sysfd
        for {
-               chunk := 0
+               // Some platforms support passing 0 to read to the end of the source,
+               // but all platforms support just writing a large value.
+               //
+               // Limit the maximum size to fit in an int32, to avoid any possible overflow.
+               chunk := 1<<31 - 1
                if size > 0 {
-                       chunk = int(size - written)
+                       chunk = int(min(size-written, int64(chunk)))
                }
                var n int
                n, err = sendFileChunk(dst, src, offset, chunk)
index 407a59af42dfefcc10115071df7cb85f74c7e064..6fe7f6e53b8a5e90127b5d361b2e77690482f6c9 100644 (file)
@@ -98,7 +98,7 @@ func TestCopyFileToFile(t *testing.T) {
        for _, srcStart := range []int64{0, 100, size} {
                remaining := size - srcStart
                for _, dstStart := range []int64{0, 200} {
-                       for _, limit := range []int64{remaining, remaining - 100, size * 2} {
+                       for _, limit := range []int64{remaining, remaining - 100, size * 2, 0} {
                                if limit < 0 {
                                        continue
                                }