Change:
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 SSIZEMAX [1], although 64-bit MacOS libc is buggy and limits the read to INTMAX [2]. I tried this code on OSX 10.11.6 (El Capitan): use std::io::prelude::*; fn main() { let mut buf = vec![0u8; ]; // 2^31 let mut file = std::fs::OpenOptions::new().read(true).open("/etc/group") .unwrap(); (&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 (sizet). On a 32-bit system it should be easy enough (about 2GiB) to create a buffer smaller than SIZEMAX but bigger than SSIZEMAX 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 INTMAX or SSIZEMAX. [0]: :40 [1]: [2]: :172 rustc 1.13.0 binary: rustc commit-hash: unknown commit-date: unknown host: x8664-apple-darwin release: 1.13.0
For comparison, on Windows Rust already caps the amount that you can read/write in a single call to (the maximum value of a ). I see no issue with enforcing similar limits on other platforms.

Discussion:
#![unstable(reason = "not public", issue = "0", feature = "fd")] <ins> use cmp; </ins> use io::{self, Read}; <del> use libc::{self, c_int, c_void}; </del> <ins> use libc::{self, c_int, c_void, ssize_t}; </ins> use mem; use sync::atomic::{AtomicBool, Ordering}; use sys::cvt;

fd: c_int, } <ins> fn max_len() -> usize { // The maximum read limit on most posix-like systems is `SSIZE_MAX`, // with the man page quoting that if the count of bytes to read is // greater than `SSIZE_MAX` the result is "unspecified". // // On OSX, however, apparently the 64-bit libc is either buggy or // intentionally showing odd behavior by rejecting any read with a size // larger than or equal to INT_MAX. To handle both of these the read // size is capped on both platforms. if cfg!(target_os = "macos") { <c_int>::max_value() as usize - 1 } else { <ssize_t>::max_value() as usize } } </ins> impl FileDesc { pub fn new(fd: c_int) -> FileDesc { FileDesc { fd: fd }

let ret = cvt(unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, <del> buf.len()) </del> <ins> cmp::min(buf.len(), max_len())) </ins> })?; Ok(ret as usize) }

unsafe { cvt_pread64(self.fd, buf.as_mut_ptr() as *mut c_void, <del> buf.len(), </del> <ins> cmp::min(buf.len(), max_len()), </ins> offset as i64) .map(|n| n as usize) }

let ret = cvt(unsafe { libc::write(self.fd, buf.as_ptr() as *const c_void, <del> buf.len()) </del> <ins> cmp::min(buf.len(), max_len())) </ins> })?; Ok(ret as usize) }

unsafe { cvt_pwrite64(self.fd, buf.as_ptr() as *const c_void, <del> buf.len(), </del> <ins> cmp::min(buf.len(), max_len()), </ins> offset as i64) .map(|n| n as usize) }

use sys::c; use sys::cvt; use sys_common::io::read_to_end_uninitialized; <del> use u32; </del> /// An owned container for `HANDLE` object, closing them on Drop. ///

pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { let mut read = 0; <del> // ReadFile takes a DWORD (u32) for the length so it only supports // reading u32::MAX bytes at a time. let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD; </del> <ins> let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; </ins> let res = cvt(unsafe { c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, len, &mut read, ptr::null_mut())

pub fn write(&self, buf: &[u8]) -> io::Result<usize> { let mut amt = 0; <del> // WriteFile takes a DWORD (u32) for the length so it only supports // writing u32::MAX bytes at a time. let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD; </del> <ins> let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD; </ins> cvt(unsafe { c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, ptr::null_mut())