|
10 | 10 |
|
11 | 11 | use io::prelude::*; |
12 | 12 |
|
| 13 | +use core::convert::TryInto; |
13 | 14 | use cmp; |
14 | 15 | use io::{self, SeekFrom, Error, ErrorKind}; |
15 | 16 |
|
@@ -242,26 +243,28 @@ impl<'a> Write for Cursor<&'a mut [u8]> { |
242 | 243 | #[stable(feature = "rust1", since = "1.0.0")] |
243 | 244 | impl Write for Cursor<Vec<u8>> { |
244 | 245 | 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 | + })?; |
245 | 250 | // Make sure the internal buffer is as least as big as where we |
246 | 251 | // 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 |
250 | 252 | 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 | + } |
253 | 257 | // Figure out what bytes will be used to overwrite what's currently |
254 | 258 | // there (left), and what will be appended on the end (right) |
255 | 259 | { |
256 | | - let pos = pos as usize; |
257 | 260 | let space = self.inner.len() - pos; |
258 | 261 | let (left, right) = buf.split_at(cmp::min(space, buf.len())); |
259 | 262 | self.inner[pos..pos + left.len()].copy_from_slice(left); |
260 | 263 | self.inner.extend_from_slice(right); |
261 | 264 | } |
262 | 265 |
|
263 | 266 | // Bump us forward |
264 | | - self.set_position(pos + buf.len() as u64); |
| 267 | + self.set_position((pos + buf.len()) as u64); |
265 | 268 | Ok(buf.len()) |
266 | 269 | } |
267 | 270 | fn flush(&mut self) -> io::Result<()> { Ok(()) } |
@@ -580,4 +583,12 @@ mod tests { |
580 | 583 | let mut r = Cursor::new(Vec::new()); |
581 | 584 | assert!(r.seek(SeekFrom::End(-2)).is_err()); |
582 | 585 | } |
| 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 | + } |
583 | 594 | } |
0 commit comments