1 //! Streaming decompression functionality.
2 
3 use super::*;
4 use crate::shared::{update_adler32, HUFFMAN_LENGTH_ORDER};
5 
6 use std::convert::TryInto;
7 use std::{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     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_cur: &mut Cursor<&mut [u8]>, flags: u32, ) -> (TINFLStatus, usize, usize)1020 pub 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]
decompress_inner( r: &mut DecompressorOxide, in_buf: &[u8], out_cur: &mut Cursor<&mut [u8]>, flags: u32, ) -> (TINFLStatus, usize, usize)1033 fn 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)]
1663 mod test {
1664     use super::*;
1665 
1666     //TODO: Fix these.
1667 
tinfl_decompress_oxide<'i>( r: &mut DecompressorOxide, input_buffer: &'i [u8], output_buffer: &mut [u8], flags: u32, ) -> (TINFLStatus, &'i [u8], usize)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]
decompress_zlib()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]
raw_block()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 
masked_lookup(table: &HuffmanTable, bit_buf: BitBuffer) -> (i32, u32)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]
fixed_table_lookup()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 
check_result(input: &[u8], expected_status: TINFLStatus, expected_state: State, zlib: bool)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]
bogus_input()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]
empty_output_buffer_non_wrapping()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]
empty_output_buffer_wrapping()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 }
1895