about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2016-10-01 00:00:00 +0200
committerTomasz Miąsko <tomasz.miasko@gmail.com>2016-10-03 22:16:13 +0200
commit4935343f6ec01dfafdc115fad5dd36d3a9ed1b7d (patch)
tree66297d369968c0892a4adf073beec14d492f6b58 /src/libstd
parent5045d4e39621b265eca947277f07e23f62608ad0 (diff)
downloadrust-4935343f6ec01dfafdc115fad5dd36d3a9ed1b7d.tar.gz
rust-4935343f6ec01dfafdc115fad5dd36d3a9ed1b7d.zip
Check for overflow in Cursor<Vec<u8>>::write.
Ensure that cursor position fits into usize, before proceeding with
write. Fixes issue #36884.
Diffstat (limited to 'src/libstd')
-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());
+    }
 }