Skip to content

Commit 2774728

Browse files
authored
Rollup merge of rust-lang#39874 - amosonn:master, r=alexcrichton
Fixes overflow in libsdt/io/cursor.rs "seek" Fixes rust-lang#39631 Test which fails (with old implementation), then fix to implementation.
2 parents f03656a + a2d176e commit 2774728

File tree

1 file changed

+49
-10
lines changed

1 file changed

+49
-10
lines changed

src/libstd/io/cursor.rs

+49-10
Original file line numberDiff line numberDiff line change
@@ -200,18 +200,20 @@ impl<T> Cursor<T> {
200200
#[stable(feature = "rust1", since = "1.0.0")]
201201
impl<T> io::Seek for Cursor<T> where T: AsRef<[u8]> {
202202
fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
203-
let pos = match style {
204-
SeekFrom::Start(n) => { self.pos = n; return Ok(n) }
205-
SeekFrom::End(n) => self.inner.as_ref().len() as i64 + n,
206-
SeekFrom::Current(n) => self.pos as i64 + n,
203+
let (base_pos, offset) = match style {
204+
SeekFrom::Start(n) => { self.pos = n; return Ok(n); }
205+
SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n),
206+
SeekFrom::Current(n) => (self.pos, n),
207207
};
208-
209-
if pos < 0 {
210-
Err(Error::new(ErrorKind::InvalidInput,
211-
"invalid seek to a negative position"))
208+
let new_pos = if offset >= 0 {
209+
base_pos.checked_add(offset as u64)
212210
} else {
213-
self.pos = pos as u64;
214-
Ok(self.pos)
211+
base_pos.checked_sub((offset.wrapping_neg()) as u64)
212+
};
213+
match new_pos {
214+
Some(n) => {self.pos = n; Ok(self.pos)}
215+
None => Err(Error::new(ErrorKind::InvalidInput,
216+
"invalid seek to a negative or overflowing position"))
215217
}
216218
}
217219
}
@@ -526,6 +528,43 @@ mod tests {
526528
assert_eq!(r.write(&[3]).unwrap(), 0);
527529
}
528530

531+
#[test]
532+
fn seek_past_i64() {
533+
let buf = [0xff];
534+
let mut r = Cursor::new(&buf[..]);
535+
assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
536+
assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
537+
assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
538+
assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
539+
assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
540+
assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
541+
542+
let mut r = Cursor::new(vec![10]);
543+
assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
544+
assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
545+
assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
546+
assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
547+
assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
548+
assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
549+
550+
let mut buf = [0];
551+
let mut r = Cursor::new(&mut buf[..]);
552+
assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
553+
assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
554+
assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
555+
assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
556+
assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
557+
assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
558+
559+
let mut r = Cursor::new(vec![10].into_boxed_slice());
560+
assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
561+
assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
562+
assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
563+
assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
564+
assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
565+
assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
566+
}
567+
529568
#[test]
530569
fn seek_before_0() {
531570
let buf = [0xff];

0 commit comments

Comments
 (0)