From 64ac04567ba397f8600952e3875b9a197f7b2910 Mon Sep 17 00:00:00 2001 From: Frank King Date: Thu, 17 Mar 2022 23:11:49 +0800 Subject: [PATCH] protect `std::io::Take::limit` from overflow in `read` fixs #94981 --- library/std/src/io/mod.rs | 1 + library/std/src/io/tests.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 6005270a75f..004f18bbfcb 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2559,6 +2559,7 @@ fn read(&mut self, buf: &mut [u8]) -> Result { 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 eb626348564..b11292ed82d 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(|| { -- 2.44.0