about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Middleton <olliemail27@gmail.com>2016-02-25 01:35:41 +0000
committerOliver Middleton <olliemail27@gmail.com>2016-02-25 01:35:41 +0000
commitac3cc33fee5e0f576cc9f04f7df40cd5d968be43 (patch)
tree41dbd37d5c3467ec4826487e3c4631412284938b
parent0ef8d426050318934d16d962325ec002eaf0c29d (diff)
downloadrust-ac3cc33fee5e0f576cc9f04f7df40cd5d968be43.tar.gz
rust-ac3cc33fee5e0f576cc9f04f7df40cd5d968be43.zip
rand: Fix filling buffers 4 GiB or larger with OsRng::fill_bytes on Windows
CryptGenRandom takes a DWORD (u32) for the length so it only supports
writing u32::MAX bytes at a time.

Casting the length from a usize caused truncation meaning the whole
buffer was not always filled.
-rw-r--r--src/libstd/sys/windows/rand.rs18
1 files changed, 11 insertions, 7 deletions
diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs
index fdd260b6e28..10e3d45f9d5 100644
--- a/src/libstd/sys/windows/rand.rs
+++ b/src/libstd/sys/windows/rand.rs
@@ -48,13 +48,17 @@ impl Rng for OsRng {
         unsafe { mem::transmute(v) }
     }
     fn fill_bytes(&mut self, v: &mut [u8]) {
-        let ret = unsafe {
-            c::CryptGenRandom(self.hcryptprov, v.len() as c::DWORD,
-                              v.as_mut_ptr())
-        };
-        if ret == 0 {
-            panic!("couldn't generate random bytes: {}",
-                   io::Error::last_os_error());
+        // CryptGenRandom takes a DWORD (u32) for the length so we need to
+        // split up the buffer.
+        for slice in v.chunks_mut(<c::DWORD>::max_value() as usize) {
+            let ret = unsafe {
+                c::CryptGenRandom(self.hcryptprov, slice.len() as c::DWORD,
+                                  slice.as_mut_ptr())
+            };
+            if ret == 0 {
+                panic!("couldn't generate random bytes: {}",
+                       io::Error::last_os_error());
+            }
         }
     }
 }