diff options
| author | NODA, Kai <nodakai@gmail.com> | 2014-12-03 06:06:59 +0800 |
|---|---|---|
| committer | NODA, Kai <nodakai@gmail.com> | 2014-12-04 11:19:55 +0800 |
| commit | 3980cdecd073789fb5ff7256e2ca40685a289b01 (patch) | |
| tree | 007c1af0e17e6c4bd21b18034d87d9e24a9c58af /src/libstd | |
| parent | 805a06ca6a4f0999e13508e6271e3589f2c4c1b2 (diff) | |
| download | rust-3980cdecd073789fb5ff7256e2ca40685a289b01.tar.gz rust-3980cdecd073789fb5ff7256e2ca40685a289b01.zip | |
libstd: explicitly disallow io::fs::File to open a directory.
On *BSD systems, we can open(2) a directory and directly read(2) from it due to an old tradition. We should avoid doing so by explicitly calling fstat(2) to check the type of the opened file. Opening a directory as a module file can't always be avoided. Even when there's no "path" attribute trick involved, there can always be a *directory* named "my_module.rs". Fix #12460 Signed-off-by: NODA, Kai <nodakai@gmail.com>
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/fs.rs | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index d5f23694fc8..c66540e639e 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -53,7 +53,8 @@ use clone::Clone; use io::standard_error; use io::{FilePermission, Write, Open, FileAccess, FileMode, FileType}; -use io::{IoResult, IoError, FileStat, SeekStyle, Seek, Writer, Reader}; +use io::{IoResult, IoError, InvalidInput}; +use io::{FileStat, SeekStyle, Seek, Writer, Reader}; use io::{Read, Truncate, ReadWrite, Append}; use io::UpdateIoError; use io; @@ -134,13 +135,26 @@ impl File { pub fn open_mode(path: &Path, mode: FileMode, access: FileAccess) -> IoResult<File> { - fs_imp::open(path, mode, access).map(|fd| { - File { - path: path.clone(), - fd: fd, - last_nread: -1 + fs_imp::open(path, mode, access).and_then(|fd| { + // On *BSD systems, we can open a directory as a file and read from it: + // fd=open("/tmp", O_RDONLY); read(fd, buf, N); + // due to an old tradition before the introduction of opendir(3). + // We explicitly reject it because there are few use cases. + if cfg!(not(any(windows, target_os = "linux", target_os = "android"))) && + try!(fd.fstat()).kind == FileType::Directory { + Err(IoError { + kind: InvalidInput, + desc: "is a directory", + detail: None + }) + } else { + Ok(File { + path: path.clone(), + fd: fd, + last_nread: -1 + }) } - }).update_err("couldn't open file", |e| { + }).update_err("couldn't open path as file", |e| { format!("{}; path={}; mode={}; access={}", e, path.display(), mode_string(mode), access_string(access)) }) @@ -886,7 +900,7 @@ mod test { let filename = &tmpdir.join("file_that_does_not_exist.txt"); let result = File::open_mode(filename, Open, Read); - error!(result, "couldn't open file"); + error!(result, "couldn't open path as file"); if cfg!(unix) { error!(result, "no such file or directory"); } |
