Skip to content

Commit e7e2d7a

Browse files
committed
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 rust-lang#12460 Signed-off-by: NODA, Kai <[email protected]>
1 parent fc40c0c commit e7e2d7a

File tree

2 files changed

+22
-10
lines changed

2 files changed

+22
-10
lines changed

src/libstd/io/fs.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
use clone::Clone;
5454
use io::standard_error;
5555
use io::{FilePermission, Write, Open, FileAccess, FileMode, FileType};
56-
use io::{IoResult, IoError, FileStat, SeekStyle, Seek, Writer, Reader};
56+
use io::{IoResult, IoError, InvalidInput};
57+
use io::{FileStat, SeekStyle, Seek, Writer, Reader};
5758
use io::{Read, Truncate, ReadWrite, Append};
5859
use io::UpdateIoError;
5960
use io;
@@ -134,13 +135,26 @@ impl File {
134135
pub fn open_mode(path: &Path,
135136
mode: FileMode,
136137
access: FileAccess) -> IoResult<File> {
137-
fs_imp::open(path, mode, access).map(|fd| {
138-
File {
139-
path: path.clone(),
140-
fd: fd,
141-
last_nread: -1
138+
fs_imp::open(path, mode, access).and_then(|fd| {
139+
// On *BSD systems, we can open a directory as a file and read from it:
140+
// fd=open("/tmp", O_RDONLY); read(fd, buf, N);
141+
// due to an old tradition before the introduction of opendir(3).
142+
// We explicitly reject it because there are few use cases.
143+
if cfg!(not(any(windows, target_os = "linux", target_os = "android"))) &&
144+
try!(fd.fstat()).kind == FileType::Directory {
145+
Err(IoError {
146+
kind: InvalidInput,
147+
desc: "is a directory",
148+
detail: None
149+
})
150+
} else {
151+
Ok(File {
152+
path: path.clone(),
153+
fd: fd,
154+
last_nread: -1
155+
})
142156
}
143-
}).update_err("couldn't open file", |e| {
157+
}).update_err("couldn't open path as file", |e| {
144158
format!("{}; path={}; mode={}; access={}", e, path.display(),
145159
mode_string(mode), access_string(access))
146160
})

src/test/compile-fail/issue-5806.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@
1818
// option. This file may not be copied, modified, or distributed
1919
// except according to those terms.
2020

21-
// ignore-freebsd FIXME #12460
22-
2321
#[path = "../compile-fail"]
24-
mod foo; //~ ERROR: illegal operation on a directory
22+
mod foo; //~ ERROR: a directory
2523

2624
fn main() {}

0 commit comments

Comments
 (0)