diff options
| author | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2016-10-01 00:00:00 +0200 |
|---|---|---|
| committer | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2016-10-03 22:16:13 +0200 |
| commit | 4935343f6ec01dfafdc115fad5dd36d3a9ed1b7d (patch) | |
| tree | 66297d369968c0892a4adf073beec14d492f6b58 /src/libstd | |
| parent | 5045d4e39621b265eca947277f07e23f62608ad0 (diff) | |
| download | rust-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.rs | 25 |
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()); + } } |
