miniz_oxide/inflate/
core.rs

1//! Streaming decompression functionality.
2
3use super::*;
4use crate::shared::{update_adler32, HUFFMAN_LENGTH_ORDER};
5
6use std::convert::TryInto;
7use std::{cmp, slice};
8
9use self::output_buffer::OutputBuffer;
10
11pub const TINFL_LZ_DICT_SIZE: usize = 32_768;
12
13/// A struct containing huffman code lengths and the huffman code tree used by the decompressor.
14struct HuffmanTable {
15    /// Length of the code at each index.
16    pub code_size: [u8; MAX_HUFF_SYMBOLS_0],
17    /// Fast lookup table for shorter huffman codes.
18    ///
19    /// See `HuffmanTable::fast_lookup`.
20    pub look_up: [i16; FAST_LOOKUP_SIZE as usize],
21    /// Full huffman tree.
22    ///
23    /// Positive values are edge nodes/symbols, negative values are
24    /// parent nodes/references to other nodes.
25    pub tree: [i16; MAX_HUFF_TREE_SIZE],
26}
27
28impl HuffmanTable {
29    fn new() -> HuffmanTable {
30        HuffmanTable {
31            code_size: [0; MAX_HUFF_SYMBOLS_0],
32            look_up: [0; FAST_LOOKUP_SIZE as usize],
33            tree: [0; MAX_HUFF_TREE_SIZE],
34        }
35    }
36
37    /// Look for a symbol in the fast lookup table.
38    /// The symbol is stored in the lower 9 bits, the length in the next 6.
39    /// If the returned value is negative, the code wasn't found in the
40    /// fast lookup table and the full tree has to be traversed to find the code.
41    #[inline]
42    fn fast_lookup(&self, bit_buf: BitBuffer) -> i16 {
43        self.look_up[(bit_buf & BitBuffer::from(FAST_LOOKUP_SIZE - 1)) as usize]
44    }
45
46    /// Get the symbol and the code length from the huffman tree.
47    #[inline]
48    fn tree_lookup(&self, fast_symbol: i32, bit_buf: BitBuffer, mut code_len: u32) -> (i32, u32) {
49        let mut symbol = fast_symbol;
50        // We step through the tree until we encounter a positive value, which indicates a
51        // symbol.
52        loop {
53            // symbol here indicates the position of the left (0) node, if the next bit is 1
54            // we add 1 to the lookup position to get the right node.
55            symbol = i32::from(self.tree[(!symbol + ((bit_buf >> code_len) & 1) as i32) as usize]);
56            code_len += 1;
57            if symbol >= 0 {
58                break;
59            }
60        }
61        (symbol, code_len)
62    }
63
64    #[inline]
65    /// Look up a symbol and code length from the bits in the provided bit buffer.
66    ///
67    /// Returns Some(symbol, length) on success,
68    /// None if the length is 0.
69    ///
70    /// It's possible we could avoid checking for 0 if we can guarantee a sane table.
71    /// TODO: Check if a smaller type for code_len helps performance.
72    fn lookup(&self, bit_buf: BitBuffer) -> Option<(i32, u32)> {
73        let symbol = self.fast_lookup(bit_buf).into();
74        if symbol >= 0 {
75            if (symbol >> 9) as u32 != 0 {
76                Some((symbol, (symbol >> 9) as u32))
77            } else {
78                // Zero-length code.
79                None
80            }
81        } else {
82            // We didn't get a symbol from the fast lookup table, so check the tree instead.
83            Some(self.tree_lookup(symbol, bit_buf, FAST_LOOKUP_BITS.into()))
84        }
85    }
86}
87
88/// The number of huffman tables used.
89const MAX_HUFF_TABLES: usize = 3;
90/// The length of the first (literal/length) huffman table.
91const MAX_HUFF_SYMBOLS_0: usize = 288;
92/// The length of the second (distance) huffman table.
93const MAX_HUFF_SYMBOLS_1: usize = 32;
94/// The length of the last (huffman code length) huffman table.
95const _MAX_HUFF_SYMBOLS_2: usize = 19;
96/// The maximum length of a code that can be looked up in the fast lookup table.
97const FAST_LOOKUP_BITS: u8 = 10;
98/// The size of the fast lookup table.
99const FAST_LOOKUP_SIZE: u32 = 1 << FAST_LOOKUP_BITS;
100const MAX_HUFF_TREE_SIZE: usize = MAX_HUFF_SYMBOLS_0 * 2;
101const LITLEN_TABLE: usize = 0;
102const DIST_TABLE: usize = 1;
103const HUFFLEN_TABLE: usize = 2;
104
105pub mod inflate_flags {
106    /// Should we try to parse a zlib header?
107    pub const TINFL_FLAG_PARSE_ZLIB_HEADER: u32 = 1;
108    /// There is more input that hasn't been given to the decompressor yet.
109    pub const TINFL_FLAG_HAS_MORE_INPUT: u32 = 2;
110    /// The output buffer should not wrap around.
111    pub const TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: u32 = 4;
112    /// Should we calculate the adler32 checksum of the output data?
113    pub const TINFL_FLAG_COMPUTE_ADLER32: u32 = 8;
114}
115
116use self::inflate_flags::*;
117
118const MIN_TABLE_SIZES: [u16; 3] = [257, 1, 4];
119
120#[cfg(target_pointer_width = "64")]
121type BitBuffer = u64;
122
123#[cfg(not(target_pointer_width = "64"))]
124type BitBuffer = u32;
125
126/// Main decompression struct.
127///
128pub struct DecompressorOxide {
129    /// Current state of the decompressor.
130    state: core::State,
131    /// Number of bits in the bit buffer.
132    num_bits: u32,
133    /// Zlib CMF
134    z_header0: u32,
135    /// Zlib FLG
136    z_header1: u32,
137    /// Adler32 checksum from the zlib header.
138    z_adler32: u32,
139    /// 1 if the current block is the last block, 0 otherwise.
140    finish: u32,
141    /// The type of the current block.
142    block_type: u32,
143    /// 1 if the adler32 value should be checked.
144    check_adler32: u32,
145    /// Last match distance.
146    dist: u32,
147    /// Variable used for match length, symbols, and a number of other things.
148    counter: u32,
149    /// Number of extra bits for the last length or distance code.
150    num_extra: u32,
151    /// Number of entries in each huffman table.
152    table_sizes: [u32; MAX_HUFF_TABLES],
153    /// Buffer of input data.
154    bit_buf: BitBuffer,
155    /// Huffman tables.
156    tables: [HuffmanTable; MAX_HUFF_TABLES],
157    /// Raw block header.
158    raw_header: [u8; 4],
159    /// Huffman length codes.
160    len_codes: [u8; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1 + 137],
161}
162
163impl DecompressorOxide {
164    /// Create a new tinfl_decompressor with all fields set to 0.
165    pub fn new() -> DecompressorOxide {
166        DecompressorOxide::default()
167    }
168
169    /// Set the current state to `Start`.
170    #[inline]
171    pub fn init(&mut self) {
172        // The rest of the data is reset or overwritten when used.
173        self.state = core::State::Start;
174    }
175
176    /// Returns the adler32 checksum of the currently decompressed data.
177    #[inline]
178    pub fn adler32(&self) -> Option<u32> {
179        if self.state != State::Start && !self.state.is_failure() && self.z_header0 != 0 {
180            Some(self.check_adler32)
181        } else {
182            None
183        }
184    }
185}
186
187impl Default for DecompressorOxide {
188    /// Create a new tinfl_decompressor with all fields set to 0.
189    #[inline(always)]
190    fn default() -> Self {
191        DecompressorOxide {
192            state: core::State::Start,
193            num_bits: 0,
194            z_header0: 0,
195            z_header1: 0,
196            z_adler32: 0,
197            finish: 0,
198            block_type: 0,
199            check_adler32: 0,
200            dist: 0,
201            counter: 0,
202            num_extra: 0,
203            table_sizes: [0; MAX_HUFF_TABLES],
204            bit_buf: 0,
205            // TODO:(oyvindln) Check that copies here are optimized out in release mode.
206            tables: [
207                HuffmanTable::new(),
208                HuffmanTable::new(),
209                HuffmanTable::new(),
210            ],
211            raw_header: [0; 4],
212            len_codes: [0; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1 + 137],
213        }
214    }
215}
216
217#[derive(Copy, Clone, PartialEq, Eq, Debug)]
218enum State {
219    Start = 0,
220    ReadZlibCmf,
221    ReadZlibFlg,
222    ReadBlockHeader,
223    BlockTypeNoCompression,
224    RawHeader,
225    RawMemcpy1,
226    RawMemcpy2,
227    ReadTableSizes,
228    ReadHufflenTableCodeSize,
229    ReadLitlenDistTablesCodeSize,
230    ReadExtraBitsCodeSize,
231    DecodeLitlen,
232    WriteSymbol,
233    ReadExtraBitsLitlen,
234    DecodeDistance,
235    ReadExtraBitsDistance,
236    RawReadFirstByte,
237    RawStoreFirstByte,
238    WriteLenBytesToEnd,
239    BlockDone,
240    HuffDecodeOuterLoop1,
241    HuffDecodeOuterLoop2,
242    ReadAdler32,
243
244    DoneForever,
245
246    // Failure states.
247    BlockTypeUnexpected,
248    BadCodeSizeSum,
249    BadTotalSymbols,
250    BadZlibHeader,
251    DistanceOutOfBounds,
252    BadRawLength,
253    BadCodeSizeDistPrevLookup,
254    InvalidLitlen,
255    InvalidDist,
256    InvalidCodeLen,
257}
258
259impl State {
260    fn is_failure(self) -> bool {
261        match self {
262            BlockTypeUnexpected => true,
263            BadCodeSizeSum => true,
264            BadTotalSymbols => true,
265            BadZlibHeader => true,
266            DistanceOutOfBounds => true,
267            BadRawLength => true,
268            BadCodeSizeDistPrevLookup => true,
269            InvalidLitlen => true,
270            InvalidDist => true,
271            _ => false,
272        }
273    }
274
275    #[inline]
276    fn begin(&mut self, new_state: State) {
277        *self = new_state;
278    }
279}
280
281use self::State::*;
282
283// Not sure why miniz uses 32-bit values for these, maybe alignment/cache again?
284// # Optimization
285// We add a extra value at the end and make the tables 32 elements long
286// so we can use a mask to avoid bounds checks.
287// The invalid values are set to something high enough to avoid underflowing
288// the match length.
289/// Base length for each length code.
290///
291/// The base is used together with the value of the extra bits to decode the actual
292/// length/distance values in a match.
293#[rustfmt::skip]
294const LENGTH_BASE: [u16; 32] = [
295    3,  4,  5,  6,  7,  8,  9,  10,  11,  13,  15,  17,  19,  23,  27,  31,
296    35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 512, 512, 512
297];
298
299/// Number of extra bits for each length code.
300#[rustfmt::skip]
301const LENGTH_EXTRA: [u8; 32] = [
302    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
303    3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0
304];
305
306/// Base length for each distance code.
307#[rustfmt::skip]
308const DIST_BASE: [u16; 32] = [
309    1,    2,    3,    4,    5,    7,      9,      13,     17,     25,    33,
310    49,   65,   97,   129,  193,  257,    385,    513,    769,    1025,  1537,
311    2049, 3073, 4097, 6145, 8193, 12_289, 16_385, 24_577, 32_768, 32_768
312];
313
314/// Number of extra bits for each distance code.
315#[rustfmt::skip]
316const DIST_EXTRA: [u8; 32] = [
317    0, 0, 0, 0, 1, 1, 2,  2,  3,  3,  4,  4,  5,  5,  6,  6,
318    7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13
319];
320
321/// The mask used when indexing the base/extra arrays.
322const BASE_EXTRA_MASK: usize = 32 - 1;
323
324/// Sets the value of all the elements of the slice to `val`.
325#[inline]
326fn memset<T: Copy>(slice: &mut [T], val: T) {
327    for x in slice {
328        *x = val
329    }
330}
331
332/// Read an le u16 value from the slice iterator.
333///
334/// # Panics
335/// Panics if there are less than two bytes left.
336#[inline]
337fn read_u16_le(iter: &mut slice::Iter<u8>) -> u16 {
338    let ret = {
339        let two_bytes = iter.as_ref()[..2].try_into().unwrap();
340        u16::from_le_bytes(two_bytes)
341    };
342    iter.nth(1);
343    ret
344}
345
346/// Read an le u32 value from the slice iterator.
347///
348/// # Panics
349/// Panics if there are less than four bytes left.
350#[inline(always)]
351#[cfg(target_pointer_width = "64")]
352fn read_u32_le(iter: &mut slice::Iter<u8>) -> u32 {
353    let ret = {
354        let four_bytes: [u8; 4] = iter.as_ref()[..4].try_into().unwrap();
355        u32::from_le_bytes(four_bytes)
356    };
357    iter.nth(3);
358    ret
359}
360
361/// Ensure that there is data in the bit buffer.
362///
363/// On 64-bit platform, we use a 64-bit value so this will
364/// result in there being at least 32 bits in the bit buffer.
365/// This function assumes that there is at least 4 bytes left in the input buffer.
366#[inline(always)]
367#[cfg(target_pointer_width = "64")]
368fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>) {
369    // Read four bytes into the buffer at once.
370    if l.num_bits < 30 {
371        l.bit_buf |= BitBuffer::from(read_u32_le(in_iter)) << l.num_bits;
372        l.num_bits += 32;
373    }
374}
375
376/// Same as previous, but for non-64-bit platforms.
377/// Ensures at least 16 bits are present, requires at least 2 bytes in the in buffer.
378#[inline(always)]
379#[cfg(not(target_pointer_width = "64"))]
380fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>) {
381    // If the buffer is 32-bit wide, read 2 bytes instead.
382    if l.num_bits < 15 {
383        l.bit_buf |= BitBuffer::from(read_u16_le(in_iter)) << l.num_bits;
384        l.num_bits += 16;
385    }
386}
387
388/// Check that the zlib header is correct and that there is enough space in the buffer
389/// for the window size specified in the header.
390///
391/// See https://tools.ietf.org/html/rfc1950
392#[inline]
393fn validate_zlib_header(cmf: u32, flg: u32, flags: u32, mask: usize) -> Action {
394    let mut failed =
395    // cmf + flg should be divisible by 31.
396        (((cmf * 256) + flg) % 31 != 0) ||
397    // If this flag is set, a dictionary was used for this zlib compressed data.
398    // This is currently not supported by miniz or miniz-oxide
399        ((flg & 0b0010_0000) != 0) ||
400    // Compression method. Only 8(DEFLATE) is defined by the standard.
401        ((cmf & 15) != 8);
402
403    let window_size = 1 << ((cmf >> 4) + 8);
404    if (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) == 0 {
405        // Bail if the buffer is wrapping and the window size is larger than the buffer.
406        failed |= (mask + 1) < window_size;
407    }
408
409    // Zlib doesn't allow window sizes above 32 * 1024.
410    failed |= window_size > 32_768;
411
412    if failed {
413        Action::Jump(BadZlibHeader)
414    } else {
415        Action::Jump(ReadBlockHeader)
416    }
417}
418
419enum Action {
420    None,
421    Jump(State),
422    End(TINFLStatus),
423}
424
425/// Try to decode the next huffman code, and puts it in the counter field of the decompressor
426/// if successful.
427///
428/// # Returns
429/// The specified action returned from `f` on success,
430/// `Action::End` if there are not enough data left to decode a symbol.
431fn decode_huffman_code<F>(
432    r: &mut DecompressorOxide,
433    l: &mut LocalVars,
434    table: usize,
435    flags: u32,
436    in_iter: &mut slice::Iter<u8>,
437    f: F,
438) -> Action
439where
440    F: FnOnce(&mut DecompressorOxide, &mut LocalVars, i32) -> Action,
441{
442    // As the huffman codes can be up to 15 bits long we need at least 15 bits
443    // ready in the bit buffer to start decoding the next huffman code.
444    if l.num_bits < 15 {
445        // First, make sure there is enough data in the bit buffer to decode a huffman code.
446        if in_iter.len() < 2 {
447            // If there is less than 2 bytes left in the input buffer, we try to look up
448            // the huffman code with what's available, and return if that doesn't succeed.
449            // Original explanation in miniz:
450            // /* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes
451            //  * remaining in the input buffer falls below 2. */
452            // /* It reads just enough bytes from the input stream that are needed to decode
453            //  * the next Huffman code (and absolutely no more). It works by trying to fully
454            //  * decode a */
455            // /* Huffman code by using whatever bits are currently present in the bit buffer.
456            //  * If this fails, it reads another byte, and tries again until it succeeds or
457            //  * until the */
458            // /* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
459            loop {
460                let mut temp = i32::from(r.tables[table].fast_lookup(l.bit_buf));
461
462                if temp >= 0 {
463                    let code_len = (temp >> 9) as u32;
464                    if (code_len != 0) && (l.num_bits >= code_len) {
465                        break;
466                    }
467                } else if l.num_bits > FAST_LOOKUP_BITS.into() {
468                    let mut code_len = u32::from(FAST_LOOKUP_BITS);
469                    loop {
470                        temp = i32::from(
471                            r.tables[table].tree
472                                [(!temp + ((l.bit_buf >> code_len) & 1) as i32) as usize],
473                        );
474                        code_len += 1;
475                        if temp >= 0 || l.num_bits < code_len + 1 {
476                            break;
477                        }
478                    }
479                    if temp >= 0 {
480                        break;
481                    }
482                }
483
484                // TODO: miniz jumps straight to here after getting here again after failing to read
485                // a byte.
486                // Doing that lets miniz avoid re-doing the lookup that that was done in the
487                // previous call.
488                let mut byte = 0;
489                if let a @ Action::End(_) = read_byte(in_iter, flags, |b| {
490                    byte = b;
491                    Action::None
492                }) {
493                    return a;
494                };
495
496                // Do this outside closure for now to avoid borrowing r.
497                l.bit_buf |= BitBuffer::from(byte) << l.num_bits;
498                l.num_bits += 8;
499
500                if l.num_bits >= 15 {
501                    break;
502                }
503            }
504        } else {
505            // There is enough data in the input buffer, so read the next two bytes
506            // and add them to the bit buffer.
507            // Unwrapping here is fine since we just checked that there are at least two
508            // bytes left.
509            l.bit_buf |= BitBuffer::from(read_u16_le(in_iter)) << l.num_bits;
510            l.num_bits += 16;
511        }
512    }
513
514    // We now have at least 15 bits in the input buffer.
515    let mut symbol = i32::from(r.tables[table].fast_lookup(l.bit_buf));
516    let code_len;
517    // If the symbol was found in the fast lookup table.
518    if symbol >= 0 {
519        // Get the length value from the top bits.
520        // As we shift down the sign bit, converting to an unsigned value
521        // shouldn't overflow.
522        code_len = (symbol >> 9) as u32;
523        // Mask out the length value.
524        symbol &= 511;
525    } else {
526        let res = r.tables[table].tree_lookup(symbol, l.bit_buf, u32::from(FAST_LOOKUP_BITS));
527        symbol = res.0;
528        code_len = res.1 as u32;
529    };
530
531    if code_len == 0 {
532        return Action::Jump(InvalidCodeLen);
533    }
534
535    l.bit_buf >>= code_len as u32;
536    l.num_bits -= code_len;
537    f(r, l, symbol)
538}
539
540/// Try to read one byte from `in_iter` and call `f` with the read byte as an argument,
541/// returning the result.
542/// If reading fails, `Action::End is returned`
543#[inline]
544fn read_byte<F>(in_iter: &mut slice::Iter<u8>, flags: u32, f: F) -> Action
545where
546    F: FnOnce(u8) -> Action,
547{
548    match in_iter.next() {
549        None => end_of_input(flags),
550        Some(&byte) => f(byte),
551    }
552}
553
554// TODO: `l: &mut LocalVars` may be slow similar to decompress_fast (even with inline(always))
555/// Try to read `amount` number of bits from `in_iter` and call the function `f` with the bits as an
556/// an argument after reading, returning the result of that function, or `Action::End` if there are
557/// not enough bytes left.
558#[inline]
559#[allow(clippy::while_immutable_condition)]
560fn read_bits<F>(
561    l: &mut LocalVars,
562    amount: u32,
563    in_iter: &mut slice::Iter<u8>,
564    flags: u32,
565    f: F,
566) -> Action
567where
568    F: FnOnce(&mut LocalVars, BitBuffer) -> Action,
569{
570    // Clippy gives a false positive warning here due to the closure.
571    // Read enough bytes from the input iterator to cover the number of bits we want.
572    while l.num_bits < amount {
573        match read_byte(in_iter, flags, |byte| {
574            l.bit_buf |= BitBuffer::from(byte) << l.num_bits;
575            l.num_bits += 8;
576            Action::None
577        }) {
578            Action::None => (),
579            // If there are not enough bytes in the input iterator, return and signal that we need
580            // more.
581            action => return action,
582        }
583    }
584
585    let bits = l.bit_buf & ((1 << amount) - 1);
586    l.bit_buf >>= amount;
587    l.num_bits -= amount;
588    f(l, bits)
589}
590
591#[inline]
592fn pad_to_bytes<F>(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>, flags: u32, f: F) -> Action
593where
594    F: FnOnce(&mut LocalVars) -> Action,
595{
596    let num_bits = l.num_bits & 7;
597    read_bits(l, num_bits, in_iter, flags, |l, _| f(l))
598}
599
600#[inline]
601fn end_of_input(flags: u32) -> Action {
602    Action::End(if flags & TINFL_FLAG_HAS_MORE_INPUT != 0 {
603        TINFLStatus::NeedsMoreInput
604    } else {
605        TINFLStatus::FailedCannotMakeProgress
606    })
607}
608
609#[inline]
610fn undo_bytes(l: &mut LocalVars, max: u32) -> u32 {
611    let res = cmp::min(l.num_bits >> 3, max);
612    l.num_bits -= res << 3;
613    res
614}
615
616fn start_static_table(r: &mut DecompressorOxide) {
617    r.table_sizes[LITLEN_TABLE] = 288;
618    r.table_sizes[DIST_TABLE] = 32;
619    memset(&mut r.tables[LITLEN_TABLE].code_size[0..144], 8);
620    memset(&mut r.tables[LITLEN_TABLE].code_size[144..256], 9);
621    memset(&mut r.tables[LITLEN_TABLE].code_size[256..280], 7);
622    memset(&mut r.tables[LITLEN_TABLE].code_size[280..288], 8);
623    memset(&mut r.tables[DIST_TABLE].code_size[0..32], 5);
624}
625
626fn init_tree(r: &mut DecompressorOxide, l: &mut LocalVars) -> Action {
627    loop {
628        let table = &mut r.tables[r.block_type as usize];
629        let table_size = r.table_sizes[r.block_type as usize] as usize;
630        let mut total_symbols = [0u32; 16];
631        let mut next_code = [0u32; 17];
632        memset(&mut table.look_up[..], 0);
633        memset(&mut table.tree[..], 0);
634
635        for &code_size in &table.code_size[..table_size] {
636            total_symbols[code_size as usize] += 1;
637        }
638
639        let mut used_symbols = 0;
640        let mut total = 0;
641        for i in 1..16 {
642            used_symbols += total_symbols[i];
643            total += total_symbols[i];
644            total <<= 1;
645            next_code[i + 1] = total;
646        }
647
648        if total != 65_536 && used_symbols > 1 {
649            return Action::Jump(BadTotalSymbols);
650        }
651
652        let mut tree_next = -1;
653        for symbol_index in 0..table_size {
654            let mut rev_code = 0;
655            let code_size = table.code_size[symbol_index];
656            if code_size == 0 {
657                continue;
658            }
659
660            let mut cur_code = next_code[code_size as usize];
661            next_code[code_size as usize] += 1;
662
663            for _ in 0..code_size {
664                rev_code = (rev_code << 1) | (cur_code & 1);
665                cur_code >>= 1;
666            }
667
668            if code_size <= FAST_LOOKUP_BITS {
669                let k = (i16::from(code_size) << 9) | symbol_index as i16;
670                while rev_code < FAST_LOOKUP_SIZE {
671                    table.look_up[rev_code as usize] = k;
672                    rev_code += 1 << code_size;
673                }
674                continue;
675            }
676
677            let mut tree_cur = table.look_up[(rev_code & (FAST_LOOKUP_SIZE - 1)) as usize];
678            if tree_cur == 0 {
679                table.look_up[(rev_code & (FAST_LOOKUP_SIZE - 1)) as usize] = tree_next as i16;
680                tree_cur = tree_next;
681                tree_next -= 2;
682            }
683
684            rev_code >>= FAST_LOOKUP_BITS - 1;
685            for _ in FAST_LOOKUP_BITS + 1..code_size {
686                rev_code >>= 1;
687                tree_cur -= (rev_code & 1) as i16;
688                if table.tree[(-tree_cur - 1) as usize] == 0 {
689                    table.tree[(-tree_cur - 1) as usize] = tree_next as i16;
690                    tree_cur = tree_next;
691                    tree_next -= 2;
692                } else {
693                    tree_cur = table.tree[(-tree_cur - 1) as usize];
694                }
695            }
696
697            rev_code >>= 1;
698            tree_cur -= (rev_code & 1) as i16;
699            table.tree[(-tree_cur - 1) as usize] = symbol_index as i16;
700        }
701
702        if r.block_type == 2 {
703            l.counter = 0;
704            return Action::Jump(ReadLitlenDistTablesCodeSize);
705        }
706
707        if r.block_type == 0 {
708            break;
709        }
710        r.block_type -= 1;
711    }
712
713    l.counter = 0;
714    Action::Jump(DecodeLitlen)
715}
716
717// A helper macro for generating the state machine.
718//
719// As Rust doesn't have fallthrough on matches, we have to return to the match statement
720// and jump for each state change. (Which would ideally be optimized away, but often isn't.)
721macro_rules! generate_state {
722    ($state: ident, $state_machine: tt, $f: expr) => {
723        loop {
724            match $f {
725                Action::None => continue,
726                Action::Jump(new_state) => {
727                    $state = new_state;
728                    continue $state_machine;
729                },
730                Action::End(result) => break $state_machine result,
731            }
732        }
733    };
734}
735
736#[derive(Copy, Clone)]
737struct LocalVars {
738    pub bit_buf: BitBuffer,
739    pub num_bits: u32,
740    pub dist: u32,
741    pub counter: u32,
742    pub num_extra: u32,
743}
744
745#[inline]
746fn transfer(
747    out_slice: &mut [u8],
748    mut source_pos: usize,
749    mut out_pos: usize,
750    match_len: usize,
751    out_buf_size_mask: usize,
752) {
753    for _ in 0..match_len >> 2 {
754        out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask];
755        out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask];
756        out_slice[out_pos + 2] = out_slice[(source_pos + 2) & out_buf_size_mask];
757        out_slice[out_pos + 3] = out_slice[(source_pos + 3) & out_buf_size_mask];
758        source_pos += 4;
759        out_pos += 4;
760    }
761
762    match match_len & 3 {
763        0 => (),
764        1 => out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask],
765        2 => {
766            out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask];
767            out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask];
768        }
769        3 => {
770            out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask];
771            out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask];
772            out_slice[out_pos + 2] = out_slice[(source_pos + 2) & out_buf_size_mask];
773        }
774        _ => unreachable!(),
775    }
776}
777
778/// Presumes that there is at least match_len bytes in output left.
779#[inline]
780fn apply_match(
781    out_slice: &mut [u8],
782    out_pos: usize,
783    dist: usize,
784    match_len: usize,
785    out_buf_size_mask: usize,
786) {
787    debug_assert!(out_pos + match_len <= out_slice.len());
788
789    let source_pos = out_pos.wrapping_sub(dist) & out_buf_size_mask;
790
791    if match_len == 3 {
792        // Fast path for match len 3.
793        out_slice[out_pos] = out_slice[source_pos];
794        out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask];
795        out_slice[out_pos + 2] = out_slice[(source_pos + 2) & out_buf_size_mask];
796        return;
797    }
798
799    if cfg!(not(any(target_arch = "x86", target_arch = "x86_64"))) {
800        // We are not on x86 so copy manually.
801        transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask);
802        return;
803    }
804
805    if source_pos >= out_pos && (source_pos - out_pos) < match_len {
806        transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask);
807    } else if match_len <= dist && source_pos + match_len < out_slice.len() {
808        // Destination and source segments does not intersect and source does not wrap.
809        if source_pos < out_pos {
810            let (from_slice, to_slice) = out_slice.split_at_mut(out_pos);
811            to_slice[..match_len].copy_from_slice(&from_slice[source_pos..source_pos + match_len]);
812        } else {
813            let (to_slice, from_slice) = out_slice.split_at_mut(source_pos);
814            to_slice[out_pos..out_pos + match_len].copy_from_slice(&from_slice[..match_len]);
815        }
816    } else {
817        transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask);
818    }
819}
820
821/// Fast inner decompression loop which is run  while there is at least
822/// 259 bytes left in the output buffer, and at least 6 bytes left in the input buffer
823/// (The maximum one match would need + 1).
824///
825/// This was inspired by a similar optimization in zlib, which uses this info to do
826/// faster unchecked copies of multiple bytes at a time.
827/// Currently we don't do this here, but this function does avoid having to jump through the
828/// big match loop on each state change(as rust does not have fallthrough or gotos at the moment),
829/// and already improves decompression speed a fair bit.
830fn decompress_fast(
831    r: &mut DecompressorOxide,
832    mut in_iter: &mut slice::Iter<u8>,
833    out_buf: &mut OutputBuffer,
834    flags: u32,
835    local_vars: &mut LocalVars,
836    out_buf_size_mask: usize,
837) -> (TINFLStatus, State) {
838    // Make a local copy of the most used variables, to avoid having to update and read from values
839    // in a random memory location and to encourage more register use.
840    let mut l = *local_vars;
841    let mut state;
842
843    let status: TINFLStatus = 'o: loop {
844        state = State::DecodeLitlen;
845        loop {
846            // This function assumes that there is at least 259 bytes left in the output buffer,
847            // and that there is at least 14 bytes left in the input buffer. 14 input bytes:
848            // 15 (prev lit) + 15 (length) + 5 (length extra) + 15 (dist)
849            // + 29 + 32 (left in bit buf, including last 13 dist extra) = 111 bits < 14 bytes
850            // We need the one extra byte as we may write one length and one full match
851            // before checking again.
852            if out_buf.bytes_left() < 259 || in_iter.len() < 14 {
853                state = State::DecodeLitlen;
854                break 'o TINFLStatus::Done;
855            }
856
857            fill_bit_buffer(&mut l, &mut in_iter);
858
859            if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) {
860                l.counter = symbol as u32;
861                l.bit_buf >>= code_len;
862                l.num_bits -= code_len;
863
864                if (l.counter & 256) != 0 {
865                    // The symbol is not a literal.
866                    break;
867                } else {
868                    // If we have a 32-bit buffer we need to read another two bytes now
869                    // to have enough bits to keep going.
870                    if cfg!(not(target_pointer_width = "64")) {
871                        fill_bit_buffer(&mut l, &mut in_iter);
872                    }
873
874                    if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) {
875                        l.bit_buf >>= code_len;
876                        l.num_bits -= code_len;
877                        // The previous symbol was a literal, so write it directly and check
878                        // the next one.
879                        out_buf.write_byte(l.counter as u8);
880                        if (symbol & 256) != 0 {
881                            l.counter = symbol as u32;
882                            // The symbol is a length value.
883                            break;
884                        } else {
885                            // The symbol is a literal, so write it directly and continue.
886                            out_buf.write_byte(symbol as u8);
887                        }
888                    } else {
889                        state.begin(InvalidCodeLen);
890                        break 'o TINFLStatus::Failed;
891                    }
892                }
893            } else {
894                state.begin(InvalidCodeLen);
895                break 'o TINFLStatus::Failed;
896            }
897        }
898
899        // Mask the top bits since they may contain length info.
900        l.counter &= 511;
901        if l.counter == 256 {
902            // We hit the end of block symbol.
903            state.begin(BlockDone);
904            break 'o TINFLStatus::Done;
905        } else if l.counter > 285 {
906            // Invalid code.
907            // We already verified earlier that the code is > 256.
908            state.begin(InvalidLitlen);
909            break 'o TINFLStatus::Failed;
910        } else {
911            // The symbol was a length code.
912            // # Optimization
913            // Mask the value to avoid bounds checks
914            // We could use get_unchecked later if can statically verify that
915            // this will never go out of bounds.
916            l.num_extra = u32::from(LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]);
917            l.counter = u32::from(LENGTH_BASE[(l.counter - 257) as usize & BASE_EXTRA_MASK]);
918            // Length and distance codes have a number of extra bits depending on
919            // the base, which together with the base gives us the exact value.
920
921            fill_bit_buffer(&mut l, &mut in_iter);
922            if l.num_extra != 0 {
923                let extra_bits = l.bit_buf & ((1 << l.num_extra) - 1);
924                l.bit_buf >>= l.num_extra;
925                l.num_bits -= l.num_extra;
926                l.counter += extra_bits as u32;
927            }
928
929            // We found a length code, so a distance code should follow.
930
931            if cfg!(not(target_pointer_width = "64")) {
932                fill_bit_buffer(&mut l, &mut in_iter);
933            }
934
935            if let Some((mut symbol, code_len)) = r.tables[DIST_TABLE].lookup(l.bit_buf) {
936                symbol &= 511;
937                l.bit_buf >>= code_len;
938                l.num_bits -= code_len;
939                if symbol > 29 {
940                    state.begin(InvalidDist);
941                    break 'o TINFLStatus::Failed;
942                }
943
944                l.num_extra = u32::from(DIST_EXTRA[symbol as usize]);
945                l.dist = u32::from(DIST_BASE[symbol as usize]);
946            } else {
947                state.begin(InvalidCodeLen);
948                break 'o TINFLStatus::Failed;
949            }
950
951            if l.num_extra != 0 {
952                fill_bit_buffer(&mut l, &mut in_iter);
953                let extra_bits = l.bit_buf & ((1 << l.num_extra) - 1);
954                l.bit_buf >>= l.num_extra;
955                l.num_bits -= l.num_extra;
956                l.dist += extra_bits as u32;
957            }
958
959            let position = out_buf.position();
960            if l.dist as usize > out_buf.position()
961                && (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0)
962            {
963                // We encountered a distance that refers a position before
964                // the start of the decoded data, so we can't continue.
965                state.begin(DistanceOutOfBounds);
966                break TINFLStatus::Failed;
967            }
968
969            apply_match(
970                out_buf.get_mut(),
971                position,
972                l.dist as usize,
973                l.counter as usize,
974                out_buf_size_mask,
975            );
976
977            out_buf.set_position(position + l.counter as usize);
978        }
979    };
980
981    *local_vars = l;
982    (status, state)
983}
984
985/// Main decompression function. Keeps decompressing data from `in_buf` until the `in_buf` is
986/// empty, `out_cur` is full, the end of the deflate stream is hit, or there is an error in the
987/// deflate stream.
988///
989/// # Arguments
990///
991/// `in_buf` is a reference to the compressed data that is to be decompressed. The decompressor will
992/// start at the first byte of this buffer.
993///
994/// `out_cur` is a mutable cursor into the buffer that will store the decompressed data, and that
995/// stores previously decompressed data if any.
996/// * The position of the output cursor indicates where in the output buffer slice writing should
997/// start.
998/// * If TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF is not set, the output buffer is used in a
999/// wrapping manner, and it's size is required to be a power of 2.
1000/// * The decompression function normally needs access to 32KiB of the previously decompressed data
1001///(or to the beginning of the decompressed data if less than 32KiB has been decompressed.)
1002///     - If this data is not available, decompression may fail.
1003///     - Some deflate compressors allow specifying a window size which limits match distances to
1004/// less than this, or alternatively an RLE mode where matches will only refer to the previous byte
1005/// and thus allows a smaller output buffer. The window size can be specified in the zlib
1006/// header structure, however, the header data should not be relied on to be correct.
1007///
1008/// `flags`
1009/// Flags to indicate settings and status to the decompression function.
1010/// * The `TINFL_FLAG_HAS_MORE_INPUT` has to be specified if more compressed data is to be provided
1011/// in a subsequent call to this function.
1012/// * See the the [`inflate_flags`](inflate_flags/index.html) module for details on other flags.
1013///
1014/// # Returns
1015/// returns a tuple containing the status of the compressor, the number of input bytes read, and the
1016/// number of bytes output to `out_cur`.
1017/// Updates the position of `out_cur` to point to the next free spot in the output buffer.
1018///
1019/// This function shouldn't panic pending any bugs.
1020pub fn decompress(
1021    r: &mut DecompressorOxide,
1022    in_buf: &[u8],
1023    out_cur: &mut Cursor<&mut [u8]>,
1024    flags: u32,
1025) -> (TINFLStatus, usize, usize) {
1026    let res = decompress_inner(r, in_buf, out_cur, flags);
1027    let new_pos = out_cur.position() + res.2 as u64;
1028    out_cur.set_position(new_pos);
1029    res
1030}
1031
1032#[inline]
1033fn decompress_inner(
1034    r: &mut DecompressorOxide,
1035    in_buf: &[u8],
1036    out_cur: &mut Cursor<&mut [u8]>,
1037    flags: u32,
1038) -> (TINFLStatus, usize, usize) {
1039    let out_buf_start_pos = out_cur.position() as usize;
1040    let out_buf_size_mask = if flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0 {
1041        usize::max_value()
1042    } else {
1043        // In the case of zero len, any attempt to write would produce HasMoreOutput,
1044        // so to gracefully process the case of there really being no output,
1045        // set the mask to all zeros.
1046        out_cur.get_ref().len().saturating_sub(1)
1047    };
1048
1049    // Ensure the output buffer's size is a power of 2, unless the output buffer
1050    // is large enough to hold the entire output file (in which case it doesn't
1051    // matter).
1052    // Also make sure that the output buffer position is not past the end of the output buffer.
1053    if (out_buf_size_mask.wrapping_add(1) & out_buf_size_mask) != 0
1054        || out_cur.position() > out_cur.get_ref().len() as u64
1055    {
1056        return (TINFLStatus::BadParam, 0, 0);
1057    }
1058
1059    let mut in_iter = in_buf.iter();
1060
1061    let mut state = r.state;
1062
1063    let mut out_buf = OutputBuffer::from_slice_and_pos(out_cur.get_mut(), out_buf_start_pos);
1064
1065    // Make a local copy of the important variables here so we can work with them on the stack.
1066    let mut l = LocalVars {
1067        bit_buf: r.bit_buf,
1068        num_bits: r.num_bits,
1069        dist: r.dist,
1070        counter: r.counter,
1071        num_extra: r.num_extra,
1072    };
1073
1074    let mut status = 'state_machine: loop {
1075        match state {
1076            Start => generate_state!(state, 'state_machine, {
1077                l.bit_buf = 0;
1078                l.num_bits = 0;
1079                l.dist = 0;
1080                l.counter = 0;
1081                l.num_extra = 0;
1082                r.z_header0 = 0;
1083                r.z_header1 = 0;
1084                r.z_adler32 = 1;
1085                r.check_adler32 = 1;
1086                if flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0 {
1087                    Action::Jump(State::ReadZlibCmf)
1088                } else {
1089                    Action::Jump(State::ReadBlockHeader)
1090                }
1091            }),
1092
1093            ReadZlibCmf => generate_state!(state, 'state_machine, {
1094                read_byte(&mut in_iter, flags, |cmf| {
1095                    r.z_header0 = u32::from(cmf);
1096                    Action::Jump(State::ReadZlibFlg)
1097                })
1098            }),
1099
1100            ReadZlibFlg => generate_state!(state, 'state_machine, {
1101                read_byte(&mut in_iter, flags, |flg| {
1102                    r.z_header1 = u32::from(flg);
1103                    validate_zlib_header(r.z_header0, r.z_header1, flags, out_buf_size_mask)
1104                })
1105            }),
1106
1107            // Read the block header and jump to the relevant section depending on the block type.
1108            ReadBlockHeader => generate_state!(state, 'state_machine, {
1109                read_bits(&mut l, 3, &mut in_iter, flags, |l, bits| {
1110                    r.finish = (bits & 1) as u32;
1111                    r.block_type = (bits >> 1) as u32 & 3;
1112                    match r.block_type {
1113                        0 => Action::Jump(BlockTypeNoCompression),
1114                        1 => {
1115                            start_static_table(r);
1116                            init_tree(r, l)
1117                        },
1118                        2 => {
1119                            l.counter = 0;
1120                            Action::Jump(ReadTableSizes)
1121                        },
1122                        3 => Action::Jump(BlockTypeUnexpected),
1123                        _ => unreachable!()
1124                    }
1125                })
1126            }),
1127
1128            // Raw/Stored/uncompressed block.
1129            BlockTypeNoCompression => generate_state!(state, 'state_machine, {
1130                pad_to_bytes(&mut l, &mut in_iter, flags, |l| {
1131                    l.counter = 0;
1132                    Action::Jump(RawHeader)
1133                })
1134            }),
1135
1136            // Check that the raw block header is correct.
1137            RawHeader => generate_state!(state, 'state_machine, {
1138                if l.counter < 4 {
1139                    // Read block length and block length check.
1140                    if l.num_bits != 0 {
1141                        read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| {
1142                            r.raw_header[l.counter as usize] = bits as u8;
1143                            l.counter += 1;
1144                            Action::None
1145                        })
1146                    } else {
1147                        read_byte(&mut in_iter, flags, |byte| {
1148                            r.raw_header[l.counter as usize] = byte;
1149                            l.counter += 1;
1150                            Action::None
1151                        })
1152                    }
1153                } else {
1154                    // Check if the length value of a raw block is correct.
1155                    // The 2 first (2-byte) words in a raw header are the length and the
1156                    // ones complement of the length.
1157                    let length = u16::from(r.raw_header[0]) | (u16::from(r.raw_header[1]) << 8);
1158                    let check = u16::from(r.raw_header[2]) | (u16::from(r.raw_header[3]) << 8);
1159                    let valid = length == !check;
1160                    l.counter = length.into();
1161
1162                    if !valid {
1163                        Action::Jump(BadRawLength)
1164                    } else if l.counter == 0 {
1165                        // Empty raw block. Sometimes used for synchronization.
1166                        Action::Jump(BlockDone)
1167                    } else if l.num_bits != 0 {
1168                        // There is some data in the bit buffer, so we need to write that first.
1169                        Action::Jump(RawReadFirstByte)
1170                    } else {
1171                        // The bit buffer is empty, so memcpy the rest of the uncompressed data from
1172                        // the block.
1173                        Action::Jump(RawMemcpy1)
1174                    }
1175                }
1176            }),
1177
1178            // Read the byte from the bit buffer.
1179            RawReadFirstByte => generate_state!(state, 'state_machine, {
1180                read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| {
1181                    l.dist = bits as u32;
1182                    Action::Jump(RawStoreFirstByte)
1183                })
1184            }),
1185
1186            // Write the byte we just read to the output buffer.
1187            RawStoreFirstByte => generate_state!(state, 'state_machine, {
1188                if out_buf.bytes_left() == 0 {
1189                    Action::End(TINFLStatus::HasMoreOutput)
1190                } else {
1191                    out_buf.write_byte(l.dist as u8);
1192                    l.counter -= 1;
1193                    if l.counter == 0 || l.num_bits == 0 {
1194                        Action::Jump(RawMemcpy1)
1195                    } else {
1196                        // There is still some data left in the bit buffer that needs to be output.
1197                        // TODO: Changed this to jump to `RawReadfirstbyte` rather than
1198                        // `RawStoreFirstByte` as that seemed to be the correct path, but this
1199                        // needs testing.
1200                        Action::Jump(RawReadFirstByte)
1201                    }
1202                }
1203            }),
1204
1205            RawMemcpy1 => generate_state!(state, 'state_machine, {
1206                if l.counter == 0 {
1207                    Action::Jump(BlockDone)
1208                } else if out_buf.bytes_left() == 0 {
1209                    Action::End(TINFLStatus::HasMoreOutput)
1210                } else {
1211                    Action::Jump(RawMemcpy2)
1212                }
1213            }),
1214
1215            RawMemcpy2 => generate_state!(state, 'state_machine, {
1216                if in_iter.len() > 0 {
1217                    // Copy as many raw bytes as possible from the input to the output using memcpy.
1218                    // Raw block lengths are limited to 64 * 1024, so casting through usize and u32
1219                    // is not an issue.
1220                    let space_left = out_buf.bytes_left();
1221                    let bytes_to_copy = cmp::min(cmp::min(
1222                        space_left,
1223                        in_iter.len()),
1224                        l.counter as usize
1225                    );
1226
1227                    out_buf.write_slice(&in_iter.as_slice()[..bytes_to_copy]);
1228
1229                    (&mut in_iter).nth(bytes_to_copy - 1);
1230                    l.counter -= bytes_to_copy as u32;
1231                    Action::Jump(RawMemcpy1)
1232                } else {
1233                    end_of_input(flags)
1234                }
1235            }),
1236
1237            // Read how many huffman codes/symbols are used for each table.
1238            ReadTableSizes => generate_state!(state, 'state_machine, {
1239                if l.counter < 3 {
1240                    let num_bits = [5, 5, 4][l.counter as usize];
1241                    read_bits(&mut l, num_bits, &mut in_iter, flags, |l, bits| {
1242                        r.table_sizes[l.counter as usize] =
1243                            bits as u32 + u32::from(MIN_TABLE_SIZES[l.counter as usize]);
1244                        l.counter += 1;
1245                        Action::None
1246                    })
1247                } else {
1248                    memset(&mut r.tables[HUFFLEN_TABLE].code_size[..], 0);
1249                    l.counter = 0;
1250                    Action::Jump(ReadHufflenTableCodeSize)
1251                }
1252            }),
1253
1254            // Read the 3-bit lengths of the huffman codes describing the huffman code lengths used
1255            // to decode the lengths of the main tables.
1256            ReadHufflenTableCodeSize => generate_state!(state, 'state_machine, {
1257                if l.counter < r.table_sizes[HUFFLEN_TABLE] {
1258                    read_bits(&mut l, 3, &mut in_iter, flags, |l, bits| {
1259                        // These lengths are not stored in a normal ascending order, but rather one
1260                        // specified by the deflate specification intended to put the most used
1261                        // values at the front as trailing zero lengths do not have to be stored.
1262                        r.tables[HUFFLEN_TABLE]
1263                            .code_size[HUFFMAN_LENGTH_ORDER[l.counter as usize] as usize] =
1264                                bits as u8;
1265                        l.counter += 1;
1266                        Action::None
1267                    })
1268                } else {
1269                    r.table_sizes[HUFFLEN_TABLE] = 19;
1270                    init_tree(r, &mut l)
1271                }
1272            }),
1273
1274            ReadLitlenDistTablesCodeSize => generate_state!(state, 'state_machine, {
1275                if l.counter < r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE] {
1276                    decode_huffman_code(
1277                        r, &mut l, HUFFLEN_TABLE,
1278                        flags, &mut in_iter, |r, l, symbol| {
1279                            l.dist = symbol as u32;
1280                            if l.dist < 16 {
1281                                r.len_codes[l.counter as usize] = l.dist as u8;
1282                                l.counter += 1;
1283                                Action::None
1284                            } else if l.dist == 16 && l.counter == 0 {
1285                                Action::Jump(BadCodeSizeDistPrevLookup)
1286                            } else {
1287                                l.num_extra = [2, 3, 7][l.dist as usize - 16];
1288                                Action::Jump(ReadExtraBitsCodeSize)
1289                            }
1290                        }
1291                    )
1292                } else if l.counter != r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE] {
1293                    Action::Jump(BadCodeSizeSum)
1294                } else {
1295                    r.tables[LITLEN_TABLE].code_size[..r.table_sizes[LITLEN_TABLE] as usize]
1296                        .copy_from_slice(&r.len_codes[..r.table_sizes[LITLEN_TABLE] as usize]);
1297
1298                    let dist_table_start = r.table_sizes[LITLEN_TABLE] as usize;
1299                    let dist_table_end = (r.table_sizes[LITLEN_TABLE] +
1300                                          r.table_sizes[DIST_TABLE]) as usize;
1301                    r.tables[DIST_TABLE].code_size[..r.table_sizes[DIST_TABLE] as usize]
1302                        .copy_from_slice(&r.len_codes[dist_table_start..dist_table_end]);
1303
1304                    r.block_type -= 1;
1305                    init_tree(r, &mut l)
1306                }
1307            }),
1308
1309            ReadExtraBitsCodeSize => generate_state!(state, 'state_machine, {
1310                let num_extra = l.num_extra;
1311                read_bits(&mut l, num_extra, &mut in_iter, flags, |l, mut extra_bits| {
1312                    // Mask to avoid a bounds check.
1313                    extra_bits += [3, 3, 11][(l.dist as usize - 16) & 3];
1314                    let val = if l.dist == 16 {
1315                        r.len_codes[l.counter as usize - 1]
1316                    } else {
1317                        0
1318                    };
1319
1320                    memset(
1321                        &mut r.len_codes[
1322                            l.counter as usize..l.counter as usize + extra_bits as usize
1323                        ],
1324                        val,
1325                    );
1326                    l.counter += extra_bits as u32;
1327                    Action::Jump(ReadLitlenDistTablesCodeSize)
1328                })
1329            }),
1330
1331            DecodeLitlen => generate_state!(state, 'state_machine, {
1332                if in_iter.len() < 4 || out_buf.bytes_left() < 2 {
1333                    // See if we can decode a literal with the data we have left.
1334                    // Jumps to next state (WriteSymbol) if successful.
1335                    decode_huffman_code(
1336                        r,
1337                        &mut l,
1338                        LITLEN_TABLE,
1339                        flags,
1340                        &mut in_iter,
1341                        |_r, l, symbol| {
1342                            l.counter = symbol as u32;
1343                            Action::Jump(WriteSymbol)
1344                        },
1345                    )
1346                } else if
1347                // If there is enough space, use the fast inner decompression
1348                // function.
1349                    out_buf.bytes_left() >= 259 &&
1350                    in_iter.len() >= 14
1351                {
1352                    let (status, new_state) = decompress_fast(
1353                        r,
1354                        &mut in_iter,
1355                        &mut out_buf,
1356                        flags,
1357                        &mut l,
1358                        out_buf_size_mask,
1359                    );
1360
1361                    state = new_state;
1362                    if status == TINFLStatus::Done {
1363                        Action::Jump(new_state)
1364                    } else {
1365                        Action::End(status)
1366                    }
1367                } else {
1368                    fill_bit_buffer(&mut l, &mut in_iter);
1369
1370                    if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) {
1371
1372                    l.counter = symbol as u32;
1373                    l.bit_buf >>= code_len;
1374                    l.num_bits -= code_len;
1375
1376                    if (l.counter & 256) != 0 {
1377                        // The symbol is not a literal.
1378                        Action::Jump(HuffDecodeOuterLoop1)
1379                    } else {
1380                        // If we have a 32-bit buffer we need to read another two bytes now
1381                        // to have enough bits to keep going.
1382                        if cfg!(not(target_pointer_width = "64")) {
1383                            fill_bit_buffer(&mut l, &mut in_iter);
1384                        }
1385
1386                        if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) {
1387
1388                            l.bit_buf >>= code_len;
1389                            l.num_bits -= code_len;
1390                            // The previous symbol was a literal, so write it directly and check
1391                            // the next one.
1392                            out_buf.write_byte(l.counter as u8);
1393                            if (symbol & 256) != 0 {
1394                                l.counter = symbol as u32;
1395                                // The symbol is a length value.
1396                                Action::Jump(HuffDecodeOuterLoop1)
1397                            } else {
1398                                // The symbol is a literal, so write it directly and continue.
1399                                out_buf.write_byte(symbol as u8);
1400                                Action::None
1401                            }
1402                        } else {
1403                            Action::Jump(InvalidCodeLen)
1404                        }
1405                    }
1406                    } else {
1407                        Action::Jump(InvalidCodeLen)
1408                    }
1409                }
1410            }),
1411
1412            WriteSymbol => generate_state!(state, 'state_machine, {
1413                if l.counter >= 256 {
1414                    Action::Jump(HuffDecodeOuterLoop1)
1415                } else if out_buf.bytes_left() > 0 {
1416                    out_buf.write_byte(l.counter as u8);
1417                    Action::Jump(DecodeLitlen)
1418                } else {
1419                    Action::End(TINFLStatus::HasMoreOutput)
1420                }
1421            }),
1422
1423            HuffDecodeOuterLoop1 => generate_state!(state, 'state_machine, {
1424                // Mask the top bits since they may contain length info.
1425                l.counter &= 511;
1426
1427                if l.counter == 256 {
1428                    // We hit the end of block symbol.
1429                    Action::Jump(BlockDone)
1430                } else if l.counter > 285 {
1431                    // Invalid code.
1432                    // We already verified earlier that the code is > 256.
1433                    Action::Jump(InvalidLitlen)
1434                } else {
1435                    // # Optimization
1436                    // Mask the value to avoid bounds checks
1437                    // We could use get_unchecked later if can statically verify that
1438                    // this will never go out of bounds.
1439                    l.num_extra =
1440                        u32::from(LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]);
1441                    l.counter = u32::from(LENGTH_BASE[(l.counter - 257) as usize & BASE_EXTRA_MASK]);
1442                    // Length and distance codes have a number of extra bits depending on
1443                    // the base, which together with the base gives us the exact value.
1444                    if l.num_extra != 0 {
1445                        Action::Jump(ReadExtraBitsLitlen)
1446                    } else {
1447                        Action::Jump(DecodeDistance)
1448                    }
1449                }
1450            }),
1451
1452            ReadExtraBitsLitlen => generate_state!(state, 'state_machine, {
1453                let num_extra = l.num_extra;
1454                read_bits(&mut l, num_extra, &mut in_iter, flags, |l, extra_bits| {
1455                    l.counter += extra_bits as u32;
1456                    Action::Jump(DecodeDistance)
1457                })
1458            }),
1459
1460            DecodeDistance => generate_state!(state, 'state_machine, {
1461                // Try to read a huffman code from the input buffer and look up what
1462                // length code the decoded symbol refers to.
1463                decode_huffman_code(r, &mut l, DIST_TABLE, flags, &mut in_iter, |_r, l, symbol| {
1464                    if symbol > 29 {
1465                        // Invalid distance code.
1466                        return Action::Jump(InvalidDist)
1467                    }
1468                    // # Optimization
1469                    // Mask the value to avoid bounds checks
1470                    // We could use get_unchecked later if can statically verify that
1471                    // this will never go out of bounds.
1472                    l.num_extra = u32::from(DIST_EXTRA[symbol as usize & BASE_EXTRA_MASK]);
1473                    l.dist = u32::from(DIST_BASE[symbol as usize & BASE_EXTRA_MASK]);
1474                    if l.num_extra != 0 {
1475                        // ReadEXTRA_BITS_DISTACNE
1476                        Action::Jump(ReadExtraBitsDistance)
1477                    } else {
1478                        Action::Jump(HuffDecodeOuterLoop2)
1479                    }
1480                })
1481            }),
1482
1483            ReadExtraBitsDistance => generate_state!(state, 'state_machine, {
1484                let num_extra = l.num_extra;
1485                read_bits(&mut l, num_extra, &mut in_iter, flags, |l, extra_bits| {
1486                    l.dist += extra_bits as u32;
1487                    Action::Jump(HuffDecodeOuterLoop2)
1488                })
1489            }),
1490
1491            HuffDecodeOuterLoop2 => generate_state!(state, 'state_machine, {
1492                if l.dist as usize > out_buf.position() &&
1493                    (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0)
1494                {
1495                    // We encountered a distance that refers a position before
1496                    // the start of the decoded data, so we can't continue.
1497                    Action::Jump(DistanceOutOfBounds)
1498                } else {
1499                    let out_pos = out_buf.position();
1500                    let source_pos = out_buf.position()
1501                        .wrapping_sub(l.dist as usize) & out_buf_size_mask;
1502
1503                    let out_len = out_buf.get_ref().len() as usize;
1504                    let match_end_pos = out_buf.position() + l.counter as usize;
1505
1506                    if match_end_pos > out_len ||
1507                        // miniz doesn't do this check here. Not sure how it makes sure
1508                        // that this case doesn't happen.
1509                        (source_pos >= out_pos && (source_pos - out_pos) < l.counter as usize)
1510                    {
1511                        // Not enough space for all of the data in the output buffer,
1512                        // so copy what we have space for.
1513                        if l.counter == 0 {
1514                            Action::Jump(DecodeLitlen)
1515                        } else {
1516                            Action::Jump(WriteLenBytesToEnd)
1517                        }
1518                    } else {
1519                        apply_match(
1520                            out_buf.get_mut(),
1521                            out_pos,
1522                            l.dist as usize,
1523                            l.counter as usize,
1524                            out_buf_size_mask
1525                        );
1526                        out_buf.set_position(out_pos + l.counter as usize);
1527                        Action::Jump(DecodeLitlen)
1528                    }
1529                }
1530            }),
1531
1532            WriteLenBytesToEnd => generate_state!(state, 'state_machine, {
1533                if out_buf.bytes_left() > 0 {
1534                    let out_pos = out_buf.position();
1535                    let source_pos = out_buf.position()
1536                        .wrapping_sub(l.dist as usize) & out_buf_size_mask;
1537
1538
1539                    let len = cmp::min(out_buf.bytes_left(), l.counter as usize);
1540
1541                    transfer(out_buf.get_mut(), source_pos, out_pos, len, out_buf_size_mask);
1542
1543                    out_buf.set_position(out_pos + len);
1544                    l.counter -= len as u32;
1545                    if l.counter == 0 {
1546                        Action::Jump(DecodeLitlen)
1547                    } else {
1548                        Action::None
1549                    }
1550                } else {
1551                    Action::End(TINFLStatus::HasMoreOutput)
1552                }
1553            }),
1554
1555            BlockDone => generate_state!(state, 'state_machine, {
1556                // End once we've read the last block.
1557                if r.finish != 0 {
1558                    pad_to_bytes(&mut l, &mut in_iter, flags, |_| Action::None);
1559
1560                    let in_consumed = in_buf.len() - in_iter.len();
1561                    let undo = undo_bytes(&mut l, in_consumed as u32) as usize;
1562                    in_iter = in_buf[in_consumed - undo..].iter();
1563
1564                    l.bit_buf &= ((1 as BitBuffer) << l.num_bits) - 1;
1565                    debug_assert_eq!(l.num_bits, 0);
1566
1567                    if flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0 {
1568                        l.counter = 0;
1569                        Action::Jump(ReadAdler32)
1570                    } else {
1571                        Action::Jump(DoneForever)
1572                    }
1573                } else {
1574                    Action::Jump(ReadBlockHeader)
1575                }
1576            }),
1577
1578            ReadAdler32 => generate_state!(state, 'state_machine, {
1579                if l.counter < 4 {
1580                    if l.num_bits != 0 {
1581                        read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| {
1582                            r.z_adler32 <<= 8;
1583                            r.z_adler32 |= bits as u32;
1584                            l.counter += 1;
1585                            Action::None
1586                        })
1587                    } else {
1588                        read_byte(&mut in_iter, flags, |byte| {
1589                            r.z_adler32 <<= 8;
1590                            r.z_adler32 |= u32::from(byte);
1591                            l.counter += 1;
1592                            Action::None
1593                        })
1594                    }
1595                } else {
1596                    Action::Jump(DoneForever)
1597                }
1598            }),
1599
1600            // We are done.
1601            DoneForever => break TINFLStatus::Done,
1602
1603            // Anything else indicates failure.
1604            // BadZlibHeader | BadRawLength | BlockTypeUnexpected | DistanceOutOfBounds |
1605            // BadTotalSymbols | BadCodeSizeDistPrevLookup | BadCodeSizeSum | InvalidLitlen |
1606            // InvalidDist | InvalidCodeLen
1607            _ => break TINFLStatus::Failed,
1608        };
1609    };
1610
1611    let in_undo = if status != TINFLStatus::NeedsMoreInput
1612        && status != TINFLStatus::FailedCannotMakeProgress
1613    {
1614        undo_bytes(&mut l, (in_buf.len() - in_iter.len()) as u32) as usize
1615    } else {
1616        0
1617    };
1618
1619    if status == TINFLStatus::NeedsMoreInput && out_buf.bytes_left() == 0 {
1620        status = TINFLStatus::HasMoreOutput
1621    }
1622
1623    r.state = state;
1624    r.bit_buf = l.bit_buf;
1625    r.num_bits = l.num_bits;
1626    r.dist = l.dist;
1627    r.counter = l.counter;
1628    r.num_extra = l.num_extra;
1629
1630    r.bit_buf &= ((1 as BitBuffer) << r.num_bits) - 1;
1631
1632    // If this is a zlib stream, and update the adler32 checksum with the decompressed bytes if
1633    // requested.
1634    let need_adler = flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32) != 0;
1635    if need_adler && status as i32 >= 0 {
1636        let out_buf_pos = out_buf.position();
1637        r.check_adler32 = update_adler32(
1638            r.check_adler32,
1639            &out_buf.get_ref()[out_buf_start_pos..out_buf_pos],
1640        );
1641
1642        // disabled so that random input from fuzzer would not be rejected early,
1643        // before it has a chance to reach interesting parts of code
1644        if !cfg!(fuzzing) {
1645            // Once we are done, check if the checksum matches with the one provided in the zlib header.
1646            if status == TINFLStatus::Done
1647                && flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0
1648                && r.check_adler32 != r.z_adler32
1649            {
1650                status = TINFLStatus::Adler32Mismatch;
1651            }
1652        }
1653    }
1654
1655    (
1656        status,
1657        in_buf.len() - in_iter.len() - in_undo,
1658        out_buf.position() - out_buf_start_pos,
1659    )
1660}
1661
1662#[cfg(test)]
1663mod test {
1664    use super::*;
1665
1666    //TODO: Fix these.
1667
1668    fn tinfl_decompress_oxide<'i>(
1669        r: &mut DecompressorOxide,
1670        input_buffer: &'i [u8],
1671        output_buffer: &mut [u8],
1672        flags: u32,
1673    ) -> (TINFLStatus, &'i [u8], usize) {
1674        let (status, in_pos, out_pos) =
1675            decompress(r, input_buffer, &mut Cursor::new(output_buffer), flags);
1676        (status, &input_buffer[in_pos..], out_pos)
1677    }
1678
1679    #[test]
1680    fn decompress_zlib() {
1681        let encoded = [
1682            120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19,
1683        ];
1684        let flags = TINFL_FLAG_COMPUTE_ADLER32 | TINFL_FLAG_PARSE_ZLIB_HEADER;
1685
1686        let mut b = DecompressorOxide::new();
1687        const LEN: usize = 32;
1688        let mut b_buf = vec![0; LEN];
1689
1690        // This should fail with the out buffer being to small.
1691        let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], b_buf.as_mut_slice(), flags);
1692
1693        assert_eq!(b_status.0, TINFLStatus::Failed);
1694
1695        let flags = flags | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
1696
1697        b = DecompressorOxide::new();
1698
1699        // With TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF set this should no longer fail.
1700        let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], b_buf.as_mut_slice(), flags);
1701
1702        assert_eq!(b_buf[..b_status.2], b"Hello, zlib!"[..]);
1703        assert_eq!(b_status.0, TINFLStatus::Done);
1704    }
1705
1706    #[test]
1707    fn raw_block() {
1708        const LEN: usize = 64;
1709
1710        let text = b"Hello, zlib!";
1711        let encoded = {
1712            let len = text.len();
1713            let notlen = !len;
1714            let mut encoded = vec![
1715                1,
1716                len as u8,
1717                (len >> 8) as u8,
1718                notlen as u8,
1719                (notlen >> 8) as u8,
1720            ];
1721            encoded.extend_from_slice(&text[..]);
1722            encoded
1723        };
1724
1725        //let flags = TINFL_FLAG_COMPUTE_ADLER32 | TINFL_FLAG_PARSE_ZLIB_HEADER |
1726        let flags = TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
1727
1728        let mut b = DecompressorOxide::new();
1729
1730        let mut b_buf = vec![0; LEN];
1731
1732        let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], b_buf.as_mut_slice(), flags);
1733        assert_eq!(b_buf[..b_status.2], text[..]);
1734        assert_eq!(b_status.0, TINFLStatus::Done);
1735    }
1736
1737    fn masked_lookup(table: &HuffmanTable, bit_buf: BitBuffer) -> (i32, u32) {
1738        let ret = table.lookup(bit_buf).unwrap();
1739        (ret.0 & 511, ret.1)
1740    }
1741
1742    #[test]
1743    fn fixed_table_lookup() {
1744        let mut d = DecompressorOxide::new();
1745        d.block_type = 1;
1746        start_static_table(&mut d);
1747        let mut l = LocalVars {
1748            bit_buf: d.bit_buf,
1749            num_bits: d.num_bits,
1750            dist: d.dist,
1751            counter: d.counter,
1752            num_extra: d.num_extra,
1753        };
1754        init_tree(&mut d, &mut l);
1755        let llt = &d.tables[LITLEN_TABLE];
1756        let dt = &d.tables[DIST_TABLE];
1757        assert_eq!(masked_lookup(llt, 0b00001100), (0, 8));
1758        assert_eq!(masked_lookup(llt, 0b00011110), (72, 8));
1759        assert_eq!(masked_lookup(llt, 0b01011110), (74, 8));
1760        assert_eq!(masked_lookup(llt, 0b11111101), (143, 8));
1761        assert_eq!(masked_lookup(llt, 0b000010011), (144, 9));
1762        assert_eq!(masked_lookup(llt, 0b111111111), (255, 9));
1763        assert_eq!(masked_lookup(llt, 0b00000000), (256, 7));
1764        assert_eq!(masked_lookup(llt, 0b1110100), (279, 7));
1765        assert_eq!(masked_lookup(llt, 0b00000011), (280, 8));
1766        assert_eq!(masked_lookup(llt, 0b11100011), (287, 8));
1767
1768        assert_eq!(masked_lookup(dt, 0), (0, 5));
1769        assert_eq!(masked_lookup(dt, 20), (5, 5));
1770    }
1771
1772    fn check_result(input: &[u8], expected_status: TINFLStatus, expected_state: State, zlib: bool) {
1773        let mut r = DecompressorOxide::default();
1774        let mut output_buf = vec![0; 1024 * 32];
1775        let mut out_cursor = Cursor::new(output_buf.as_mut_slice());
1776        let flags = if zlib {
1777            inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER
1778        } else {
1779            0
1780        } | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
1781            | TINFL_FLAG_HAS_MORE_INPUT;
1782        let (d_status, _in_bytes, _out_bytes) = decompress(&mut r, input, &mut out_cursor, flags);
1783        assert_eq!(expected_status, d_status);
1784        assert_eq!(expected_state, r.state);
1785    }
1786
1787    #[test]
1788    fn bogus_input() {
1789        use self::check_result as cr;
1790        const F: TINFLStatus = TINFLStatus::Failed;
1791        const OK: TINFLStatus = TINFLStatus::Done;
1792        // Bad CM.
1793        cr(&[0x77, 0x85], F, State::BadZlibHeader, true);
1794        // Bad window size (but check is correct).
1795        cr(&[0x88, 0x98], F, State::BadZlibHeader, true);
1796        // Bad check bits.
1797        cr(&[0x78, 0x98], F, State::BadZlibHeader, true);
1798
1799        // Too many code lengths. (From inflate library issues)
1800        cr(
1801            b"M\xff\xffM*\xad\xad\xad\xad\xad\xad\xad\xcd\xcd\xcdM",
1802            F,
1803            State::BadTotalSymbols,
1804            false,
1805        );
1806        // Bad CLEN (also from inflate library issues)
1807        cr(
1808            b"\xdd\xff\xff*M\x94ffffffffff",
1809            F,
1810            State::BadTotalSymbols,
1811            false,
1812        );
1813
1814        // Port of inflate coverage tests from zlib-ng
1815        // https://github.com/Dead2/zlib-ng/blob/develop/test/infcover.c
1816        let c = |a, b, c| cr(a, b, c, false);
1817
1818        // Invalid uncompressed/raw block length.
1819        c(&[0, 0, 0, 0, 0], F, State::BadRawLength);
1820        // Ok empty uncompressed block.
1821        c(&[3, 0], OK, State::DoneForever);
1822        // Invalid block type.
1823        c(&[6], F, State::BlockTypeUnexpected);
1824        // Ok uncompressed block.
1825        c(&[1, 1, 0, 0xfe, 0xff, 0], OK, State::DoneForever);
1826        // Too many litlens, we handle this later than zlib, so this test won't
1827        // give the same result.
1828        //        c(&[0xfc, 0, 0], F, State::BadTotalSymbols);
1829        // Invalid set of code lengths - TODO Check if this is the correct error for this.
1830        c(&[4, 0, 0xfe, 0xff], F, State::BadTotalSymbols);
1831        // Invalid repeat in list of code lengths.
1832        // (Try to repeat a non-existant code.)
1833        c(&[4, 0, 0x24, 0x49, 0], F, State::BadCodeSizeDistPrevLookup);
1834        // Missing end of block code (should we have a separate error for this?) - fails on futher input
1835        //    c(&[4, 0, 0x24, 0xe9, 0xff, 0x6d], F, State::BadTotalSymbols);
1836        // Invalid set of literals/lengths
1837        c(
1838            &[
1839                4, 0x80, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x71, 0xff, 0xff, 0x93, 0x11, 0,
1840            ],
1841            F,
1842            State::BadTotalSymbols,
1843        );
1844        // Invalid set of distances _ needsmoreinput
1845        // c(&[4, 0x80, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x0f, 0xb4, 0xff, 0xff, 0xc3, 0x84], F, State::BadTotalSymbols);
1846        // Invalid distance code
1847        c(&[2, 0x7e, 0xff, 0xff], F, State::InvalidDist);
1848
1849        // Distance refers to position before the start
1850        c(
1851            &[0x0c, 0xc0, 0x81, 0, 0, 0, 0, 0, 0x90, 0xff, 0x6b, 0x4, 0],
1852            F,
1853            State::DistanceOutOfBounds,
1854        );
1855
1856        // Trailer
1857        // Bad gzip trailer checksum GZip header not handled by miniz_oxide
1858        //cr(&[0x1f, 0x8b, 0x08 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x03, 0, 0, 0, 0, 0x01], F, State::BadCRC, false)
1859        // Bad gzip trailer length
1860        //cr(&[0x1f, 0x8b, 0x08 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x03, 0, 0, 0, 0, 0, 0, 0, 0, 0x01], F, State::BadCRC, false)
1861    }
1862
1863    #[test]
1864    fn empty_output_buffer_non_wrapping() {
1865        let encoded = [
1866            120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19,
1867        ];
1868        let flags = TINFL_FLAG_COMPUTE_ADLER32
1869            | TINFL_FLAG_PARSE_ZLIB_HEADER
1870            | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
1871        let mut r = DecompressorOxide::new();
1872        let mut output_buf = vec![];
1873        let mut out_cursor = Cursor::new(output_buf.as_mut_slice());
1874        // Check that we handle an empty buffer properly and not panicking.
1875        // https://github.com/Frommi/miniz_oxide/issues/23
1876        let res = decompress(&mut r, &encoded, &mut out_cursor, flags);
1877        assert_eq!(res, (TINFLStatus::HasMoreOutput, 4, 0));
1878    }
1879
1880    #[test]
1881    fn empty_output_buffer_wrapping() {
1882        let encoded = [
1883            0x73, 0x49, 0x4d, 0xcb, 0x49, 0x2c, 0x49, 0x55, 0x00, 0x11, 0x00,
1884        ];
1885        let flags = TINFL_FLAG_COMPUTE_ADLER32;
1886        let mut r = DecompressorOxide::new();
1887        let mut output_buf = vec![];
1888        let mut out_cursor = Cursor::new(output_buf.as_mut_slice());
1889        // Check that we handle an empty buffer properly and not panicking.
1890        // https://github.com/Frommi/miniz_oxide/issues/23
1891        let res = decompress(&mut r, &encoded, &mut out_cursor, flags);
1892        assert_eq!(res, (TINFLStatus::HasMoreOutput, 2, 0));
1893    }
1894}