Skip to content

Commit 64ac045

Browse files
committed
protect std::io::Take::limit from overflow in read
fixs rust-lang#94981
1 parent be52b4a commit 64ac045

File tree

2 files changed

+20
-0
lines changed

2 files changed

+20
-0
lines changed

library/std/src/io/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2559,6 +2559,7 @@ impl<T: Read> Read for Take<T> {
25592559

25602560
let max = cmp::min(buf.len() as u64, self.limit) as usize;
25612561
let n = self.inner.read(&mut buf[..max])?;
2562+
assert!(n as u64 <= self.limit, "number of read bytes exceeds limit");
25622563
self.limit -= n as u64;
25632564
Ok(n)
25642565
}

library/std/src/io/tests.rs

+19
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,25 @@ fn test_write_all_vectored() {
583583
}
584584
}
585585

586+
// Issue 94981
587+
#[test]
588+
#[should_panic = "number of read bytes exceeds limit"]
589+
fn test_take_wrong_length() {
590+
struct LieAboutSize(bool);
591+
592+
impl Read for LieAboutSize {
593+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
594+
// Lie about the read size at first time of read.
595+
if core::mem::take(&mut self.0) { Ok(buf.len() + 1) } else { Ok(buf.len()) }
596+
}
597+
}
598+
599+
let mut buffer = vec![0; 4];
600+
let mut reader = LieAboutSize(true).take(4);
601+
// Primed the `Limit` by lying about the read size.
602+
let _ = reader.read(&mut buffer[..]);
603+
}
604+
586605
#[bench]
587606
fn bench_take_read(b: &mut test::Bencher) {
588607
b.iter(|| {

0 commit comments

Comments
 (0)