about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <jtitor@2k36.org>2022-07-25 18:46:47 +0900
committerGitHub <noreply@github.com>2022-07-25 18:46:47 +0900
commit0ecbcbb0ace4229f59e09de035ccef747b024e00 (patch)
treee7fae9c81da63a062a316547669bdac59a968e4e
parent7f93d4aa0dc4ac071c617e0e07d2758e3bb388f9 (diff)
parent64ac04567ba397f8600952e3875b9a197f7b2910 (diff)
downloadrust-0ecbcbb0ace4229f59e09de035ccef747b024e00.tar.gz
rust-0ecbcbb0ace4229f59e09de035ccef747b024e00.zip
Rollup merge of #95040 - frank-king:fix/94981, r=Mark-Simulacrum
protect `std::io::Take::limit` from overflow in `read`

Resolves #94981
-rw-r--r--library/std/src/io/mod.rs1
-rw-r--r--library/std/src/io/tests.rs19
2 files changed, 20 insertions, 0 deletions
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<T: Read> Read for Take<T> {
 
         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<usize> {
+            // 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(|| {