1 //! Streaming decompression functionality.
2 
3 use super::*;
4 use crate::shared::{update_adler32, HUFFMAN_LENGTH_ORDER};
5 
6 use ::core::convert::TryInto;
7 use ::core::{cmp, slice};
8 
9 use self::output_buffer::OutputBuffer;
10 
11 pub 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.
14 struct 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 
28 impl HuffmanTable {
new() -> HuffmanTable29     const 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]
fast_lookup(&self, bit_buf: BitBuffer) -> i1642     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]
tree_lookup(&self, fast_symbol: i32, bit_buf: BitBuffer, mut code_len: u32) -> (i32, u32)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.
lookup(&self, bit_buf: BitBuffer) -> Option<(i32, u32)>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.
89 const MAX_HUFF_TABLES: usize = 3;
90 /// The length of the first (literal/length) huffman table.
91 const MAX_HUFF_SYMBOLS_0: usize = 288;
92 /// The length of the second (distance) huffman table.
93 const MAX_HUFF_SYMBOLS_1: usize = 32;
94 /// The length of the last (huffman code length) huffman table.
95 const _MAX_HUFF_SYMBOLS_2: usize = 19;
96 /// The maximum length of a code that can be looked up in the fast lookup table.
97 const FAST_LOOKUP_BITS: u8 = 10;
98 /// The size of the fast lookup table.
99 const FAST_LOOKUP_SIZE: u32 = 1 << FAST_LOOKUP_BITS;
100 const MAX_HUFF_TREE_SIZE: usize = MAX_HUFF_SYMBOLS_0 * 2;
101 const LITLEN_TABLE: usize = 0;
102 const DIST_TABLE: usize = 1;
103 const HUFFLEN_TABLE: usize = 2;
104 
105 pub 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 
116 use self::inflate_flags::*;
117 
118 const MIN_TABLE_SIZES: [u16; 3] = [257, 1, 4];
119 
120 #[cfg(target_pointer_width = "64")]
121 type BitBuffer = u64;
122 
123 #[cfg(not(target_pointer_width = "64"))]
124 type BitBuffer = u32;
125 
126 /// Main decompression struct.
127 ///
128 pub 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 
163 impl DecompressorOxide {
164     /// Create a new tinfl_decompressor with all fields set to 0.
new() -> DecompressorOxide165     pub fn new() -> DecompressorOxide {
166         DecompressorOxide::default()
167     }
168 
169     /// Set the current state to `Start`.
170     #[inline]
init(&mut self)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]
adler32(&self) -> Option<u32>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 
187 impl Default for DecompressorOxide {
188     /// Create a new tinfl_decompressor with all fields set to 0.
189     #[inline(always)]
default() -> Self190     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)]
218 enum 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 
259 impl State {
is_failure(self) -> bool260     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]
begin(&mut self, new_state: State)276     fn begin(&mut self, new_state: State) {
277         *self = new_state;
278     }
279 }
280 
281 use 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]
294 const 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]
301 const 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]
308 const 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]
316 const 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.
322 const BASE_EXTRA_MASK: usize = 32 - 1;
323 
324 /// Sets the value of all the elements of the slice to `val`.
325 #[inline]
memset<T: Copy>(slice: &mut [T], val: T)326 fn 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]
read_u16_le(iter: &mut slice::Iter<u8>) -> u16337 fn 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")]
read_u32_le(iter: &mut slice::Iter<u8>) -> u32352 fn 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")]
fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>)368 fn 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"))]
fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>)380 fn 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]
validate_zlib_header(cmf: u32, flg: u32, flags: u32, mask: usize) -> Action393 fn 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 
419 enum 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.
decode_huffman_code<F>( r: &mut DecompressorOxide, l: &mut LocalVars, table: usize, flags: u32, in_iter: &mut slice::Iter<u8>, f: F, ) -> Action where F: FnOnce(&mut DecompressorOxide, &mut LocalVars, i32) -> Action,431 fn 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
439 where
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]
read_byte<F>(in_iter: &mut slice::Iter<u8>, flags: u32, f: F) -> Action where F: FnOnce(u8) -> Action,544 fn read_byte<F>(in_iter: &mut slice::Iter<u8>, flags: u32, f: F) -> Action
545 where
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)]
read_bits<F>( l: &mut LocalVars, amount: u32, in_iter: &mut slice::Iter<u8>, flags: u32, f: F, ) -> Action where F: FnOnce(&mut LocalVars, BitBuffer) -> Action,560 fn 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
567 where
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]
pad_to_bytes<F>(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>, flags: u32, f: F) -> Action where F: FnOnce(&mut LocalVars) -> Action,592 fn pad_to_bytes<F>(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>, flags: u32, f: F) -> Action
593 where
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]
end_of_input(flags: u32) -> Action601 fn 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]
undo_bytes(l: &mut LocalVars, max: u32) -> u32610 fn 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 
start_static_table(r: &mut DecompressorOxide)616 fn 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 
init_tree(r: &mut DecompressorOxide, l: &mut LocalVars) -> Action626 fn 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.)
721 macro_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)]
737 struct 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]
transfer( out_slice: &mut [u8], mut source_pos: usize, mut out_pos: usize, match_len: usize, out_buf_size_mask: usize, )746 fn 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]
apply_match( out_slice: &mut [u8], out_pos: usize, dist: usize, match_len: usize, out_buf_size_mask: usize, )780 fn 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.
decompress_fast( r: &mut DecompressorOxide, mut in_iter: &mut slice::Iter<u8>, out_buf: &mut OutputBuffer, flags: u32, local_vars: &mut LocalVars, out_buf_size_mask: usize, ) -> (TINFLStatus, State)830 fn 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.
decompress( r: &mut DecompressorOxide, in_buf: &[u8], out: &mut [u8], out_pos: usize, flags: u32, ) -> (TINFLStatus, usize, usize)1020 pub fn decompress(
1021     r: &mut DecompressorOxide,
1022     in_buf: &[u8],
1023     out: &mut [u8],
1024     out_pos: usize,
1025     flags: u32,
1026 ) -> (TINFLStatus, usize, usize) {
1027     let out_buf_size_mask = if flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0 {
1028         usize::max_value()
1029     } else {
1030         // In the case of zero len, any attempt to write would produce HasMoreOutput,
1031         // so to gracefully process the case of there really being no output,
1032         // set the mask to all zeros.
1033         out.len().saturating_sub(1)
1034     };
1035 
1036     // Ensure the output buffer's size is a power of 2, unless the output buffer
1037     // is large enough to hold the entire output file (in which case it doesn't
1038     // matter).
1039     // Also make sure that the output buffer position is not past the end of the output buffer.
1040     if (out_buf_size_mask.wrapping_add(1) & out_buf_size_mask) != 0 || out_pos > out.len() {
1041         return (TINFLStatus::BadParam, 0, 0);
1042     }
1043 
1044     let mut in_iter = in_buf.iter();
1045 
1046     let mut state = r.state;
1047 
1048     let mut out_buf = OutputBuffer::from_slice_and_pos(out, out_pos);
1049 
1050     // Make a local copy of the important variables here so we can work with them on the stack.
1051     let mut l = LocalVars {
1052         bit_buf: r.bit_buf,
1053         num_bits: r.num_bits,
1054         dist: r.dist,
1055         counter: r.counter,
1056         num_extra: r.num_extra,
1057     };
1058 
1059     let mut status = 'state_machine: loop {
1060         match state {
1061             Start => generate_state!(state, 'state_machine, {
1062                 l.bit_buf = 0;
1063                 l.num_bits = 0;
1064                 l.dist = 0;
1065                 l.counter = 0;
1066                 l.num_extra = 0;
1067                 r.z_header0 = 0;
1068                 r.z_header1 = 0;
1069                 r.z_adler32 = 1;
1070                 r.check_adler32 = 1;
1071                 if flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0 {
1072                     Action::Jump(State::ReadZlibCmf)
1073                 } else {
1074                     Action::Jump(State::ReadBlockHeader)
1075                 }
1076             }),
1077 
1078             ReadZlibCmf => generate_state!(state, 'state_machine, {
1079                 read_byte(&mut in_iter, flags, |cmf| {
1080                     r.z_header0 = u32::from(cmf);
1081                     Action::Jump(State::ReadZlibFlg)
1082                 })
1083             }),
1084 
1085             ReadZlibFlg => generate_state!(state, 'state_machine, {
1086                 read_byte(&mut in_iter, flags, |flg| {
1087                     r.z_header1 = u32::from(flg);
1088                     validate_zlib_header(r.z_header0, r.z_header1, flags, out_buf_size_mask)
1089                 })
1090             }),
1091 
1092             // Read the block header and jump to the relevant section depending on the block type.
1093             ReadBlockHeader => generate_state!(state, 'state_machine, {
1094                 read_bits(&mut l, 3, &mut in_iter, flags, |l, bits| {
1095                     r.finish = (bits & 1) as u32;
1096                     r.block_type = (bits >> 1) as u32 & 3;
1097                     match r.block_type {
1098                         0 => Action::Jump(BlockTypeNoCompression),
1099                         1 => {
1100                             start_static_table(r);
1101                             init_tree(r, l)
1102                         },
1103                         2 => {
1104                             l.counter = 0;
1105                             Action::Jump(ReadTableSizes)
1106                         },
1107                         3 => Action::Jump(BlockTypeUnexpected),
1108                         _ => unreachable!()
1109                     }
1110                 })
1111             }),
1112 
1113             // Raw/Stored/uncompressed block.
1114             BlockTypeNoCompression => generate_state!(state, 'state_machine, {
1115                 pad_to_bytes(&mut l, &mut in_iter, flags, |l| {
1116                     l.counter = 0;
1117                     Action::Jump(RawHeader)
1118                 })
1119             }),
1120 
1121             // Check that the raw block header is correct.
1122             RawHeader => generate_state!(state, 'state_machine, {
1123                 if l.counter < 4 {
1124                     // Read block length and block length check.
1125                     if l.num_bits != 0 {
1126                         read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| {
1127                             r.raw_header[l.counter as usize] = bits as u8;
1128                             l.counter += 1;
1129                             Action::None
1130                         })
1131                     } else {
1132                         read_byte(&mut in_iter, flags, |byte| {
1133                             r.raw_header[l.counter as usize] = byte;
1134                             l.counter += 1;
1135                             Action::None
1136                         })
1137                     }
1138                 } else {
1139                     // Check if the length value of a raw block is correct.
1140                     // The 2 first (2-byte) words in a raw header are the length and the
1141                     // ones complement of the length.
1142                     let length = u16::from(r.raw_header[0]) | (u16::from(r.raw_header[1]) << 8);
1143                     let check = u16::from(r.raw_header[2]) | (u16::from(r.raw_header[3]) << 8);
1144                     let valid = length == !check;
1145                     l.counter = length.into();
1146 
1147                     if !valid {
1148                         Action::Jump(BadRawLength)
1149                     } else if l.counter == 0 {
1150                         // Empty raw block. Sometimes used for synchronization.
1151                         Action::Jump(BlockDone)
1152                     } else if l.num_bits != 0 {
1153                         // There is some data in the bit buffer, so we need to write that first.
1154                         Action::Jump(RawReadFirstByte)
1155                     } else {
1156                         // The bit buffer is empty, so memcpy the rest of the uncompressed data from
1157                         // the block.
1158                         Action::Jump(RawMemcpy1)
1159                     }
1160                 }
1161             }),
1162 
1163             // Read the byte from the bit buffer.
1164             RawReadFirstByte => generate_state!(state, 'state_machine, {
1165                 read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| {
1166                     l.dist = bits as u32;
1167                     Action::Jump(RawStoreFirstByte)
1168                 })
1169             }),
1170 
1171             // Write the byte we just read to the output buffer.
1172             RawStoreFirstByte => generate_state!(state, 'state_machine, {
1173                 if out_buf.bytes_left() == 0 {
1174                     Action::End(TINFLStatus::HasMoreOutput)
1175                 } else {
1176                     out_buf.write_byte(l.dist as u8);
1177                     l.counter -= 1;
1178                     if l.counter == 0 || l.num_bits == 0 {
1179                         Action::Jump(RawMemcpy1)
1180                     } else {
1181                         // There is still some data left in the bit buffer that needs to be output.
1182                         // TODO: Changed this to jump to `RawReadfirstbyte` rather than
1183                         // `RawStoreFirstByte` as that seemed to be the correct path, but this
1184                         // needs testing.
1185                         Action::Jump(RawReadFirstByte)
1186                     }
1187                 }
1188             }),
1189 
1190             RawMemcpy1 => generate_state!(state, 'state_machine, {
1191                 if l.counter == 0 {
1192                     Action::Jump(BlockDone)
1193                 } else if out_buf.bytes_left() == 0 {
1194                     Action::End(TINFLStatus::HasMoreOutput)
1195                 } else {
1196                     Action::Jump(RawMemcpy2)
1197                 }
1198             }),
1199 
1200             RawMemcpy2 => generate_state!(state, 'state_machine, {
1201                 if in_iter.len() > 0 {
1202                     // Copy as many raw bytes as possible from the input to the output using memcpy.
1203                     // Raw block lengths are limited to 64 * 1024, so casting through usize and u32
1204                     // is not an issue.
1205                     let space_left = out_buf.bytes_left();
1206                     let bytes_to_copy = cmp::min(cmp::min(
1207                         space_left,
1208                         in_iter.len()),
1209                         l.counter as usize
1210                     );
1211 
1212                     out_buf.write_slice(&in_iter.as_slice()[..bytes_to_copy]);
1213 
1214                     (&mut in_iter).nth(bytes_to_copy - 1);
1215                     l.counter -= bytes_to_copy as u32;
1216                     Action::Jump(RawMemcpy1)
1217                 } else {
1218                     end_of_input(flags)
1219                 }
1220             }),
1221 
1222             // Read how many huffman codes/symbols are used for each table.
1223             ReadTableSizes => generate_state!(state, 'state_machine, {
1224                 if l.counter < 3 {
1225                     let num_bits = [5, 5, 4][l.counter as usize];
1226                     read_bits(&mut l, num_bits, &mut in_iter, flags, |l, bits| {
1227                         r.table_sizes[l.counter as usize] =
1228                             bits as u32 + u32::from(MIN_TABLE_SIZES[l.counter as usize]);
1229                         l.counter += 1;
1230                         Action::None
1231                     })
1232                 } else {
1233                     memset(&mut r.tables[HUFFLEN_TABLE].code_size[..], 0);
1234                     l.counter = 0;
1235                     Action::Jump(ReadHufflenTableCodeSize)
1236                 }
1237             }),
1238 
1239             // Read the 3-bit lengths of the huffman codes describing the huffman code lengths used
1240             // to decode the lengths of the main tables.
1241             ReadHufflenTableCodeSize => generate_state!(state, 'state_machine, {
1242                 if l.counter < r.table_sizes[HUFFLEN_TABLE] {
1243                     read_bits(&mut l, 3, &mut in_iter, flags, |l, bits| {
1244                         // These lengths are not stored in a normal ascending order, but rather one
1245                         // specified by the deflate specification intended to put the most used
1246                         // values at the front as trailing zero lengths do not have to be stored.
1247                         r.tables[HUFFLEN_TABLE]
1248                             .code_size[HUFFMAN_LENGTH_ORDER[l.counter as usize] as usize] =
1249                                 bits as u8;
1250                         l.counter += 1;
1251                         Action::None
1252                     })
1253                 } else {
1254                     r.table_sizes[HUFFLEN_TABLE] = 19;
1255                     init_tree(r, &mut l)
1256                 }
1257             }),
1258 
1259             ReadLitlenDistTablesCodeSize => generate_state!(state, 'state_machine, {
1260                 if l.counter < r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE] {
1261                     decode_huffman_code(
1262                         r, &mut l, HUFFLEN_TABLE,
1263                         flags, &mut in_iter, |r, l, symbol| {
1264                             l.dist = symbol as u32;
1265                             if l.dist < 16 {
1266                                 r.len_codes[l.counter as usize] = l.dist as u8;
1267                                 l.counter += 1;
1268                                 Action::None
1269                             } else if l.dist == 16 && l.counter == 0 {
1270                                 Action::Jump(BadCodeSizeDistPrevLookup)
1271                             } else {
1272                                 l.num_extra = [2, 3, 7][l.dist as usize - 16];
1273                                 Action::Jump(ReadExtraBitsCodeSize)
1274                             }
1275                         }
1276                     )
1277                 } else if l.counter != r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE] {
1278                     Action::Jump(BadCodeSizeSum)
1279                 } else {
1280                     r.tables[LITLEN_TABLE].code_size[..r.table_sizes[LITLEN_TABLE] as usize]
1281                         .copy_from_slice(&r.len_codes[..r.table_sizes[LITLEN_TABLE] as usize]);
1282 
1283                     let dist_table_start = r.table_sizes[LITLEN_TABLE] as usize;
1284                     let dist_table_end = (r.table_sizes[LITLEN_TABLE] +
1285                                           r.table_sizes[DIST_TABLE]) as usize;
1286                     r.tables[DIST_TABLE].code_size[..r.table_sizes[DIST_TABLE] as usize]
1287                         .copy_from_slice(&r.len_codes[dist_table_start..dist_table_end]);
1288 
1289                     r.block_type -= 1;
1290                     init_tree(r, &mut l)
1291                 }
1292             }),
1293 
1294             ReadExtraBitsCodeSize => generate_state!(state, 'state_machine, {
1295                 let num_extra = l.num_extra;
1296                 read_bits(&mut l, num_extra, &mut in_iter, flags, |l, mut extra_bits| {
1297                     // Mask to avoid a bounds check.
1298                     extra_bits += [3, 3, 11][(l.dist as usize - 16) & 3];
1299                     let val = if l.dist == 16 {
1300                         r.len_codes[l.counter as usize - 1]
1301                     } else {
1302                         0
1303                     };
1304 
1305                     memset(
1306                         &mut r.len_codes[
1307                             l.counter as usize..l.counter as usize + extra_bits as usize
1308                         ],
1309                         val,
1310                     );
1311                     l.counter += extra_bits as u32;
1312                     Action::Jump(ReadLitlenDistTablesCodeSize)
1313                 })
1314             }),
1315 
1316             DecodeLitlen => generate_state!(state, 'state_machine, {
1317                 if in_iter.len() < 4 || out_buf.bytes_left() < 2 {
1318                     // See if we can decode a literal with the data we have left.
1319                     // Jumps to next state (WriteSymbol) if successful.
1320                     decode_huffman_code(
1321                         r,
1322                         &mut l,
1323                         LITLEN_TABLE,
1324                         flags,
1325                         &mut in_iter,
1326                         |_r, l, symbol| {
1327                             l.counter = symbol as u32;
1328                             Action::Jump(WriteSymbol)
1329                         },
1330                     )
1331                 } else if
1332                 // If there is enough space, use the fast inner decompression
1333                 // function.
1334                     out_buf.bytes_left() >= 259 &&
1335                     in_iter.len() >= 14
1336                 {
1337                     let (status, new_state) = decompress_fast(
1338                         r,
1339                         &mut in_iter,
1340                         &mut out_buf,
1341                         flags,
1342                         &mut l,
1343                         out_buf_size_mask,
1344                     );
1345 
1346                     state = new_state;
1347                     if status == TINFLStatus::Done {
1348                         Action::Jump(new_state)
1349                     } else {
1350                         Action::End(status)
1351                     }
1352                 } else {
1353                     fill_bit_buffer(&mut l, &mut in_iter);
1354 
1355                     if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) {
1356 
1357                     l.counter = symbol as u32;
1358                     l.bit_buf >>= code_len;
1359                     l.num_bits -= code_len;
1360 
1361                     if (l.counter & 256) != 0 {
1362                         // The symbol is not a literal.
1363                         Action::Jump(HuffDecodeOuterLoop1)
1364                     } else {
1365                         // If we have a 32-bit buffer we need to read another two bytes now
1366                         // to have enough bits to keep going.
1367                         if cfg!(not(target_pointer_width = "64")) {
1368                             fill_bit_buffer(&mut l, &mut in_iter);
1369                         }
1370 
1371                         if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) {
1372 
1373                             l.bit_buf >>= code_len;
1374                             l.num_bits -= code_len;
1375                             // The previous symbol was a literal, so write it directly and check
1376                             // the next one.
1377                             out_buf.write_byte(l.counter as u8);
1378                             if (symbol & 256) != 0 {
1379                                 l.counter = symbol as u32;
1380                                 // The symbol is a length value.
1381                                 Action::Jump(HuffDecodeOuterLoop1)
1382                             } else {
1383                                 // The symbol is a literal, so write it directly and continue.
1384                                 out_buf.write_byte(symbol as u8);
1385                                 Action::None
1386                             }
1387                         } else {
1388                             Action::Jump(InvalidCodeLen)
1389                         }
1390                     }
1391                     } else {
1392                         Action::Jump(InvalidCodeLen)
1393                     }
1394                 }
1395             }),
1396 
1397             WriteSymbol => generate_state!(state, 'state_machine, {
1398                 if l.counter >= 256 {
1399                     Action::Jump(HuffDecodeOuterLoop1)
1400                 } else if out_buf.bytes_left() > 0 {
1401                     out_buf.write_byte(l.counter as u8);
1402                     Action::Jump(DecodeLitlen)
1403                 } else {
1404                     Action::End(TINFLStatus::HasMoreOutput)
1405                 }
1406             }),
1407 
1408             HuffDecodeOuterLoop1 => generate_state!(state, 'state_machine, {
1409                 // Mask the top bits since they may contain length info.
1410                 l.counter &= 511;
1411 
1412                 if l.counter == 256 {
1413                     // We hit the end of block symbol.
1414                     Action::Jump(BlockDone)
1415                 } else if l.counter > 285 {
1416                     // Invalid code.
1417                     // We already verified earlier that the code is > 256.
1418                     Action::Jump(InvalidLitlen)
1419                 } else {
1420                     // # Optimization
1421                     // Mask the value to avoid bounds checks
1422                     // We could use get_unchecked later if can statically verify that
1423                     // this will never go out of bounds.
1424                     l.num_extra =
1425                         u32::from(LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]);
1426                     l.counter = u32::from(LENGTH_BASE[(l.counter - 257) as usize & BASE_EXTRA_MASK]);
1427                     // Length and distance codes have a number of extra bits depending on
1428                     // the base, which together with the base gives us the exact value.
1429                     if l.num_extra != 0 {
1430                         Action::Jump(ReadExtraBitsLitlen)
1431                     } else {
1432                         Action::Jump(DecodeDistance)
1433                     }
1434                 }
1435             }),
1436 
1437             ReadExtraBitsLitlen => generate_state!(state, 'state_machine, {
1438                 let num_extra = l.num_extra;
1439                 read_bits(&mut l, num_extra, &mut in_iter, flags, |l, extra_bits| {
1440                     l.counter += extra_bits as u32;
1441                     Action::Jump(DecodeDistance)
1442                 })
1443             }),
1444 
1445             DecodeDistance => generate_state!(state, 'state_machine, {
1446                 // Try to read a huffman code from the input buffer and look up what
1447                 // length code the decoded symbol refers to.
1448                 decode_huffman_code(r, &mut l, DIST_TABLE, flags, &mut in_iter, |_r, l, symbol| {
1449                     if symbol > 29 {
1450                         // Invalid distance code.
1451                         return Action::Jump(InvalidDist)
1452                     }
1453                     // # Optimization
1454                     // Mask the value to avoid bounds checks
1455                     // We could use get_unchecked later if can statically verify that
1456                     // this will never go out of bounds.
1457                     l.num_extra = u32::from(DIST_EXTRA[symbol as usize & BASE_EXTRA_MASK]);
1458                     l.dist = u32::from(DIST_BASE[symbol as usize & BASE_EXTRA_MASK]);
1459                     if l.num_extra != 0 {
1460                         // ReadEXTRA_BITS_DISTACNE
1461                         Action::Jump(ReadExtraBitsDistance)
1462                     } else {
1463                         Action::Jump(HuffDecodeOuterLoop2)
1464                     }
1465                 })
1466             }),
1467 
1468             ReadExtraBitsDistance => generate_state!(state, 'state_machine, {
1469                 let num_extra = l.num_extra;
1470                 read_bits(&mut l, num_extra, &mut in_iter, flags, |l, extra_bits| {
1471                     l.dist += extra_bits as u32;
1472                     Action::Jump(HuffDecodeOuterLoop2)
1473                 })
1474             }),
1475 
1476             HuffDecodeOuterLoop2 => generate_state!(state, 'state_machine, {
1477                 if l.dist as usize > out_buf.position() &&
1478                     (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0)
1479                 {
1480                     // We encountered a distance that refers a position before
1481                     // the start of the decoded data, so we can't continue.
1482                     Action::Jump(DistanceOutOfBounds)
1483                 } else {
1484                     let out_pos = out_buf.position();
1485                     let source_pos = out_buf.position()
1486                         .wrapping_sub(l.dist as usize) & out_buf_size_mask;
1487 
1488                     let out_len = out_buf.get_ref().len() as usize;
1489                     let match_end_pos = out_buf.position() + l.counter as usize;
1490 
1491                     if match_end_pos > out_len ||
1492                         // miniz doesn't do this check here. Not sure how it makes sure
1493                         // that this case doesn't happen.
1494                         (source_pos >= out_pos && (source_pos - out_pos) < l.counter as usize)
1495                     {
1496                         // Not enough space for all of the data in the output buffer,
1497                         // so copy what we have space for.
1498                         if l.counter == 0 {
1499                             Action::Jump(DecodeLitlen)
1500                         } else {
1501                             Action::Jump(WriteLenBytesToEnd)
1502                         }
1503                     } else {
1504                         apply_match(
1505                             out_buf.get_mut(),
1506                             out_pos,
1507                             l.dist as usize,
1508                             l.counter as usize,
1509                             out_buf_size_mask
1510                         );
1511                         out_buf.set_position(out_pos + l.counter as usize);
1512                         Action::Jump(DecodeLitlen)
1513                     }
1514                 }
1515             }),
1516 
1517             WriteLenBytesToEnd => generate_state!(state, 'state_machine, {
1518                 if out_buf.bytes_left() > 0 {
1519                     let out_pos = out_buf.position();
1520                     let source_pos = out_buf.position()
1521                         .wrapping_sub(l.dist as usize) & out_buf_size_mask;
1522 
1523 
1524                     let len = cmp::min(out_buf.bytes_left(), l.counter as usize);
1525 
1526                     transfer(out_buf.get_mut(), source_pos, out_pos, len, out_buf_size_mask);
1527 
1528                     out_buf.set_position(out_pos + len);
1529                     l.counter -= len as u32;
1530                     if l.counter == 0 {
1531                         Action::Jump(DecodeLitlen)
1532                     } else {
1533                         Action::None
1534                     }
1535                 } else {
1536                     Action::End(TINFLStatus::HasMoreOutput)
1537                 }
1538             }),
1539 
1540             BlockDone => generate_state!(state, 'state_machine, {
1541                 // End once we've read the last block.
1542                 if r.finish != 0 {
1543                     pad_to_bytes(&mut l, &mut in_iter, flags, |_| Action::None);
1544 
1545                     let in_consumed = in_buf.len() - in_iter.len();
1546                     let undo = undo_bytes(&mut l, in_consumed as u32) as usize;
1547                     in_iter = in_buf[in_consumed - undo..].iter();
1548 
1549                     l.bit_buf &= ((1 as BitBuffer) << l.num_bits) - 1;
1550                     debug_assert_eq!(l.num_bits, 0);
1551 
1552                     if flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0 {
1553                         l.counter = 0;
1554                         Action::Jump(ReadAdler32)
1555                     } else {
1556                         Action::Jump(DoneForever)
1557                     }
1558                 } else {
1559                     Action::Jump(ReadBlockHeader)
1560                 }
1561             }),
1562 
1563             ReadAdler32 => generate_state!(state, 'state_machine, {
1564                 if l.counter < 4 {
1565                     if l.num_bits != 0 {
1566                         read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| {
1567                             r.z_adler32 <<= 8;
1568                             r.z_adler32 |= bits as u32;
1569                             l.counter += 1;
1570                             Action::None
1571                         })
1572                     } else {
1573                         read_byte(&mut in_iter, flags, |byte| {
1574                             r.z_adler32 <<= 8;
1575                             r.z_adler32 |= u32::from(byte);
1576                             l.counter += 1;
1577                             Action::None
1578                         })
1579                     }
1580                 } else {
1581                     Action::Jump(DoneForever)
1582                 }
1583             }),
1584 
1585             // We are done.
1586             DoneForever => break TINFLStatus::Done,
1587 
1588             // Anything else indicates failure.
1589             // BadZlibHeader | BadRawLength | BlockTypeUnexpected | DistanceOutOfBounds |
1590             // BadTotalSymbols | BadCodeSizeDistPrevLookup | BadCodeSizeSum | InvalidLitlen |
1591             // InvalidDist | InvalidCodeLen
1592             _ => break TINFLStatus::Failed,
1593         };
1594     };
1595 
1596     let in_undo = if status != TINFLStatus::NeedsMoreInput
1597         && status != TINFLStatus::FailedCannotMakeProgress
1598     {
1599         undo_bytes(&mut l, (in_buf.len() - in_iter.len()) as u32) as usize
1600     } else {
1601         0
1602     };
1603 
1604     if status == TINFLStatus::NeedsMoreInput && out_buf.bytes_left() == 0 {
1605         status = TINFLStatus::HasMoreOutput
1606     }
1607 
1608     r.state = state;
1609     r.bit_buf = l.bit_buf;
1610     r.num_bits = l.num_bits;
1611     r.dist = l.dist;
1612     r.counter = l.counter;
1613     r.num_extra = l.num_extra;
1614 
1615     r.bit_buf &= ((1 as BitBuffer) << r.num_bits) - 1;
1616 
1617     // If this is a zlib stream, and update the adler32 checksum with the decompressed bytes if
1618     // requested.
1619     let need_adler = flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32) != 0;
1620     if need_adler && status as i32 >= 0 {
1621         let out_buf_pos = out_buf.position();
1622         r.check_adler32 = update_adler32(r.check_adler32, &out_buf.get_ref()[out_pos..out_buf_pos]);
1623 
1624         // disabled so that random input from fuzzer would not be rejected early,
1625         // before it has a chance to reach interesting parts of code
1626         if !cfg!(fuzzing) {
1627             // Once we are done, check if the checksum matches with the one provided in the zlib header.
1628             if status == TINFLStatus::Done
1629                 && flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0
1630                 && r.check_adler32 != r.z_adler32
1631             {
1632                 status = TINFLStatus::Adler32Mismatch;
1633             }
1634         }
1635     }
1636 
1637     (
1638         status,
1639         in_buf.len() - in_iter.len() - in_undo,
1640         out_buf.position() - out_pos,
1641     )
1642 }
1643 
1644 #[cfg(test)]
1645 mod test {
1646     use super::*;
1647 
1648     //TODO: Fix these.
1649 
tinfl_decompress_oxide<'i>( r: &mut DecompressorOxide, input_buffer: &'i [u8], output_buffer: &mut [u8], flags: u32, ) -> (TINFLStatus, &'i [u8], usize)1650     fn tinfl_decompress_oxide<'i>(
1651         r: &mut DecompressorOxide,
1652         input_buffer: &'i [u8],
1653         output_buffer: &mut [u8],
1654         flags: u32,
1655     ) -> (TINFLStatus, &'i [u8], usize) {
1656         let (status, in_pos, out_pos) = decompress(r, input_buffer, output_buffer, 0, flags);
1657         (status, &input_buffer[in_pos..], out_pos)
1658     }
1659 
1660     #[test]
decompress_zlib()1661     fn decompress_zlib() {
1662         let encoded = [
1663             120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19,
1664         ];
1665         let flags = TINFL_FLAG_COMPUTE_ADLER32 | TINFL_FLAG_PARSE_ZLIB_HEADER;
1666 
1667         let mut b = DecompressorOxide::new();
1668         const LEN: usize = 32;
1669         let mut b_buf = vec![0; LEN];
1670 
1671         // This should fail with the out buffer being to small.
1672         let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], b_buf.as_mut_slice(), flags);
1673 
1674         assert_eq!(b_status.0, TINFLStatus::Failed);
1675 
1676         let flags = flags | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
1677 
1678         b = DecompressorOxide::new();
1679 
1680         // With TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF set this should no longer fail.
1681         let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], b_buf.as_mut_slice(), flags);
1682 
1683         assert_eq!(b_buf[..b_status.2], b"Hello, zlib!"[..]);
1684         assert_eq!(b_status.0, TINFLStatus::Done);
1685     }
1686 
1687     #[test]
raw_block()1688     fn raw_block() {
1689         const LEN: usize = 64;
1690 
1691         let text = b"Hello, zlib!";
1692         let encoded = {
1693             let len = text.len();
1694             let notlen = !len;
1695             let mut encoded = vec![
1696                 1,
1697                 len as u8,
1698                 (len >> 8) as u8,
1699                 notlen as u8,
1700                 (notlen >> 8) as u8,
1701             ];
1702             encoded.extend_from_slice(&text[..]);
1703             encoded
1704         };
1705 
1706         //let flags = TINFL_FLAG_COMPUTE_ADLER32 | TINFL_FLAG_PARSE_ZLIB_HEADER |
1707         let flags = TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
1708 
1709         let mut b = DecompressorOxide::new();
1710 
1711         let mut b_buf = vec![0; LEN];
1712 
1713         let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], b_buf.as_mut_slice(), flags);
1714         assert_eq!(b_buf[..b_status.2], text[..]);
1715         assert_eq!(b_status.0, TINFLStatus::Done);
1716     }
1717 
masked_lookup(table: &HuffmanTable, bit_buf: BitBuffer) -> (i32, u32)1718     fn masked_lookup(table: &HuffmanTable, bit_buf: BitBuffer) -> (i32, u32) {
1719         let ret = table.lookup(bit_buf).unwrap();
1720         (ret.0 & 511, ret.1)
1721     }
1722 
1723     #[test]
fixed_table_lookup()1724     fn fixed_table_lookup() {
1725         let mut d = DecompressorOxide::new();
1726         d.block_type = 1;
1727         start_static_table(&mut d);
1728         let mut l = LocalVars {
1729             bit_buf: d.bit_buf,
1730             num_bits: d.num_bits,
1731             dist: d.dist,
1732             counter: d.counter,
1733             num_extra: d.num_extra,
1734         };
1735         init_tree(&mut d, &mut l);
1736         let llt = &d.tables[LITLEN_TABLE];
1737         let dt = &d.tables[DIST_TABLE];
1738         assert_eq!(masked_lookup(llt, 0b00001100), (0, 8));
1739         assert_eq!(masked_lookup(llt, 0b00011110), (72, 8));
1740         assert_eq!(masked_lookup(llt, 0b01011110), (74, 8));
1741         assert_eq!(masked_lookup(llt, 0b11111101), (143, 8));
1742         assert_eq!(masked_lookup(llt, 0b000010011), (144, 9));
1743         assert_eq!(masked_lookup(llt, 0b111111111), (255, 9));
1744         assert_eq!(masked_lookup(llt, 0b00000000), (256, 7));
1745         assert_eq!(masked_lookup(llt, 0b1110100), (279, 7));
1746         assert_eq!(masked_lookup(llt, 0b00000011), (280, 8));
1747         assert_eq!(masked_lookup(llt, 0b11100011), (287, 8));
1748 
1749         assert_eq!(masked_lookup(dt, 0), (0, 5));
1750         assert_eq!(masked_lookup(dt, 20), (5, 5));
1751     }
1752 
check_result(input: &[u8], expected_status: TINFLStatus, expected_state: State, zlib: bool)1753     fn check_result(input: &[u8], expected_status: TINFLStatus, expected_state: State, zlib: bool) {
1754         let mut r = DecompressorOxide::default();
1755         let mut output_buf = vec![0; 1024 * 32];
1756         let flags = if zlib {
1757             inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER
1758         } else {
1759             0
1760         } | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
1761             | TINFL_FLAG_HAS_MORE_INPUT;
1762         let (d_status, _in_bytes, _out_bytes) =
1763             decompress(&mut r, input, &mut output_buf, 0, flags);
1764         assert_eq!(expected_status, d_status);
1765         assert_eq!(expected_state, r.state);
1766     }
1767 
1768     #[test]
bogus_input()1769     fn bogus_input() {
1770         use self::check_result as cr;
1771         const F: TINFLStatus = TINFLStatus::Failed;
1772         const OK: TINFLStatus = TINFLStatus::Done;
1773         // Bad CM.
1774         cr(&[0x77, 0x85], F, State::BadZlibHeader, true);
1775         // Bad window size (but check is correct).
1776         cr(&[0x88, 0x98], F, State::BadZlibHeader, true);
1777         // Bad check bits.
1778         cr(&[0x78, 0x98], F, State::BadZlibHeader, true);
1779 
1780         // Too many code lengths. (From inflate library issues)
1781         cr(
1782             b"M\xff\xffM*\xad\xad\xad\xad\xad\xad\xad\xcd\xcd\xcdM",
1783             F,
1784             State::BadTotalSymbols,
1785             false,
1786         );
1787         // Bad CLEN (also from inflate library issues)
1788         cr(
1789             b"\xdd\xff\xff*M\x94ffffffffff",
1790             F,
1791             State::BadTotalSymbols,
1792             false,
1793         );
1794 
1795         // Port of inflate coverage tests from zlib-ng
1796         // https://github.com/Dead2/zlib-ng/blob/develop/test/infcover.c
1797         let c = |a, b, c| cr(a, b, c, false);
1798 
1799         // Invalid uncompressed/raw block length.
1800         c(&[0, 0, 0, 0, 0], F, State::BadRawLength);
1801         // Ok empty uncompressed block.
1802         c(&[3, 0], OK, State::DoneForever);
1803         // Invalid block type.
1804         c(&[6], F, State::BlockTypeUnexpected);
1805         // Ok uncompressed block.
1806         c(&[1, 1, 0, 0xfe, 0xff, 0], OK, State::DoneForever);
1807         // Too many litlens, we handle this later than zlib, so this test won't
1808         // give the same result.
1809         //        c(&[0xfc, 0, 0], F, State::BadTotalSymbols);
1810         // Invalid set of code lengths - TODO Check if this is the correct error for this.
1811         c(&[4, 0, 0xfe, 0xff], F, State::BadTotalSymbols);
1812         // Invalid repeat in list of code lengths.
1813         // (Try to repeat a non-existant code.)
1814         c(&[4, 0, 0x24, 0x49, 0], F, State::BadCodeSizeDistPrevLookup);
1815         // Missing end of block code (should we have a separate error for this?) - fails on futher input
1816         //    c(&[4, 0, 0x24, 0xe9, 0xff, 0x6d], F, State::BadTotalSymbols);
1817         // Invalid set of literals/lengths
1818         c(
1819             &[
1820                 4, 0x80, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x71, 0xff, 0xff, 0x93, 0x11, 0,
1821             ],
1822             F,
1823             State::BadTotalSymbols,
1824         );
1825         // Invalid set of distances _ needsmoreinput
1826         // c(&[4, 0x80, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x0f, 0xb4, 0xff, 0xff, 0xc3, 0x84], F, State::BadTotalSymbols);
1827         // Invalid distance code
1828         c(&[2, 0x7e, 0xff, 0xff], F, State::InvalidDist);
1829 
1830         // Distance refers to position before the start
1831         c(
1832             &[0x0c, 0xc0, 0x81, 0, 0, 0, 0, 0, 0x90, 0xff, 0x6b, 0x4, 0],
1833             F,
1834             State::DistanceOutOfBounds,
1835         );
1836 
1837         // Trailer
1838         // Bad gzip trailer checksum GZip header not handled by miniz_oxide
1839         //cr(&[0x1f, 0x8b, 0x08 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x03, 0, 0, 0, 0, 0x01], F, State::BadCRC, false)
1840         // Bad gzip trailer length
1841         //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)
1842     }
1843 
1844     #[test]
empty_output_buffer_non_wrapping()1845     fn empty_output_buffer_non_wrapping() {
1846         let encoded = [
1847             120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19,
1848         ];
1849         let flags = TINFL_FLAG_COMPUTE_ADLER32
1850             | TINFL_FLAG_PARSE_ZLIB_HEADER
1851             | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
1852         let mut r = DecompressorOxide::new();
1853         let mut output_buf = vec![];
1854         // Check that we handle an empty buffer properly and not panicking.
1855         // https://github.com/Frommi/miniz_oxide/issues/23
1856         let res = decompress(&mut r, &encoded, &mut output_buf, 0, flags);
1857         assert_eq!(res, (TINFLStatus::HasMoreOutput, 4, 0));
1858     }
1859 
1860     #[test]
empty_output_buffer_wrapping()1861     fn empty_output_buffer_wrapping() {
1862         let encoded = [
1863             0x73, 0x49, 0x4d, 0xcb, 0x49, 0x2c, 0x49, 0x55, 0x00, 0x11, 0x00,
1864         ];
1865         let flags = TINFL_FLAG_COMPUTE_ADLER32;
1866         let mut r = DecompressorOxide::new();
1867         let mut output_buf = vec![];
1868         // Check that we handle an empty buffer properly and not panicking.
1869         // https://github.com/Frommi/miniz_oxide/issues/23
1870         let res = decompress(&mut r, &encoded, &mut output_buf, 0, flags);
1871         assert_eq!(res, (TINFLStatus::HasMoreOutput, 2, 0));
1872     }
1873 }
1874