Skip to content

Commit 5e2f935

Browse files
committed
Avoid an out-of-bounds panic in deflate_stored
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.
1 parent b1b4d20 commit 5e2f935

File tree

2 files changed

+185
-1
lines changed

2 files changed

+185
-1
lines changed

test-libz-rs-sys/src/lib.rs

+179
Original file line numberDiff line numberDiff line change
@@ -1552,3 +1552,182 @@ fn inflate_strict_is_off() {
15521552
(zlib_rs::ReturnCode::from(err), dest_len)
15531553
});
15541554
}
1555+
1556+
#[test]
1557+
fn deflate_stored_window_out_of_bounds() {
1558+
use core::ffi::c_int;
1559+
use zlib_rs::ReturnCode;
1560+
1561+
let mut source = [
1562+
161, 161, 161, 161, 179, 179, 179, 179, 179, 179, 133, 133, 133, 133, 13, 13, 13, 13, 13,
1563+
13, 13, 13, 13, 13, 13, 13, 13, 13, 95, 95, 95, 255, 179, 179, 179, 179, 179, 179, 179,
1564+
179, 179, 43, 179, 8, 179, 133, 133, 133, 133, 13, 13, 122, 13, 13, 13, 13, 13, 13, 13, 13,
1565+
13, 3, 13, 13, 95, 95, 95, 13, 13, 255, 255, 255, 189, 189, 189, 189, 189, 189, 189, 0,
1566+
189, 189, 189, 189, 189, 189, 189, 189, 189, 173, 189, 189, 189, 189, 189, 189, 189, 255,
1567+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1568+
255, 255, 255, 255, 255, 95, 95, 95, 255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95,
1569+
95, 95, 255, 255, 189, 189, 189, 189, 189, 173, 189, 189, 189, 189, 189, 189, 189, 255,
1570+
255, 245, 255, 255, 255, 255, 255, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1571+
255, 255, 255, 255, 255, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189,
1572+
189, 189, 189, 255, 255, 255, 255, 189, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
1573+
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 125, 125, 125, 125, 125, 39, 39, 39, 39,
1574+
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 125, 125, 125, 125, 125, 125,
1575+
125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 255, 18, 125, 125,
1576+
125, 69, 125, 125, 125, 125, 255, 255, 255, 255, 125, 125, 125, 125, 125, 63, 125, 125,
1577+
125, 125, 125, 125, 125, 125, 125, 223, 223, 223, 223, 223, 223, 223, 223, 39, 39, 39, 39,
1578+
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1579+
255, 255, 255, 255, 255, 255, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 255, 255, 255,
1580+
255, 255, 255, 13, 13, 13, 13, 13, 13, 13, 95, 95, 95, 255, 179, 179, 179, 179, 179, 179,
1581+
179, 179, 179, 43, 179, 8, 179, 133, 133, 133, 133, 13, 13, 122, 13, 13, 13, 13, 13, 13,
1582+
13, 13, 13, 3, 13, 13, 95, 95, 95, 13, 13, 255, 255, 255, 189, 189, 189, 189, 189, 189,
1583+
189, 0, 189, 189, 189, 189, 189, 189, 189, 189, 189, 173, 189, 189, 189, 189, 189, 189,
1584+
189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 255,
1585+
255, 255, 255, 189, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
1586+
13, 13, 13, 13, 13, 13, 13, 125, 125, 125, 125, 125, 39, 39, 39, 39, 39, 39, 39, 39, 39,
1587+
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
1588+
125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 255, 18, 125, 125, 125, 69, 125, 125,
1589+
125, 125, 255, 255, 255, 255, 125, 125, 125, 125, 125, 63, 125, 125, 125, 125, 125, 125,
1590+
125, 125, 125, 223, 223, 223, 223, 223, 223, 223, 223, 39, 39, 39, 39, 39, 39, 39, 39, 39,
1591+
39, 39, 39, 39, 39, 39, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1592+
255, 255, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 255, 255, 255, 255, 255, 255, 189,
1593+
189, 189, 189, 189, 189, 183, 183, 183, 183, 183, 189, 189, 189, 189, 189, 189, 189, 189,
1594+
189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 255, 255, 255, 255,
1595+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 189, 189, 255, 255,
1596+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1597+
255, 255, 255, 255, 255, 255, 255, 255, 255, 189, 189, 189, 189, 189, 66, 189, 65, 65, 65,
1598+
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1599+
158, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1600+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 95,
1601+
255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 95, 95, 255, 255, 189, 189, 189, 189,
1602+
189, 173, 189, 189, 189, 189, 189, 189, 189, 255, 255, 245, 255, 255, 255, 255, 255, 189,
1603+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1604+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1605+
189, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 5, 5,
1606+
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,
1607+
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
1608+
39, 39, 39, 39, 39, 255, 255, 255, 189, 189, 189, 189, 189, 255, 255, 255, 255, 255, 248,
1609+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 141,
1610+
141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
1611+
141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 255, 255, 255, 81, 126, 81, 81, 81,
1612+
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,
1613+
5, 5, 5, 5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 189,
1614+
189, 189, 189, 189, 189, 189, 255, 255, 189, 189, 189, 189, 189, 189, 19, 189, 189, 255,
1615+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 95, 95, 95, 255, 255, 255, 255,
1616+
255, 255, 255, 255, 255, 95, 95, 95, 95, 255, 255, 189, 189, 189, 189, 189, 173, 189, 189,
1617+
189, 189, 189, 189, 189, 255, 255, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1618+
255, 255, 255, 255, 255, 255, 255, 255, 189, 189, 255, 255, 255, 255, 255, 255, 255, 255,
1619+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1620+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1621+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1622+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1623+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1624+
255, 255, 255, 255, 189, 171, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1625+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 199, 199, 199, 199, 199, 199,
1626+
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
1627+
199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
1628+
199, 199, 199, 199, 199, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1629+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1630+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1631+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1632+
255, 191, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1633+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1634+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1635+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1636+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1637+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1638+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 7, 255, 255, 255, 255, 255,
1639+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1640+
255, 255, 255, 255, 255, 255, 189, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1641+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1642+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 81, 255, 255, 255, 255, 255, 255,
1643+
255, 255, 255, 36, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 40, 255, 255, 255,
1644+
255, 255, 255, 81, 81, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255,
1645+
]
1646+
.to_vec();
1647+
1648+
assert_eq_rs_ng!({
1649+
let mut strm = std::mem::MaybeUninit::<z_stream>::zeroed();
1650+
let err = unsafe {
1651+
deflateInit2_(
1652+
strm.as_mut_ptr(),
1653+
0,
1654+
Z_DEFLATED,
1655+
8,
1656+
3,
1657+
Z_HUFFMAN_ONLY,
1658+
zlibVersion(),
1659+
std::mem::size_of::<z_stream>() as c_int,
1660+
)
1661+
};
1662+
assert_eq!(ReturnCode::from(err), ReturnCode::Ok);
1663+
1664+
let strm = strm.assume_init_mut();
1665+
1666+
let buf_size = unsafe { deflateBound(strm, source.len() as _) };
1667+
1668+
let mut dest = vec![0; buf_size as usize];
1669+
let chunk = 305u32;
1670+
let flush = Z_NO_FLUSH;
1671+
1672+
strm.next_in = source.as_mut_ptr().cast();
1673+
strm.avail_in = chunk; // First chunk.
1674+
strm.next_out = dest.as_mut_ptr().cast();
1675+
strm.avail_out = dest.len().try_into().unwrap();
1676+
1677+
// Deflate first chunk.
1678+
let err = unsafe { deflate(strm, flush) };
1679+
assert_eq!(ReturnCode::from(err), ReturnCode::Ok);
1680+
1681+
// Change the parameters.
1682+
let new_level = 0;
1683+
let new_strategy = Z_DEFAULT_STRATEGY;
1684+
let err = unsafe { deflateParams(strm, new_level, new_strategy) };
1685+
match ReturnCode::from(err) {
1686+
ReturnCode::Ok => {}
1687+
ReturnCode::BufError => {
1688+
// Flushing the current pending data may run us out of buffer space.
1689+
// Worst case double the buffer size.
1690+
let add_space = Ord::min(chunk, buf_size as u32);
1691+
dest.resize(dest.len() + add_space as usize, 0);
1692+
1693+
// If extend() reallocates, it may have moved in memory.
1694+
strm.next_out = dest.as_mut_ptr();
1695+
strm.avail_out += add_space;
1696+
1697+
let err = unsafe { deflateParams(strm, new_level, new_strategy) };
1698+
assert_eq!(ReturnCode::from(err), ReturnCode::Ok);
1699+
}
1700+
err => panic!("fatal {:?}", err),
1701+
}
1702+
1703+
// Deflate the rest in chunks.
1704+
let mut left: u32 = source.len() as u32 - chunk;
1705+
while left > 0 {
1706+
// Write the chunk.
1707+
let avail = Ord::min(chunk, left).try_into().unwrap();
1708+
strm.avail_in = avail;
1709+
let err = unsafe { deflate(strm, flush) };
1710+
match ReturnCode::from(err) {
1711+
ReturnCode::Ok => {
1712+
left -= avail;
1713+
}
1714+
ReturnCode::BufError => {
1715+
// Worst case double the buffer size.
1716+
let add_space = Ord::min(chunk, buf_size as u32);
1717+
dest.resize(dest.len() + add_space as usize, 0);
1718+
1719+
// If extend() reallocates, it may have moved in memory.
1720+
strm.next_out = dest.as_mut_ptr();
1721+
strm.avail_out += add_space;
1722+
1723+
left -= avail - strm.avail_in;
1724+
}
1725+
err => panic!("fatal {:?}", err),
1726+
}
1727+
}
1728+
1729+
assert_eq!(left, 0);
1730+
1731+
let _ = unsafe { deflateEnd(strm) };
1732+
});
1733+
}

zlib-rs/src/deflate/algorithm/stored.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,15 @@ pub fn deflate_stored(stream: &mut DeflateStream, flush: DeflateFlush) -> BlockS
181181
let state = &mut stream.state;
182182
state.block_start -= state.w_size as isize;
183183
state.strstart -= state.w_size;
184+
185+
// make sure we don't copy uninitialized bytes. While we discard the first lower w_size
186+
// bytes, it is not guaranteed that the upper w_size bytes are all initialized
187+
let copy = Ord::min(state.strstart, state.window.filled().len() - state.w_size);
188+
184189
state
185190
.window
186191
.filled_mut()
187-
.copy_within(state.w_size..state.w_size + state.strstart, 0);
192+
.copy_within(state.w_size..state.w_size + copy, 0);
188193

189194
if state.matches < 2 {
190195
// add a pending slide_hash

0 commit comments

Comments
 (0)