Skip to content

Commit 1f90368

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#36884.
2 parents 05e412a + 4935343 commit 1f90368

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

src/libstd/io/cursor.rs

+18-7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use io::prelude::*;
1212

13+
use core::convert::TryInto;
1314
use cmp;
1415
use io::{self, SeekFrom, Error, ErrorKind};
1516

@@ -242,26 +243,28 @@ impl<'a> Write for Cursor<&'a mut [u8]> {
242243
#[stable(feature = "rust1", since = "1.0.0")]
243244
impl Write for Cursor<Vec<u8>> {
244245
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
246+
let pos: usize = self.position().try_into().map_err(|_| {
247+
Error::new(ErrorKind::InvalidInput,
248+
"cursor position exceeds maximum possible vector length")
249+
})?;
245250
// Make sure the internal buffer is as least as big as where we
246251
// currently are
247-
let pos = self.position();
248-
let amt = pos.saturating_sub(self.inner.len() as u64);
249-
// use `resize` so that the zero filling is as efficient as possible
250252
let len = self.inner.len();
251-
self.inner.resize(len + amt as usize, 0);
252-
253+
if len < pos {
254+
// use `resize` so that the zero filling is as efficient as possible
255+
self.inner.resize(pos, 0);
256+
}
253257
// Figure out what bytes will be used to overwrite what's currently
254258
// there (left), and what will be appended on the end (right)
255259
{
256-
let pos = pos as usize;
257260
let space = self.inner.len() - pos;
258261
let (left, right) = buf.split_at(cmp::min(space, buf.len()));
259262
self.inner[pos..pos + left.len()].copy_from_slice(left);
260263
self.inner.extend_from_slice(right);
261264
}
262265

263266
// Bump us forward
264-
self.set_position(pos + buf.len() as u64);
267+
self.set_position((pos + buf.len()) as u64);
265268
Ok(buf.len())
266269
}
267270
fn flush(&mut self) -> io::Result<()> { Ok(()) }
@@ -580,4 +583,12 @@ mod tests {
580583
let mut r = Cursor::new(Vec::new());
581584
assert!(r.seek(SeekFrom::End(-2)).is_err());
582585
}
586+
587+
#[test]
588+
#[cfg(target_pointer_width = "32")]
589+
fn vec_seek_and_write_past_usize_max() {
590+
let mut c = Cursor::new(Vec::new());
591+
c.set_position(<usize>::max_value() as u64 + 1);
592+
assert!(c.write_all(&[1, 2, 3]).is_err());
593+
}
583594
}

0 commit comments

Comments
 (0)