From 4cb086b838548fa5dbdcb502a51b29294e268db6 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Tue, 20 Aug 2013 14:33:03 +1000 Subject: [PATCH] os: be consistent about File methods with nil receivers Some crashed, some didn't. Make a nil receiver always return ErrInvalid rather than crash. Fixes #5824. The program in the bug listing is silent now, at least on my Mac. R=golang-dev, adg CC=golang-dev https://golang.org/cl/13108044 --- src/pkg/os/doc.go | 6 ++++++ src/pkg/os/file.go | 6 ++++++ src/pkg/os/file_plan9.go | 17 ++++++++++++++++- src/pkg/os/file_posix.go | 9 +++++++++ src/pkg/os/file_unix.go | 6 ++++++ src/pkg/os/file_windows.go | 3 +++ src/pkg/os/stat_windows.go | 3 +++ 7 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/pkg/os/doc.go b/src/pkg/os/doc.go index c8d0a8632a..a954e313d1 100644 --- a/src/pkg/os/doc.go +++ b/src/pkg/os/doc.go @@ -106,6 +106,9 @@ func Hostname() (name string, err error) { // directory, Readdir returns the FileInfo read until that point // and a non-nil error. func (f *File) Readdir(n int) (fi []FileInfo, err error) { + if f == nil { + return nil, ErrInvalid + } return f.readdir(n) } @@ -122,5 +125,8 @@ func (f *File) Readdir(n int) (fi []FileInfo, err error) { // directory, Readdirnames returns the names read until that point and // a non-nil error. func (f *File) Readdirnames(n int) (names []string, err error) { + if f == nil { + return nil, ErrInvalid + } return f.readdirnames(n) } diff --git a/src/pkg/os/file.go b/src/pkg/os/file.go index 00a8755f42..2dd1fcf282 100644 --- a/src/pkg/os/file.go +++ b/src/pkg/os/file.go @@ -174,6 +174,9 @@ func (f *File) WriteAt(b []byte, off int64) (n int, err error) { // relative to the current offset, and 2 means relative to the end. // It returns the new offset and an error, if any. func (f *File) Seek(offset int64, whence int) (ret int64, err error) { + if f == nil { + return 0, ErrInvalid + } r, e := f.seek(offset, whence) if e == nil && f.dirinfo != nil && r != 0 { e = syscall.EISDIR @@ -216,6 +219,9 @@ func Chdir(dir string) error { // which must be a directory. // If there is an error, it will be of type *PathError. func (f *File) Chdir() error { + if f == nil { + return ErrInvalid + } if e := syscall.Fchdir(f.fd); e != nil { return &PathError{"chdir", f.name, e} } diff --git a/src/pkg/os/file_plan9.go b/src/pkg/os/file_plan9.go index d6d39a8997..708163ee1c 100644 --- a/src/pkg/os/file_plan9.go +++ b/src/pkg/os/file_plan9.go @@ -133,6 +133,9 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) { // Close closes the File, rendering it unusable for I/O. // It returns an error, if any. func (f *File) Close() error { + if f == nil { + return ErrInvalid + } return f.file.close() } @@ -156,6 +159,9 @@ func (file *file) close() error { // Stat returns the FileInfo structure describing file. // If there is an error, it will be of type *PathError. func (f *File) Stat() (fi FileInfo, err error) { + if f == nil { + return nil, ErrInvalid + } d, err := dirstat(f) if err != nil { return nil, err @@ -167,8 +173,11 @@ func (f *File) Stat() (fi FileInfo, err error) { // It does not change the I/O offset. // If there is an error, it will be of type *PathError. func (f *File) Truncate(size int64) error { - var d syscall.Dir + if f == nil { + return ErrInvalid + } + var d syscall.Dir d.Null() d.Length = size @@ -188,6 +197,9 @@ const chmodMask = uint32(syscall.DMAPPEND | syscall.DMEXCL | syscall.DMTMP | Mod // Chmod changes the mode of the file to mode. // If there is an error, it will be of type *PathError. func (f *File) Chmod(mode FileMode) error { + if f == nil { + return ErrInvalid + } var d syscall.Dir odir, e := dirstat(f) @@ -419,6 +431,9 @@ func Lchown(name string, uid, gid int) error { // Chown changes the numeric uid and gid of the named file. // If there is an error, it will be of type *PathError. func (f *File) Chown(uid, gid int) error { + if f == nil { + return ErrInvalid + } return &PathError{"chown", f.name, syscall.EPLAN9} } diff --git a/src/pkg/os/file_posix.go b/src/pkg/os/file_posix.go index 3df43feaa1..b64d9edd14 100644 --- a/src/pkg/os/file_posix.go +++ b/src/pkg/os/file_posix.go @@ -86,6 +86,9 @@ func Chmod(name string, mode FileMode) error { // Chmod changes the mode of the file to mode. // If there is an error, it will be of type *PathError. func (f *File) Chmod(mode FileMode) error { + if f == nil { + return ErrInvalid + } if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil { return &PathError{"chmod", f.name, e} } @@ -115,6 +118,9 @@ func Lchown(name string, uid, gid int) error { // Chown changes the numeric uid and gid of the named file. // If there is an error, it will be of type *PathError. func (f *File) Chown(uid, gid int) error { + if f == nil { + return ErrInvalid + } if e := syscall.Fchown(f.fd, uid, gid); e != nil { return &PathError{"chown", f.name, e} } @@ -125,6 +131,9 @@ func (f *File) Chown(uid, gid int) error { // It does not change the I/O offset. // If there is an error, it will be of type *PathError. func (f *File) Truncate(size int64) error { + if f == nil { + return ErrInvalid + } if e := syscall.Ftruncate(f.fd, size); e != nil { return &PathError{"truncate", f.name, e} } diff --git a/src/pkg/os/file_unix.go b/src/pkg/os/file_unix.go index 855eb50ff5..e0013ac640 100644 --- a/src/pkg/os/file_unix.go +++ b/src/pkg/os/file_unix.go @@ -96,6 +96,9 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) { // Close closes the File, rendering it unusable for I/O. // It returns an error, if any. func (f *File) Close() error { + if f == nil { + return ErrInvalid + } return f.file.close() } @@ -117,6 +120,9 @@ func (file *file) close() error { // Stat returns the FileInfo structure describing file. // If there is an error, it will be of type *PathError. func (f *File) Stat() (fi FileInfo, err error) { + if f == nil { + return nil, ErrInvalid + } var stat syscall.Stat_t err = syscall.Fstat(f.fd, &stat) if err != nil { diff --git a/src/pkg/os/file_windows.go b/src/pkg/os/file_windows.go index 7a63566148..f6e53d4ff0 100644 --- a/src/pkg/os/file_windows.go +++ b/src/pkg/os/file_windows.go @@ -153,6 +153,9 @@ func OpenFile(name string, flag int, perm FileMode) (file *File, err error) { // Close closes the File, rendering it unusable for I/O. // It returns an error, if any. func (file *File) Close() error { + if f == nil { + return ErrInvalid + } return file.file.close() } diff --git a/src/pkg/os/stat_windows.go b/src/pkg/os/stat_windows.go index 8394c2b320..6dc3866859 100644 --- a/src/pkg/os/stat_windows.go +++ b/src/pkg/os/stat_windows.go @@ -12,6 +12,9 @@ import ( // Stat returns the FileInfo structure describing file. // If there is an error, it will be of type *PathError. func (file *File) Stat() (fi FileInfo, err error) { + if file == nil { + return nil, ErrInvalid + } if file == nil || file.fd < 0 { return nil, syscall.EINVAL } -- 2.48.1