Skip to main content

cadmpeg_core/decode/
deflate.rs

1// SPDX-License-Identifier: Apache-2.0
2//! Bounded DEFLATE output for detection.
3
4use super::{DecodeContext, View};
5use crate::CodecError;
6use flate2::{Decompress, FlushDecompress, Status};
7
8impl DecodeContext<'_> {
9    /// Inflates one raw or zlib member up to `cap`. An oversized or malformed
10    /// member supplies no evidence. Resource refusals remain typed.
11    pub fn inflate_probe(
12        &self,
13        source: View<'_>,
14        cap: usize,
15        zlib: bool,
16    ) -> Result<Option<Vec<u8>>, CodecError> {
17        if let Some(limit) = self.resource_refusal() {
18            return Err(CodecError::ResourceLimit(limit));
19        }
20        let mut decoder = Decompress::new(zlib);
21        let mut output = Vec::new();
22        let mut chunk = [0_u8; 1024];
23        let mut offset = 0;
24        loop {
25            let before_in = decoder.total_in();
26            let before_out = decoder.total_out();
27            let Ok(status) = decoder.decompress(
28                &source.window()[offset..],
29                &mut chunk,
30                FlushDecompress::None,
31            ) else {
32                return Ok(None);
33            };
34            let consumed = usize::try_from(decoder.total_in() - before_in)
35                .map_err(|_| CodecError::Malformed("DEFLATE probe input overflow".into()))?;
36            let produced = usize::try_from(decoder.total_out() - before_out)
37                .map_err(|_| CodecError::Malformed("DEFLATE probe output overflow".into()))?;
38            offset += consumed;
39            if cap
40                .checked_sub(output.len())
41                .is_none_or(|remaining| produced > remaining)
42            {
43                return Ok(None);
44            }
45            output.extend_from_slice(&chunk[..produced]);
46            if status == Status::StreamEnd || (consumed == 0 && produced == 0) {
47                return Ok(Some(output));
48            }
49        }
50    }
51}