Skip to content

Commit 4efd519

Browse files
neildgopherbot
authored andcommitted
internal/poll: avoid overflow in sendfile limit, simplify Solaris
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 <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 0fd414c commit 4efd519

File tree

2 files changed

+10
-26
lines changed

2 files changed

+10
-26
lines changed

src/internal/poll/sendfile_unix.go

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ import (
3030
func SendFile(dstFD *FD, src int, size int64) (n int64, err error, handled bool) {
3131
if runtime.GOOS == "linux" {
3232
// Linux's sendfile doesn't require any setup:
33-
// It sends from the current position of the source file,
34-
// updates the position of the source after sending,
35-
// and sends everything when the size is 0.
33+
// It sends from the current position of the source file and
34+
// updates the position of the source after sending.
3635
return sendFile(dstFD, src, nil, size)
3736
}
3837

@@ -46,28 +45,9 @@ func SendFile(dstFD *FD, src int, size int64) (n int64, err error, handled bool)
4645
return 0, err, false
4746
}
4847

49-
mustReposition := false
50-
switch runtime.GOOS {
51-
case "solaris", "illumos":
52-
// Solaris/illumos requires us to pass a length to send,
53-
// rather than accepting 0 as "send everything".
54-
//
55-
// Seek to the end of the source file to find its length.
56-
if size == 0 {
57-
end, err := ignoringEINTR2(func() (int64, error) {
58-
return syscall.Seek(src, 0, io.SeekEnd)
59-
})
60-
if err != nil {
61-
return 0, err, false
62-
}
63-
size = end - start
64-
mustReposition = true
65-
}
66-
}
67-
6848
pos := start
6949
n, err, handled = sendFile(dstFD, src, &pos, size)
70-
if n > 0 || mustReposition {
50+
if n > 0 {
7151
ignoringEINTR2(func() (int64, error) {
7252
return syscall.Seek(src, start+n, io.SeekStart)
7353
})
@@ -91,9 +71,13 @@ func sendFile(dstFD *FD, src int, offset *int64, size int64) (written int64, err
9171

9272
dst := dstFD.Sysfd
9373
for {
94-
chunk := 0
74+
// Some platforms support passing 0 to read to the end of the source,
75+
// but all platforms support just writing a large value.
76+
//
77+
// Limit the maximum size to fit in an int32, to avoid any possible overflow.
78+
chunk := 1<<31 - 1
9579
if size > 0 {
96-
chunk = int(size - written)
80+
chunk = int(min(size-written, int64(chunk)))
9781
}
9882
var n int
9983
n, err = sendFileChunk(dst, src, offset, chunk)

src/os/copy_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func TestCopyFileToFile(t *testing.T) {
9898
for _, srcStart := range []int64{0, 100, size} {
9999
remaining := size - srcStart
100100
for _, dstStart := range []int64{0, 200} {
101-
for _, limit := range []int64{remaining, remaining - 100, size * 2} {
101+
for _, limit := range []int64{remaining, remaining - 100, size * 2, 0} {
102102
if limit < 0 {
103103
continue
104104
}

0 commit comments

Comments
 (0)