Closed
Description
Code
#![feature(read_buf)]
use std::io::{self, BufWriter, Read, ReadBuf};
struct BadReader;
impl Read for BadReader {
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
unreachable!()
}
fn read_buf(&mut self, read_buf: &mut ReadBuf<'_>) -> io::Result<()> {
let vec = vec![0; 2048];
let mut buf = ReadBuf::new(vec.leak());
buf.append(&[123; 2048]);
*read_buf = buf;
Ok(())
}
}
fn main() {
let mut buf = Vec::new();
{
let mut buf_ = BufWriter::with_capacity(1024, &mut buf);
let mut input = BadReader.take(4096);
io::copy(&mut input, &mut buf_).unwrap();
}
// read the memory to trigger miri to realize that the memory is uninitialized
println!("buf[0]: {}", buf[0]);
}
Playground link: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=483f0b4f2f881519f459c3cd273a50f4 (run miri on it)
Unsound implementation
rust/library/std/src/io/copy.rs
Lines 80 to 122 in 92ed874
(we're basically tricking it into calling set_len
with a length higher than what has actually been filled)
Documentation
Should this be considered a possible footgun when implementing something that calls read_buf
? Should it be documented?
Activity
Urgau commentedon Jan 25, 2022
This was already mention in the PR that added ReadBuf #81156 (comment)
cc @drmeepster @joshtriplett
beepster4096 commentedon Jan 26, 2022
There's two possible solutions I see here.
ReadBuf
points to the same buffer as before and return an error if it doesn't. This doesn't seem very "rusty" to me though, relying on a runtime check.ReadBufRef
type passed by value toread_buf
instead of&mut ReadBuf
. This solves the issue in general at compile time, but could make this api a lot more complicated to use.nrc commentedon Apr 8, 2022
I think another example of unsound code in std for a similar reason is in the
read_buf
implementation forTake
.paolobarbolini commentedon Apr 10, 2022
Yes it seems like a similar attack could be done against it
rust/library/std/src/io/mod.rs
Lines 2584 to 2601 in 18f32b7
Rollup merge of rust-lang#97015 - nrc:read-buf-cursor, r=Mark-Simulacrum
Rollup merge of rust-lang#97015 - nrc:read-buf-cursor, r=Mark-Simulacrum