Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Broken Read implementations can cause uninitialized memory read #3

Open
ammaraskar opened this issue Feb 3, 2021 · 0 comments
Open

Comments

@ammaraskar
Copy link

Hi there, we (Rust group @sslab-gatech) are scanning crates on crates.io for potential soundness bugs. We noticed that in Window::new, the bytes read returned from the reader are used to set_len:

rdiff/src/window.rs

Lines 9 to 18 in 6680843

let mut front = vec!(0;block_size);
let mut back = vec!(0;block_size);
let size = try!(reader.read(front.as_mut_slice()));
unsafe {
front.set_len(size);
}
let size = try!(reader.read(back.as_mut_slice()));
unsafe {
back.set_len(size);
}

This means that a buggy Read implementation that returns more bytes than the buf size can cause front and back to contain initialized memory. See this example:

#![forbid(unsafe_code)]

use rdiff::BlockHashes;
use std::io::{Cursor, Read};

struct MyRead {
    first: bool,
}

impl MyRead {
    pub fn new() -> Self {
        MyRead { first: false }
    }
}

impl Read for MyRead {
    fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
        if !self.first {
            self.first = true;
            // First iteration: return more than the buffer size
            Ok(256)
        } else {
            // Second iteration: indicate that we are done
            Ok(0)
        }
    }
}

fn main() {
    let mut hashes = BlockHashes::new(Cursor::new("Hello"), 32).unwrap();
    let diff = hashes.diff_and_update(MyRead::new()).unwrap();

    for insert in diff.inserts() {
        println!("{:?}", insert);
    }
}

This outputs:

Insert(0, '1���� =�>�U��X���������������X�q')

I think there should be an assert in Window::new to ensure that the number of bytes are <= block_size

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant