Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std::fs::File::read tries to read more than INT_MAX on OSX and causes EINVAL #38590

Closed
cillian64 opened this issue Dec 24, 2016 · 1 comment
Closed
Labels
O-macos Operating system: macOS

Comments

@cillian64
Copy link

std::fs::File::read calls the libc read function passing the buffer length to read's nbyte (or count) argument [0]. From POSIX the maximum read is SSIZE_MAX [1], although 64-bit MacOS libc is buggy and limits the read to INT_MAX [2].

I tried this code on OSX 10.11.6 (El Capitan):

use std::io::prelude::*;
fn main() {
let mut buf = vec![0u8; 2147483648]; // 2^31
let mut file = std::fs::OpenOptions::new().read(true).open("/etc/group")
.unwrap();
file.read(&mut buf[..]).unwrap();
}

I would expect this to run happily and read the small number of bytes in /etc/group. Instead, libc read returns -1 with the perror message "Invalid argument" causing the last unwrap to panic. I can confirm that this code produces the expected result on 64-bit glibc (ubuntu 16.04).

In theory this could cause problems even on systems without a buggy libc. A slice's maximum size is limited by usize (size_t). On a 32-bit system it should be easy enough (about 2GiB) to create a buffer smaller than SIZE_MAX but bigger than SSIZE_MAX which would cause this problem with glibc. I have not confirmed this.

I feel that File::read should shield the user from these odd implementation issues. Given the uncertain number of bytes read by File::read, I see no harm in capping the read size at INT_MAX or SSIZE_MAX.

[0]: rust/src/libstd/sys/unix/fd.rs :40
[1]: https://linux.die.net/man/2/read
[2]: https://opensource.apple.com/source/Git/Git-61/src/git/wrapper.c?txt :172

Meta

rustc 1.13.0
binary: rustc
commit-hash: unknown
commit-date: unknown
host: x86_64-apple-darwin
release: 1.13.0

@retep998
Copy link
Member

For comparison, on Windows Rust already caps the amount that you can read/write in a single call to 0xFFFFFFFF (the maximum value of a DWORD). I see no issue with enforcing similar limits on other platforms.

alexcrichton added a commit to alexcrichton/rust that referenced this issue Dec 26, 2016
Turns out that even though all these functions take a `size_t` they don't
actually work that well with anything larger than the maximum value of
`ssize_t`, the return value. Furthermore it looks like OSX rejects any
read/write requests larger than `INT_MAX - 1`. Handle all these cases by just
clamping the maximum size of a read/write on Unix to a platform-specific value.

Closes rust-lang#38590
@sanxiyn sanxiyn added the O-macos Operating system: macOS label Dec 28, 2016
bors added a commit that referenced this issue Dec 29, 2016
std: Clamp max read/write sizes on Unix

Turns out that even though all these functions take a `size_t` they don't
actually work that well with anything larger than the maximum value of
`ssize_t`, the return value. Furthermore it looks like OSX rejects any
read/write requests larger than `INT_MAX - 1`. Handle all these cases by just
clamping the maximum size of a read/write on Unix to a platform-specific value.

Closes #38590
alexcrichton added a commit to alexcrichton/rust that referenced this issue Dec 30, 2016
std: Clamp max read/write sizes on Unix

Turns out that even though all these functions take a `size_t` they don't
actually work that well with anything larger than the maximum value of
`ssize_t`, the return value. Furthermore it looks like OSX rejects any
read/write requests larger than `INT_MAX - 1`. Handle all these cases by just
clamping the maximum size of a read/write on Unix to a platform-specific value.

Closes rust-lang#38590
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-macos Operating system: macOS
Projects
None yet
Development

No branches or pull requests

3 participants