about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-02-05 06:37:16 +0100
committerGitHub <noreply@github.com>2024-02-05 06:37:16 +0100
commitd8e9ddc843e4da26815492bb0b3a6ca3a4713ed2 (patch)
tree7ebd7eb2232fd489bcfe328287c2052583ba2d41
parente348f0739d85ed962fdd517c566ec222a96b3adb (diff)
parent4c694db25270243597657ec73ec9912f2ddfb0cc (diff)
downloadrust-d8e9ddc843e4da26815492bb0b3a6ca3a4713ed2.tar.gz
rust-d8e9ddc843e4da26815492bb0b3a6ca3a4713ed2.zip
Rollup merge of #120607 - conradludgate:fix-120603, r=dtolnay
fix #120603 by adding a check in default_read_buf

Fixes #120603 by checking the returned read n is in-bounds of the cursor.

Interestingly, I noticed that `BorrowedBuf` side-steps this issue by using checked accesses. Maybe this can be switched to unchecked to mirror what BufReader does https://github.com/rust-lang/rust/blob/bf3c6c5bed498f41ad815641319a1ad9bcecb8e8/library/core/src/io/borrowed_buf.rs#L95
-rw-r--r--library/std/src/io/mod.rs7
-rw-r--r--library/std/src/io/tests.rs31
2 files changed, 36 insertions, 2 deletions
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index ee79d47ddd9..a238e74ed95 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -578,8 +578,13 @@ where
     F: FnOnce(&mut [u8]) -> Result<usize>,
 {
     let n = read(cursor.ensure_init().init_mut())?;
+    assert!(
+        n <= cursor.capacity(),
+        "read should not return more bytes than there is capacity for in the read buffer"
+    );
     unsafe {
-        // SAFETY: we initialised using `ensure_init` so there is no uninit data to advance to.
+        // SAFETY: we initialised using `ensure_init` so there is no uninit data to advance to
+        // and we have checked that the read amount is not over capacity (see #120603)
         cursor.advance(n);
     }
     Ok(())
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index bda5b721adc..33e9d8efed5 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -1,6 +1,6 @@
 use super::{repeat, BorrowedBuf, Cursor, SeekFrom};
 use crate::cmp::{self, min};
-use crate::io::{self, IoSlice, IoSliceMut};
+use crate::io::{self, IoSlice, IoSliceMut, DEFAULT_BUF_SIZE};
 use crate::io::{BufRead, BufReader, Read, Seek, Write};
 use crate::mem::MaybeUninit;
 use crate::ops::Deref;
@@ -652,3 +652,32 @@ fn bench_take_read_buf(b: &mut test::Bencher) {
         [255; 128].take(64).read_buf(buf.unfilled()).unwrap();
     });
 }
+
+// Issue #120603
+#[test]
+#[should_panic = "read should not return more bytes than there is capacity for in the read buffer"]
+fn read_buf_broken_read() {
+    struct MalformedRead;
+
+    impl Read for MalformedRead {
+        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+            // broken length calculation
+            Ok(buf.len() + 1)
+        }
+    }
+
+    let _ = BufReader::new(MalformedRead).fill_buf();
+}
+
+#[test]
+fn read_buf_full_read() {
+    struct FullRead;
+
+    impl Read for FullRead {
+        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+            Ok(buf.len())
+        }
+    }
+
+    assert_eq!(BufReader::new(FullRead).fill_buf().unwrap().len(), DEFAULT_BUF_SIZE);
+}