Skip to content

Commit 0ecbcbb

Browse files
authored
Rollup merge of rust-lang#95040 - frank-king:fix/94981, r=Mark-Simulacrum
protect `std::io::Take::limit` from overflow in `read` Resolves rust-lang#94981
2 parents 7f93d4a + 64ac045 commit 0ecbcbb

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
@@ -2577,6 +2577,7 @@ impl<T: Read> Read for Take<T> {
25772577

25782578
let max = cmp::min(buf.len() as u64, self.limit) as usize;
25792579
let n = self.inner.read(&mut buf[..max])?;
2580+
assert!(n as u64 <= self.limit, "number of read bytes exceeds limit");
25802581
self.limit -= n as u64;
25812582
Ok(n)
25822583
}

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)