diff --git a/src/net/fd_unix.go b/src/net/fd_unix.go index 198f606284db22e7c523cca1fa8dc56f68627481..a8d3a253a97b108945306f99dddaf5a025a44f71 100644 --- a/src/net/fd_unix.go +++ b/src/net/fd_unix.go @@ -191,7 +191,7 @@ func (fd *netFD) accept() (netfd *netFD, err error) { } // Defined in os package. -func newUnixFile(fd uintptr, name string) *os.File +func newUnixFile(fd int, name string) *os.File func (fd *netFD) dup() (f *os.File, err error) { ns, call, err := fd.pfd.Dup() @@ -202,5 +202,5 @@ func (fd *netFD) dup() (f *os.File, err error) { return nil, err } - return newUnixFile(uintptr(ns), fd.name()), nil + return newUnixFile(ns, fd.name()), nil } diff --git a/src/os/file_unix.go b/src/os/file_unix.go index a34de8333da49b57aeccf07b358cad9e0be670ee..533a48404b9d090e390823222f2566348e8478e0 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -103,15 +103,20 @@ func (f *File) Fd() uintptr { // conditions described in the comments of the Fd method, and the same // constraints apply. func NewFile(fd uintptr, name string) *File { + fdi := int(fd) + if fdi < 0 { + return nil + } + kind := kindNewFile appendMode := false - if flags, err := unix.Fcntl(int(fd), syscall.F_GETFL, 0); err == nil { + if flags, err := unix.Fcntl(fdi, syscall.F_GETFL, 0); err == nil { if unix.HasNonblockFlag(flags) { kind = kindNonBlock } appendMode = flags&syscall.O_APPEND != 0 } - f := newFile(fd, name, kind) + f := newFile(fdi, name, kind) f.appendMode = appendMode return f } @@ -126,7 +131,11 @@ func NewFile(fd uintptr, name string) *File { // retain that behavior because existing code expects it and depends on it. // //go:linkname net_newUnixFile net.newUnixFile -func net_newUnixFile(fd uintptr, name string) *File { +func net_newUnixFile(fd int, name string) *File { + if fd < 0 { + panic("invalid FD") + } + f := newFile(fd, name, kindNonBlock) f.nonblock = true // tell Fd to return blocking descriptor return f @@ -155,19 +164,15 @@ const ( // newFile is like NewFile, but if called from OpenFile or Pipe // (as passed in the kind parameter) it tries to add the file to // the runtime poller. -func newFile(fd uintptr, name string, kind newFileKind) *File { - fdi := int(fd) - if fdi < 0 { - return nil - } +func newFile(fd int, name string, kind newFileKind) *File { f := &File{&file{ pfd: poll.FD{ - Sysfd: fdi, + Sysfd: fd, IsStream: true, ZeroReadIsEOF: true, }, name: name, - stdoutOrErr: fdi == 1 || fdi == 2, + stdoutOrErr: fd == 1 || fd == 2, }} pollable := kind == kindOpenFile || kind == kindPipe || kind == kindNonBlock @@ -180,7 +185,7 @@ func newFile(fd uintptr, name string, kind newFileKind) *File { case "darwin", "ios", "dragonfly", "freebsd", "netbsd", "openbsd": var st syscall.Stat_t err := ignoringEINTR(func() error { - return syscall.Fstat(fdi, &st) + return syscall.Fstat(fd, &st) }) typ := st.Mode & syscall.S_IFMT // Don't try to use kqueue with regular files on *BSDs. @@ -210,7 +215,7 @@ func newFile(fd uintptr, name string, kind newFileKind) *File { // The descriptor is already in non-blocking mode. // We only set f.nonblock if we put the file into // non-blocking mode. - } else if err := syscall.SetNonblock(fdi, true); err == nil { + } else if err := syscall.SetNonblock(fd, true); err == nil { f.nonblock = true clearNonBlock = true } else { @@ -226,7 +231,7 @@ func newFile(fd uintptr, name string, kind newFileKind) *File { // will show up in later I/O. // We do restore the blocking behavior if it was set by us. if pollErr := f.pfd.Init("file", pollable); pollErr != nil && clearNonBlock { - if err := syscall.SetNonblock(fdi, false); err == nil { + if err := syscall.SetNonblock(fd, false); err == nil { f.nonblock = false } } @@ -293,7 +298,7 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) { kind = kindNonBlock } - f := newFile(uintptr(r), name, kind) + f := newFile(r, name, kind) f.pfd.SysFile = s return f, nil } diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go index 73940f982f442e56d1355f056da69c3b74c7b6ba..98e7afd0f6ba0a8b55c73a092d4cf6cf6ce0cfb3 100644 --- a/src/os/os_unix_test.go +++ b/src/os/os_unix_test.go @@ -314,6 +314,14 @@ func TestNewFileNonBlock(t *testing.T) { newFileTest(t, false) } +func TestNewFileInvalid(t *testing.T) { + t.Parallel() + const negOne = ^uintptr(0) + if f := NewFile(negOne, "invalid"); f != nil { + t.Errorf("NewFile(-1) got %v want nil", f) + } +} + func TestSplitPath(t *testing.T) { t.Parallel() for _, tt := range []struct{ path, wantDir, wantBase string }{ diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go index fbc8cc1b9f8fdcd85fd970fd98e3c634720034a6..a0bfd991e33c1ea5e8554117c62e0ff1391e0146 100644 --- a/src/os/os_windows_test.go +++ b/src/os/os_windows_test.go @@ -1446,3 +1446,10 @@ func TestUTF16Alloc(t *testing.T) { syscall.UTF16FromString("abc") }) } + +func TestNewFileInvalid(t *testing.T) { + t.Parallel() + if f := os.NewFile(uintptr(syscall.InvalidHandle), "invalid"); f != nil { + t.Errorf("NewFile(InvalidHandle) got %v want nil", f) + } +} diff --git a/src/os/pipe2_unix.go b/src/os/pipe2_unix.go index 1e2e8ccb67cb78510589597ee1ed038575ed251d..2d293fdb4d9665fca9034e989e9bf127bc6f6d0a 100644 --- a/src/os/pipe2_unix.go +++ b/src/os/pipe2_unix.go @@ -18,5 +18,5 @@ func Pipe() (r *File, w *File, err error) { return nil, nil, NewSyscallError("pipe2", e) } - return newFile(uintptr(p[0]), "|0", kindPipe), newFile(uintptr(p[1]), "|1", kindPipe), nil + return newFile(p[0], "|0", kindPipe), newFile(p[1], "|1", kindPipe), nil } diff --git a/src/os/pipe_unix.go b/src/os/pipe_unix.go index a12412e0ca798722f08b0e748ecf020c017bd0c6..2eb11a04cb2d929ac9f11769f0a18a59ab8b1cba 100644 --- a/src/os/pipe_unix.go +++ b/src/os/pipe_unix.go @@ -24,5 +24,5 @@ func Pipe() (r *File, w *File, err error) { syscall.CloseOnExec(p[1]) syscall.ForkLock.RUnlock() - return newFile(uintptr(p[0]), "|0", kindPipe), newFile(uintptr(p[1]), "|1", kindPipe), nil + return newFile(p[0], "|0", kindPipe), newFile(p[1], "|1", kindPipe), nil } diff --git a/src/os/removeall_at.go b/src/os/removeall_at.go index 378733ffdb4d636011a1bf143f34e676e1d29c55..8ea5df411740fd7dfbb5025b11b478502ca1ff71 100644 --- a/src/os/removeall_at.go +++ b/src/os/removeall_at.go @@ -195,5 +195,5 @@ func openFdAt(dirfd int, name string) (*File, error) { } // We use kindNoPoll because we know that this is a directory. - return newFile(uintptr(r), name, kindNoPoll), nil + return newFile(r, name, kindNoPoll), nil }