diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index f4f2e3f2434..18f7f6a35e9 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2577,6 +2577,7 @@ impl Read for Take { let max = cmp::min(buf.len() as u64, self.limit) as usize; let n = self.inner.read(&mut buf[..max])?; + assert!(n as u64 <= self.limit, "number of read bytes exceeds limit"); self.limit -= n as u64; Ok(n) } diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index d5a8c93b0ce..f357f33ec52 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -583,6 +583,25 @@ fn test_write_all_vectored() { } } +// Issue 94981 +#[test] +#[should_panic = "number of read bytes exceeds limit"] +fn test_take_wrong_length() { + struct LieAboutSize(bool); + + impl Read for LieAboutSize { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + // Lie about the read size at first time of read. + if core::mem::take(&mut self.0) { Ok(buf.len() + 1) } else { Ok(buf.len()) } + } + } + + let mut buffer = vec![0; 4]; + let mut reader = LieAboutSize(true).take(4); + // Primed the `Limit` by lying about the read size. + let _ = reader.read(&mut buffer[..]); +} + #[bench] fn bench_take_read(b: &mut test::Bencher) { b.iter(|| {