about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-10-04 15:24:04 +0530
committerGitHub <noreply@github.com>2016-10-04 15:24:04 +0530
commit1f9036872d7ea8bee91f8588e3c4a613c58c76cb (patch)
tree6deb3afa67883bda0e890dfff47fc6d2805476ba
parent05e412a1e50c687150700142e184ce26d85de464 (diff)
parent4935343f6ec01dfafdc115fad5dd36d3a9ed1b7d (diff)
downloadrust-1f9036872d7ea8bee91f8588e3c4a613c58c76cb.tar.gz
rust-1f9036872d7ea8bee91f8588e3c4a613c58c76cb.zip
Rollup merge of #36938 - tmiasko:cursor-seek-overflow, r=alexcrichton
Check for overflow in Cursor<Vec<u8>>::write.

Ensure that cursor position fits into usize, before proceeding with
write. Fixes issue #36884.
-rw-r--r--src/libstd/io/cursor.rs25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index 1b836b74537..ae0085f1044 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -10,6 +10,7 @@
 
 use io::prelude::*;
 
+use core::convert::TryInto;
 use cmp;
 use io::{self, SeekFrom, Error, ErrorKind};
 
@@ -242,18 +243,20 @@ impl<'a> Write for Cursor<&'a mut [u8]> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for Cursor<Vec<u8>> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        let pos: usize = self.position().try_into().map_err(|_| {
+            Error::new(ErrorKind::InvalidInput,
+                       "cursor position exceeds maximum possible vector length")
+        })?;
         // Make sure the internal buffer is as least as big as where we
         // currently are
-        let pos = self.position();
-        let amt = pos.saturating_sub(self.inner.len() as u64);
-        // use `resize` so that the zero filling is as efficient as possible
         let len = self.inner.len();
-        self.inner.resize(len + amt as usize, 0);
-
+        if len < pos {
+            // use `resize` so that the zero filling is as efficient as possible
+            self.inner.resize(pos, 0);
+        }
         // Figure out what bytes will be used to overwrite what's currently
         // there (left), and what will be appended on the end (right)
         {
-            let pos = pos as usize;
             let space = self.inner.len() - pos;
             let (left, right) = buf.split_at(cmp::min(space, buf.len()));
             self.inner[pos..pos + left.len()].copy_from_slice(left);
@@ -261,7 +264,7 @@ impl Write for Cursor<Vec<u8>> {
         }
 
         // Bump us forward
-        self.set_position(pos + buf.len() as u64);
+        self.set_position((pos + buf.len()) as u64);
         Ok(buf.len())
     }
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
@@ -580,4 +583,12 @@ mod tests {
         let mut r = Cursor::new(Vec::new());
         assert!(r.seek(SeekFrom::End(-2)).is_err());
     }
+
+    #[test]
+    #[cfg(target_pointer_width = "32")]
+    fn vec_seek_and_write_past_usize_max() {
+        let mut c = Cursor::new(Vec::new());
+        c.set_position(<usize>::max_value() as u64 + 1);
+        assert!(c.write_all(&[1, 2, 3]).is_err());
+    }
 }