]> git.lizzy.rs Git - rust.git/commitdiff
Check for overflow in Cursor<Vec<u8>>::write.
authorTomasz Miąsko <tomasz.miasko@gmail.com>
Fri, 30 Sep 2016 22:00:00 +0000 (00:00 +0200)
committerTomasz Miąsko <tomasz.miasko@gmail.com>
Mon, 3 Oct 2016 20:16:13 +0000 (22:16 +0200)
Ensure that cursor position fits into usize, before proceeding with
write. Fixes issue #36884.

src/libstd/io/cursor.rs

index 1b836b745372f00ed8189a6b4e2b956b1c5e5e12..ae0085f1044e4bb683e37e49a67592d539013765 100644 (file)
@@ -10,6 +10,7 @@
 
 use io::prelude::*;
 
+use core::convert::TryInto;
 use cmp;
 use io::{self, SeekFrom, Error, ErrorKind};
 
@@ -242,18 +243,20 @@ fn flush(&mut self) -> io::Result<()> { Ok(()) }
 #[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 @@ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         }
 
         // 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 @@ fn vec_seek_before_0() {
         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());
+    }
 }