Skip to content

Commit 466f24c

Browse files
committed
Don't fail in zlib.decompress with too big an input
1 parent 8be180d commit 466f24c

File tree

1 file changed

+28
-8
lines changed

1 file changed

+28
-8
lines changed

vm/src/stdlib/zlib.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,20 +108,40 @@ fn zlib_decompress(
108108
wbits: OptionalArg<i8>,
109109
bufsize: OptionalArg<usize>,
110110
vm: &VirtualMachine,
111-
) -> PyResult {
112-
let encoded_bytes = data.get_value();
111+
) -> PyResult<Vec<u8>> {
112+
let data = data.get_value();
113113

114114
let (header, wbits) = header_from_wbits(wbits);
115115
let bufsize = bufsize.unwrap_or(DEF_BUF_SIZE);
116116

117-
let mut decompressor = Decompress::new_with_window_bits(header, wbits);
118-
let mut decoded_bytes = Vec::with_capacity(bufsize);
117+
let mut d = Decompress::new_with_window_bits(header, wbits);
118+
let mut buf = Vec::new();
119119

120-
match decompressor.decompress_vec(&encoded_bytes, &mut decoded_bytes, FlushDecompress::Finish) {
121-
Ok(Status::BufError) => Err(zlib_error("inconsistent or truncated state", vm)),
122-
Err(_) => Err(zlib_error("invalid input data", vm)),
123-
_ => Ok(vm.ctx.new_bytes(decoded_bytes)),
120+
// TODO: maybe deduplicate this with the Decompress.{decompress,flush}
121+
'outer: for chunk in data.chunks(libc::c_uint::max_value() as usize) {
122+
// if this is the final chunk, finish it
123+
let flush = if d.total_in() == (data.len() - chunk.len()) as u64 {
124+
FlushDecompress::Finish
125+
} else {
126+
FlushDecompress::None
127+
};
128+
loop {
129+
buf.reserve(bufsize);
130+
match d.decompress_vec(chunk, &mut buf, flush) {
131+
// we've run out of space, loop again and allocate more
132+
Ok(_) if buf.len() == buf.capacity() => {}
133+
// we've reached the end of the stream, we're done
134+
Ok(Status::StreamEnd) => {
135+
break 'outer;
136+
}
137+
// we've reached the end of this chunk of the data, do the next one
138+
Ok(_) => break,
139+
Err(_) => return Err(zlib_error("invalid input data", vm)),
140+
}
141+
}
124142
}
143+
buf.shrink_to_fit();
144+
Ok(buf)
125145
}
126146

127147
fn zlib_decompressobj(

0 commit comments

Comments
 (0)