diff --git a/test-libz-rs-sys/src/lib.rs b/test-libz-rs-sys/src/lib.rs index 1c869b55..648c385e 100644 --- a/test-libz-rs-sys/src/lib.rs +++ b/test-libz-rs-sys/src/lib.rs @@ -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::::zeroed(); + let err = unsafe { + deflateInit2_( + strm.as_mut_ptr(), + 0, + Z_DEFLATED, + 8, + 3, + Z_HUFFMAN_ONLY, + zlibVersion(), + std::mem::size_of::() 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 _) }; + + 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 = source.len() as uInt - chunk; + while left > 0 { + // Write the chunk. + let avail = Ord::min(chunk, left); + 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 uInt); + 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) }; + }); +} diff --git a/zlib-rs/src/deflate/algorithm/stored.rs b/zlib-rs/src/deflate/algorithm/stored.rs index 17d042c9..6c18db36 100644 --- a/zlib-rs/src/deflate/algorithm/stored.rs +++ b/zlib-rs/src/deflate/algorithm/stored.rs @@ -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