Skip to content

Commit

Permalink
Rollup merge of rust-lang#120607 - conradludgate:fix-120603, r=dtolnay
Browse files Browse the repository at this point in the history
fix rust-lang#120603 by adding a check in default_read_buf

Fixes rust-lang#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
  • Loading branch information
matthiaskrgr committed Feb 4, 2024
2 parents dc1f20a + 4c694db commit c168f17
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 2 deletions.
7 changes: 6 additions & 1 deletion library/std/src/io/mod.rs
Expand Up @@ -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(())
Expand Down
31 changes: 30 additions & 1 deletion 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;
Expand Down Expand Up @@ -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);
}

0 comments on commit c168f17

Please sign in to comment.