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