about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorOliver Middleton <olliemail27@gmail.com>2016-02-23 00:04:24 +0000
committerOliver Middleton <olliemail27@gmail.com>2016-02-23 00:51:18 +0000
commitb340f2535277a562e3b9ec8d9bb0033a41f72bb8 (patch)
treecbb36c1f61832577be68ae4d42d0be8e388b0801 /src/libstd/sys
parentc8fc4817dcbf50690aba1fc8bd4db336aff2dbc6 (diff)
downloadrust-b340f2535277a562e3b9ec8d9bb0033a41f72bb8.tar.gz
rust-b340f2535277a562e3b9ec8d9bb0033a41f72bb8.zip
Fix reading/writing 4 GiB or larger files on Windows 64-bit
`ReadFile` and `WriteFile` take a DWORD (u32) for the length argument
which was erroneously cast from a usize causing truncation. This meant
methods like `write_all` and `read_exact` would unexpectedly fail if
given a buffer 4 GiB or larger.

We can instead just ask for `u32::MAX` bytes if the given buffer is too
big.
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/windows/handle.rs16
1 files changed, 11 insertions, 5 deletions
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index cb41b05daae..47676a927f6 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use cmp;
 use io::ErrorKind;
 use io;
 use mem;
@@ -15,6 +16,7 @@ use ops::Deref;
 use ptr;
 use sys::c;
 use sys::cvt;
+use u32;
 
 /// An owned container for `HANDLE` object, closing them on Drop.
 ///
@@ -64,10 +66,12 @@ impl RawHandle {
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let mut read = 0;
+        // 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;
         let res = cvt(unsafe {
-            c::ReadFile(self.0, buf.as_ptr() as c::LPVOID,
-                           buf.len() as c::DWORD, &mut read,
-                           ptr::null_mut())
+            c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
+                        len, &mut read, ptr::null_mut())
         });
 
         match res {
@@ -85,10 +89,12 @@ impl RawHandle {
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let mut amt = 0;
+        // 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;
         try!(cvt(unsafe {
             c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
-                            buf.len() as c::DWORD, &mut amt,
-                            ptr::null_mut())
+                         len, &mut amt, ptr::null_mut())
         }));
         Ok(amt as usize)
     }