Skip to content

Commit

Permalink
Avoid an out-of-bounds panic in deflate_stored
Browse files Browse the repository at this point in the history
When shifting the window down, it is possible for the end of the window
to be after the last initialized byte of the buffer. These uninitialized
bytes don't affect the output of the compression, so we can safely skip
copying them to avoid the panic. This matches the code a bit higher up
which also does a window slide.
  • Loading branch information
bjorn3 committed Dec 2, 2024
1 parent b1b4d20 commit 43ca3df
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 1 deletion.
179 changes: 179 additions & 0 deletions test-libz-rs-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1552,3 +1552,182 @@ fn inflate_strict_is_off() {
(zlib_rs::ReturnCode::from(err), dest_len)
});
}

#[test]
fn deflate_stored_window_out_of_bounds() {
use core::ffi::c_int;
use zlib_rs::ReturnCode;

let mut source = [
161, 161, 161, 161, 179, 179, 179, 179, 179, 179, 133, 133, 133, 133, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 95, 95, 95, 255, 179, 179, 179, 179, 179, 179, 179,
179, 179, 43, 179, 8, 179, 133, 133, 133, 133, 13, 13, 122, 13, 13, 13, 13, 13, 13, 13, 13,
13, 3, 13, 13, 95, 95, 95, 13, 13, 255, 255, 255, 189, 189, 189, 189, 189, 189, 189, 0,
189, 189, 189, 189, 189, 189, 189, 189, 189, 173, 189, 189, 189, 189, 189, 189, 189, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 95, 95, 95, 255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95,
95, 95, 255, 255, 189, 189, 189, 189, 189, 173, 189, 189, 189, 189, 189, 189, 189, 255,
255, 245, 255, 255, 255, 255, 255, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189,
189, 189, 189, 255, 255, 255, 255, 189, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 125, 125, 125, 125, 125, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 125, 125, 125, 125, 125, 125,
125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 255, 18, 125, 125,
125, 69, 125, 125, 125, 125, 255, 255, 255, 255, 125, 125, 125, 125, 125, 63, 125, 125,
125, 125, 125, 125, 125, 125, 125, 223, 223, 223, 223, 223, 223, 223, 223, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 255, 255, 255,
255, 255, 255, 13, 13, 13, 13, 13, 13, 13, 95, 95, 95, 255, 179, 179, 179, 179, 179, 179,
179, 179, 179, 43, 179, 8, 179, 133, 133, 133, 133, 13, 13, 122, 13, 13, 13, 13, 13, 13,
13, 13, 13, 3, 13, 13, 95, 95, 95, 13, 13, 255, 255, 255, 189, 189, 189, 189, 189, 189,
189, 0, 189, 189, 189, 189, 189, 189, 189, 189, 189, 173, 189, 189, 189, 189, 189, 189,
189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 255,
255, 255, 255, 189, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 125, 125, 125, 125, 125, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 255, 18, 125, 125, 125, 69, 125, 125,
125, 125, 255, 255, 255, 255, 125, 125, 125, 125, 125, 63, 125, 125, 125, 125, 125, 125,
125, 125, 125, 223, 223, 223, 223, 223, 223, 223, 223, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 255, 255, 255, 255, 255, 255, 189,
189, 189, 189, 189, 189, 183, 183, 183, 183, 183, 189, 189, 189, 189, 189, 189, 189, 189,
189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 189, 189, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 189, 189, 189, 189, 189, 66, 189, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 255, 255, 255, 255, 255, 255, 255, 255, 255,
158, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 95,
255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 95, 95, 255, 255, 189, 189, 189, 189,
189, 173, 189, 189, 189, 189, 189, 189, 189, 255, 255, 245, 255, 255, 255, 255, 255, 189,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
189, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 255, 255, 255, 189, 189, 189, 189, 189, 255, 255, 255, 255, 255, 248,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 141,
141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 255, 255, 255, 81, 126, 81, 81, 81,
81, 81, 81, 81, 85, 5, 5, 5, 5, 5, 5, 5, 5, 49, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 189,
189, 189, 189, 189, 189, 189, 255, 255, 189, 189, 189, 189, 189, 189, 19, 189, 189, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 95, 255, 255, 255, 255,
255, 255, 255, 255, 255, 95, 95, 95, 95, 255, 255, 189, 189, 189, 189, 189, 173, 189, 189,
189, 189, 189, 189, 189, 255, 255, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 189, 189, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 189, 171, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 199, 199, 199, 199, 199, 199,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
199, 199, 199, 199, 199, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 191, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 7, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 189, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 81, 255, 255, 255, 255, 255, 255,
255, 255, 255, 36, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 40, 255, 255, 255,
255, 255, 255, 81, 81, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255,
]
.to_vec();

assert_eq_rs_ng!({
let mut strm = std::mem::MaybeUninit::<z_stream>::zeroed();
let err = unsafe {
deflateInit2_(
strm.as_mut_ptr(),
0,
Z_DEFLATED,
8,
3,
Z_HUFFMAN_ONLY,
zlibVersion(),
std::mem::size_of::<z_stream>() as c_int,
)
};
assert_eq!(ReturnCode::from(err), ReturnCode::Ok);

let strm = strm.assume_init_mut();

let buf_size = unsafe { deflateBound(strm, source.len() as u64) };

let mut dest = vec![0; buf_size as usize];
let chunk = 305u32;
let flush = Z_NO_FLUSH;

strm.next_in = source.as_mut_ptr().cast();
strm.avail_in = chunk; // First chunk.
strm.next_out = dest.as_mut_ptr().cast();
strm.avail_out = dest.len().try_into().unwrap();

// Deflate first chunk.
let err = unsafe { deflate(strm, flush) };
assert_eq!(ReturnCode::from(err), ReturnCode::Ok);

// Change the parameters.
let new_level = 0;
let new_strategy = Z_DEFAULT_STRATEGY;
let err = unsafe { deflateParams(strm, new_level, new_strategy) };
match ReturnCode::from(err) {
ReturnCode::Ok => {}
ReturnCode::BufError => {
// Flushing the current pending data may run us out of buffer space.
// Worst case double the buffer size.
let add_space = Ord::min(chunk, buf_size as u32);
dest.resize(dest.len() + add_space as usize, 0);

// If extend() reallocates, it may have moved in memory.
strm.next_out = dest.as_mut_ptr();
strm.avail_out += add_space;

let err = unsafe { deflateParams(strm, new_level, new_strategy) };
assert_eq!(ReturnCode::from(err), ReturnCode::Ok);
}
err => panic!("fatal {:?}", err),
}

// Deflate the rest in chunks.
let mut left: u32 = source.len() as u32 - chunk;
while left > 0 {
// Write the chunk.
let avail = Ord::min(chunk, left).try_into().unwrap();
strm.avail_in = avail;
let err = unsafe { deflate(strm, flush) };
match ReturnCode::from(err) {
ReturnCode::Ok => {
left -= avail;
}
ReturnCode::BufError => {
// Worst case double the buffer size.
let add_space = Ord::min(chunk, buf_size as u32);
dest.resize(dest.len() + add_space as usize, 0);

// If extend() reallocates, it may have moved in memory.
strm.next_out = dest.as_mut_ptr();
strm.avail_out += add_space;

left -= avail - strm.avail_in;
}
err => panic!("fatal {:?}", err),
}
}

assert_eq!(left, 0);

let _ = unsafe { deflateEnd(strm) };
});
}
7 changes: 6 additions & 1 deletion zlib-rs/src/deflate/algorithm/stored.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,15 @@ pub fn deflate_stored(stream: &mut DeflateStream, flush: DeflateFlush) -> BlockS
let state = &mut stream.state;
state.block_start -= state.w_size as isize;
state.strstart -= state.w_size;

// make sure we don't copy uninitialized bytes. While we discard the first lower w_size
// bytes, it is not guaranteed that the upper w_size bytes are all initialized
let copy = Ord::min(state.strstart, state.window.filled().len() - state.w_size);

state
.window
.filled_mut()
.copy_within(state.w_size..state.w_size + state.strstart, 0);
.copy_within(state.w_size..state.w_size + copy, 0);

if state.matches < 2 {
// add a pending slide_hash
Expand Down

0 comments on commit 43ca3df

Please sign in to comment.