sile / libflate

A Rust implementation of DEFLATE algorithm and related formats (ZLIB, GZIP)

Home Page:https://docs.rs/libflate

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Decoder::read_non_compressed_block() is unsound

Shnatsel opened this issue · comments

The following code is unsound:

let old_len = self.buffer.len();
self.buffer.reserve(len as usize);
unsafe { self.buffer.set_len(old_len + len as usize) };
self.bit_reader
.as_inner_mut()
.read_exact(&mut self.buffer[old_len..])?;

The slice passed to read_exact() is uninitialized. This uses a Read implementation supplied by the API user, and there is no guarantee that it will never read from the provided buffer. If it does, it may cause a memory disclosure vulnerability.

Similar bug in Rust MP4 parser for reference: mozilla/mp4parse-rust#172

The equivalent code in stdlib initializes the vector with zeroes before growing it: https://doc.rust-lang.org/src/std/io/mod.rs.html#355-391

There have been some language proposals to create a contract for never reading from the buffer in this case, but they have not been stabilized: rust-lang/rust#42788

For now replacing unsafe { self.buffer.set_len(old_len + len as usize) }; with self.buffer.resize(old_len + len as usize, 0); should fix it.

I have not read all of the unsafe code in libflate, there may be similar issues in other unsafe blocks, which is why I'm opening an issue instead of a PR right away.

This code might also be affected:

let mut reader = mem::replace(&mut self.decoder, Err(unsafe { mem::uninitialized() }))

Thank you for your detailed report.
I would like to fix unsound code one by one.

This seems to be the only occurrence of this issue. Everywhere else read_exact() is passed properly initialized buffers.

Fixed by the linked PR.