Coverage Report

Created: 2026-08-14 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/fdeflate-0.3.7/src/decompress.rs
Line
Count
Source
1
use simd_adler32::Adler32;
2
3
use crate::{
4
    huffman::{self, build_table},
5
    tables::{
6
        self, CLCL_ORDER, DIST_SYM_TO_DIST_BASE, DIST_SYM_TO_DIST_EXTRA, FIXED_DIST_TABLE,
7
        FIXED_LITLEN_TABLE, LEN_SYM_TO_LEN_BASE, LEN_SYM_TO_LEN_EXTRA, LITLEN_TABLE_ENTRIES,
8
    },
9
};
10
11
/// An error encountered while decompressing a deflate stream.
12
#[derive(Debug, PartialEq)]
13
pub enum DecompressionError {
14
    /// The zlib header is corrupt.
15
    BadZlibHeader,
16
    /// All input was consumed, but the end of the stream hasn't been reached.
17
    InsufficientInput,
18
    /// A block header specifies an invalid block type.
19
    InvalidBlockType,
20
    /// An uncompressed block's NLEN value is invalid.
21
    InvalidUncompressedBlockLength,
22
    /// Too many literals were specified.
23
    InvalidHlit,
24
    /// Too many distance codes were specified.
25
    InvalidHdist,
26
    /// Attempted to repeat a previous code before reading any codes, or past the end of the code
27
    /// lengths.
28
    InvalidCodeLengthRepeat,
29
    /// The stream doesn't specify a valid huffman tree.
30
    BadCodeLengthHuffmanTree,
31
    /// The stream doesn't specify a valid huffman tree.
32
    BadLiteralLengthHuffmanTree,
33
    /// The stream doesn't specify a valid huffman tree.
34
    BadDistanceHuffmanTree,
35
    /// The stream contains a literal/length code that was not allowed by the header.
36
    InvalidLiteralLengthCode,
37
    /// The stream contains a distance code that was not allowed by the header.
38
    InvalidDistanceCode,
39
    /// The stream contains contains back-reference as the first symbol.
40
    InputStartsWithRun,
41
    /// The stream contains a back-reference that is too far back.
42
    DistanceTooFarBack,
43
    /// The deflate stream checksum is incorrect.
44
    WrongChecksum,
45
    /// Extra input data.
46
    ExtraInput,
47
}
48
49
struct BlockHeader {
50
    hlit: usize,
51
    hdist: usize,
52
    hclen: usize,
53
    num_lengths_read: usize,
54
55
    /// Low 3-bits are code length code length, high 5-bits are code length code.
56
    table: [u32; 128],
57
    code_lengths: [u8; 320],
58
}
59
60
pub const LITERAL_ENTRY: u32 = 0x8000;
61
pub const EXCEPTIONAL_ENTRY: u32 = 0x4000;
62
pub const SECONDARY_TABLE_ENTRY: u32 = 0x2000;
63
64
/// The Decompressor state for a compressed block.
65
#[derive(Eq, PartialEq, Debug)]
66
struct CompressedBlock {
67
    litlen_table: Box<[u32; 4096]>,
68
    secondary_table: Vec<u16>,
69
70
    dist_table: Box<[u32; 512]>,
71
    dist_secondary_table: Vec<u16>,
72
73
    eof_code: u16,
74
    eof_mask: u16,
75
    eof_bits: u8,
76
}
77
78
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
79
enum State {
80
    ZlibHeader,
81
    BlockHeader,
82
    CodeLengthCodes,
83
    CodeLengths,
84
    CompressedData,
85
    UncompressedData,
86
    Checksum,
87
    Done,
88
}
89
90
/// Decompressor for arbitrary zlib streams.
91
pub struct Decompressor {
92
    /// State for decoding a compressed block.
93
    compression: CompressedBlock,
94
    // State for decoding a block header.
95
    header: BlockHeader,
96
    // Number of bytes left for uncompressed block.
97
    uncompressed_bytes_left: u16,
98
99
    buffer: u64,
100
    nbits: u8,
101
102
    queued_rle: Option<(u8, usize)>,
103
    queued_backref: Option<(usize, usize)>,
104
    last_block: bool,
105
    fixed_table: bool,
106
107
    state: State,
108
    checksum: Adler32,
109
    ignore_adler32: bool,
110
}
111
112
impl Default for Decompressor {
113
0
    fn default() -> Self {
114
0
        Self::new()
115
0
    }
116
}
117
118
impl Decompressor {
119
    /// Create a new decompressor.
120
46.9k
    pub fn new() -> Self {
121
46.9k
        Self {
122
46.9k
            buffer: 0,
123
46.9k
            nbits: 0,
124
46.9k
            compression: CompressedBlock {
125
46.9k
                litlen_table: Box::new([0; 4096]),
126
46.9k
                dist_table: Box::new([0; 512]),
127
46.9k
                secondary_table: Vec::new(),
128
46.9k
                dist_secondary_table: Vec::new(),
129
46.9k
                eof_code: 0,
130
46.9k
                eof_mask: 0,
131
46.9k
                eof_bits: 0,
132
46.9k
            },
133
46.9k
            header: BlockHeader {
134
46.9k
                hlit: 0,
135
46.9k
                hdist: 0,
136
46.9k
                hclen: 0,
137
46.9k
                table: [0; 128],
138
46.9k
                num_lengths_read: 0,
139
46.9k
                code_lengths: [0; 320],
140
46.9k
            },
141
46.9k
            uncompressed_bytes_left: 0,
142
46.9k
            queued_rle: None,
143
46.9k
            queued_backref: None,
144
46.9k
            checksum: Adler32::new(),
145
46.9k
            state: State::ZlibHeader,
146
46.9k
            last_block: false,
147
46.9k
            ignore_adler32: false,
148
46.9k
            fixed_table: false,
149
46.9k
        }
150
46.9k
    }
151
152
    /// Ignore the checksum at the end of the stream.
153
28.0k
    pub fn ignore_adler32(&mut self) {
154
28.0k
        self.ignore_adler32 = true;
155
28.0k
    }
156
157
144M
    fn fill_buffer(&mut self, input: &mut &[u8]) {
158
144M
        if input.len() >= 8 {
159
131M
            self.buffer |= u64::from_le_bytes(input[..8].try_into().unwrap()) << self.nbits;
160
131M
            *input = &input[(63 - self.nbits as usize) / 8..];
161
131M
            self.nbits |= 56;
162
131M
        } else {
163
12.8M
            let nbytes = input.len().min((63 - self.nbits as usize) / 8);
164
12.8M
            let mut input_data = [0; 8];
165
12.8M
            input_data[..nbytes].copy_from_slice(&input[..nbytes]);
166
12.8M
            self.buffer |= u64::from_le_bytes(input_data)
167
12.8M
                .checked_shl(self.nbits as u32)
168
12.8M
                .unwrap_or(0);
169
12.8M
            self.nbits += nbytes as u8 * 8;
170
12.8M
            *input = &input[nbytes..];
171
12.8M
        }
172
144M
    }
173
174
7.41M
    fn peak_bits(&mut self, nbits: u8) -> u64 {
175
7.41M
        debug_assert!(nbits <= 56 && nbits <= self.nbits);
176
7.41M
        self.buffer & ((1u64 << nbits) - 1)
177
7.41M
    }
178
153M
    fn consume_bits(&mut self, nbits: u8) {
179
153M
        debug_assert!(self.nbits >= nbits);
180
153M
        self.buffer >>= nbits;
181
153M
        self.nbits -= nbits;
182
153M
    }
183
184
1.58M
    fn read_block_header(&mut self, remaining_input: &mut &[u8]) -> Result<(), DecompressionError> {
185
1.58M
        self.fill_buffer(remaining_input);
186
1.58M
        if self.nbits < 10 {
187
847k
            return Ok(());
188
735k
        }
189
190
735k
        let start = self.peak_bits(3);
191
735k
        self.last_block = start & 1 != 0;
192
735k
        match start >> 1 {
193
            0b00 => {
194
10.4k
                let align_bits = (self.nbits - 3) % 8;
195
10.4k
                let header_bits = 3 + 32 + align_bits;
196
10.4k
                if self.nbits < header_bits {
197
4.35k
                    return Ok(());
198
6.12k
                }
199
200
6.12k
                let len = (self.peak_bits(align_bits + 19) >> (align_bits + 3)) as u16;
201
6.12k
                let nlen = (self.peak_bits(header_bits) >> (align_bits + 19)) as u16;
202
6.12k
                if nlen != !len {
203
293
                    return Err(DecompressionError::InvalidUncompressedBlockLength);
204
5.82k
                }
205
206
5.82k
                self.state = State::UncompressedData;
207
5.82k
                self.uncompressed_bytes_left = len;
208
5.82k
                self.consume_bits(header_bits);
209
5.82k
                Ok(())
210
            }
211
            0b01 => {
212
668k
                self.consume_bits(3);
213
214
                // Check for an entirely empty blocks which can happen if there are "partial
215
                // flushes" in the deflate stream. With fixed huffman codes, the EOF symbol is
216
                // 7-bits of zeros so we peak ahead and see if the next 7-bits are all zero.
217
668k
                if self.peak_bits(7) == 0 {
218
651k
                    self.consume_bits(7);
219
651k
                    if self.last_block {
220
137
                        self.state = State::Checksum;
221
137
                        return Ok(());
222
650k
                    }
223
224
                    // At this point we've consumed the entire block and need to read the next block
225
                    // header. If tail call optimization were guaranteed, we could just recurse
226
                    // here. But without it, a long sequence of empty fixed-blocks might cause a
227
                    // stack overflow. Instead, we consume all empty blocks in a loop and then
228
                    // recurse. This is the only recursive call this function, and thus is safe.
229
1.10M
                    while self.nbits >= 10 && self.peak_bits(10) == 0b010 {
230
456k
                        self.consume_bits(10);
231
456k
                        self.fill_buffer(remaining_input);
232
456k
                    }
233
650k
                    return self.read_block_header(remaining_input);
234
17.5k
                }
235
236
                // Build decoding tables if the previous block wasn't also a fixed block.
237
17.5k
                if !self.fixed_table {
238
10.2k
                    self.fixed_table = true;
239
82.0k
                    for chunk in self.compression.litlen_table.chunks_exact_mut(512) {
240
82.0k
                        chunk.copy_from_slice(&FIXED_LITLEN_TABLE);
241
82.0k
                    }
242
164k
                    for chunk in self.compression.dist_table.chunks_exact_mut(32) {
243
164k
                        chunk.copy_from_slice(&FIXED_DIST_TABLE);
244
164k
                    }
245
10.2k
                    self.compression.eof_bits = 7;
246
10.2k
                    self.compression.eof_code = 0;
247
10.2k
                    self.compression.eof_mask = 0x7f;
248
7.34k
                }
249
250
17.5k
                self.state = State::CompressedData;
251
17.5k
                Ok(())
252
            }
253
            0b10 => {
254
56.5k
                if self.nbits < 17 {
255
11.6k
                    return Ok(());
256
44.8k
                }
257
258
44.8k
                self.header.hlit = (self.peak_bits(8) >> 3) as usize + 257;
259
44.8k
                self.header.hdist = (self.peak_bits(13) >> 8) as usize + 1;
260
44.8k
                self.header.hclen = (self.peak_bits(17) >> 13) as usize + 4;
261
44.8k
                if self.header.hlit > 286 {
262
33
                    return Err(DecompressionError::InvalidHlit);
263
44.8k
                }
264
44.8k
                if self.header.hdist > 30 {
265
31
                    return Err(DecompressionError::InvalidHdist);
266
44.8k
                }
267
268
44.8k
                self.consume_bits(17);
269
44.8k
                self.state = State::CodeLengthCodes;
270
44.8k
                self.fixed_table = false;
271
44.8k
                Ok(())
272
            }
273
170
            0b11 => Err(DecompressionError::InvalidBlockType),
274
0
            _ => unreachable!(),
275
        }
276
1.58M
    }
277
278
114k
    fn read_code_length_codes(
279
114k
        &mut self,
280
114k
        remaining_input: &mut &[u8],
281
114k
    ) -> Result<(), DecompressionError> {
282
114k
        self.fill_buffer(remaining_input);
283
114k
        if self.nbits as usize + remaining_input.len() * 8 < 3 * self.header.hclen {
284
70.0k
            return Ok(());
285
44.7k
        }
286
287
44.7k
        let mut code_length_lengths = [0; 19];
288
783k
        for i in 0..self.header.hclen {
289
783k
            code_length_lengths[CLCL_ORDER[i]] = self.peak_bits(3) as u8;
290
783k
            self.consume_bits(3);
291
292
            // We need to refill the buffer after reading 3 * 18 = 54 bits since the buffer holds
293
            // between 56 and 63 bits total.
294
783k
            if i == 17 {
295
34.8k
                self.fill_buffer(remaining_input);
296
748k
            }
297
        }
298
299
44.7k
        let mut codes = [0; 19];
300
44.7k
        if !build_table(
301
44.7k
            &code_length_lengths,
302
44.7k
            &[],
303
44.7k
            &mut codes,
304
44.7k
            &mut self.header.table,
305
44.7k
            &mut Vec::new(),
306
44.7k
            false,
307
44.7k
            false,
308
44.7k
        ) {
309
507
            return Err(DecompressionError::BadCodeLengthHuffmanTree);
310
44.1k
        }
311
312
44.1k
        self.state = State::CodeLengths;
313
44.1k
        self.header.num_lengths_read = 0;
314
44.1k
        Ok(())
315
114k
    }
316
317
319k
    fn read_code_lengths(&mut self, remaining_input: &mut &[u8]) -> Result<(), DecompressionError> {
318
319k
        let total_lengths = self.header.hlit + self.header.hdist;
319
3.82M
        while self.header.num_lengths_read < total_lengths {
320
3.78M
            self.fill_buffer(remaining_input);
321
3.78M
            if self.nbits < 7 {
322
256k
                return Ok(());
323
3.52M
            }
324
325
3.52M
            let code = self.peak_bits(7);
326
3.52M
            let entry = self.header.table[code as usize];
327
3.52M
            let length = (entry & 0x7) as u8;
328
3.52M
            let symbol = (entry >> 16) as u8;
329
330
3.52M
            debug_assert!(length != 0);
331
3.52M
            match symbol {
332
3.52M
                0..=15 => {
333
2.98M
                    self.header.code_lengths[self.header.num_lengths_read] = symbol;
334
2.98M
                    self.header.num_lengths_read += 1;
335
2.98M
                    self.consume_bits(length);
336
2.98M
                }
337
549k
                16..=18 => {
338
549k
                    let (base_repeat, extra_bits) = match symbol {
339
340k
                        16 => (3, 2),
340
84.1k
                        17 => (3, 3),
341
124k
                        18 => (11, 7),
342
0
                        _ => unreachable!(),
343
                    };
344
345
549k
                    if self.nbits < length + extra_bits {
346
19.0k
                        return Ok(());
347
530k
                    }
348
349
530k
                    let value = match symbol {
350
                        16 => {
351
340k
                            self.header.code_lengths[self
352
340k
                                .header
353
340k
                                .num_lengths_read
354
340k
                                .checked_sub(1)
355
340k
                                .ok_or(DecompressionError::InvalidCodeLengthRepeat)?]
356
                            // TODO: is this right?
357
                        }
358
82.3k
                        17 => 0,
359
107k
                        18 => 0,
360
0
                        _ => unreachable!(),
361
                    };
362
363
530k
                    let repeat =
364
530k
                        (self.peak_bits(length + extra_bits) >> length) as usize + base_repeat;
365
530k
                    if self.header.num_lengths_read + repeat > total_lengths {
366
88
                        return Err(DecompressionError::InvalidCodeLengthRepeat);
367
530k
                    }
368
369
9.59M
                    for i in 0..repeat {
370
9.59M
                        self.header.code_lengths[self.header.num_lengths_read + i] = value;
371
9.59M
                    }
372
530k
                    self.header.num_lengths_read += repeat;
373
530k
                    self.consume_bits(length + extra_bits);
374
                }
375
0
                _ => unreachable!(),
376
            }
377
        }
378
379
43.5k
        self.header
380
43.5k
            .code_lengths
381
43.5k
            .copy_within(self.header.hlit..total_lengths, 288);
382
613k
        for i in self.header.hlit..288 {
383
613k
            self.header.code_lengths[i] = 0;
384
613k
        }
385
813k
        for i in 288 + self.header.hdist..320 {
386
813k
            self.header.code_lengths[i] = 0;
387
813k
        }
388
389
43.5k
        Self::build_tables(
390
43.5k
            self.header.hlit,
391
43.5k
            &self.header.code_lengths,
392
43.5k
            &mut self.compression,
393
858
        )?;
394
42.7k
        self.state = State::CompressedData;
395
42.7k
        Ok(())
396
319k
    }
397
398
43.5k
    fn build_tables(
399
43.5k
        hlit: usize,
400
43.5k
        code_lengths: &[u8],
401
43.5k
        compression: &mut CompressedBlock,
402
43.5k
    ) -> Result<(), DecompressionError> {
403
        // If there is no code assigned for the EOF symbol then the bitstream is invalid.
404
43.5k
        if code_lengths[256] == 0 {
405
            // TODO: Return a dedicated error in this case.
406
43
            return Err(DecompressionError::BadLiteralLengthHuffmanTree);
407
43.5k
        }
408
409
43.5k
        let mut codes = [0; 288];
410
43.5k
        compression.secondary_table.clear();
411
43.5k
        if !huffman::build_table(
412
43.5k
            &code_lengths[..hlit],
413
43.5k
            &LITLEN_TABLE_ENTRIES,
414
43.5k
            &mut codes[..hlit],
415
43.5k
            &mut *compression.litlen_table,
416
43.5k
            &mut compression.secondary_table,
417
43.5k
            false,
418
43.5k
            true,
419
43.5k
        ) {
420
399
            return Err(DecompressionError::BadCodeLengthHuffmanTree);
421
43.1k
        }
422
423
43.1k
        compression.eof_code = codes[256];
424
43.1k
        compression.eof_mask = (1 << code_lengths[256]) - 1;
425
43.1k
        compression.eof_bits = code_lengths[256];
426
427
        // Build the distance code table.
428
43.1k
        let lengths = &code_lengths[288..320];
429
43.1k
        if lengths == [0; 32] {
430
1.60k
            compression.dist_table.fill(0);
431
1.60k
        } else {
432
41.5k
            let mut dist_codes = [0; 32];
433
41.5k
            if !huffman::build_table(
434
41.5k
                lengths,
435
41.5k
                &tables::DISTANCE_TABLE_ENTRIES,
436
41.5k
                &mut dist_codes,
437
41.5k
                &mut *compression.dist_table,
438
41.5k
                &mut compression.dist_secondary_table,
439
41.5k
                true,
440
41.5k
                false,
441
41.5k
            ) {
442
416
                return Err(DecompressionError::BadDistanceHuffmanTree);
443
41.1k
            }
444
        }
445
446
42.7k
        Ok(())
447
43.5k
    }
448
449
3.43M
    fn read_compressed(
450
3.43M
        &mut self,
451
3.43M
        remaining_input: &mut &[u8],
452
3.43M
        output: &mut [u8],
453
3.43M
        mut output_index: usize,
454
3.43M
    ) -> Result<usize, DecompressionError> {
455
        // Fast decoding loop.
456
        //
457
        // This loop is optimized for speed and is the main decoding loop for the decompressor,
458
        // which is used when there are at least 8 bytes of input and output data available. It
459
        // assumes that the bitbuffer is full (nbits >= 56) and that litlen_entry has been loaded.
460
        //
461
        // These assumptions enable a few optimizations:
462
        // - Nearly all checks for nbits are avoided.
463
        // - Checking the input size is optimized out in the refill function call.
464
        // - The litlen_entry for the next loop iteration can be loaded in parallel with refilling
465
        //   the bit buffer. This is because when the input is non-empty, the bit buffer actually
466
        //   has 64-bits of valid data (even though nbits will be in 56..=63).
467
3.43M
        self.fill_buffer(remaining_input);
468
3.43M
        let mut litlen_entry = self.compression.litlen_table[(self.buffer & 0xfff) as usize];
469
126M
        while self.state == State::CompressedData
470
126M
            && output_index + 8 <= output.len()
471
126M
            && remaining_input.len() >= 8
472
        {
473
            // First check whether the next symbol is a literal. This code does up to 2 additional
474
            // table lookups to decode more literals.
475
            let mut bits;
476
122M
            let mut litlen_code_bits = litlen_entry as u8;
477
122M
            if litlen_entry & LITERAL_ENTRY != 0 {
478
113M
                let litlen_entry2 = self.compression.litlen_table
479
113M
                    [(self.buffer >> litlen_code_bits & 0xfff) as usize];
480
113M
                let litlen_code_bits2 = litlen_entry2 as u8;
481
113M
                let litlen_entry3 = self.compression.litlen_table
482
113M
                    [(self.buffer >> (litlen_code_bits + litlen_code_bits2) & 0xfff) as usize];
483
113M
                let litlen_code_bits3 = litlen_entry3 as u8;
484
113M
                let litlen_entry4 = self.compression.litlen_table[(self.buffer
485
113M
                    >> (litlen_code_bits + litlen_code_bits2 + litlen_code_bits3)
486
113M
                    & 0xfff)
487
113M
                    as usize];
488
489
113M
                let advance_output_bytes = ((litlen_entry & 0xf00) >> 8) as usize;
490
113M
                output[output_index] = (litlen_entry >> 16) as u8;
491
113M
                output[output_index + 1] = (litlen_entry >> 24) as u8;
492
113M
                output_index += advance_output_bytes;
493
494
113M
                if litlen_entry2 & LITERAL_ENTRY != 0 {
495
96.1M
                    let advance_output_bytes2 = ((litlen_entry2 & 0xf00) >> 8) as usize;
496
96.1M
                    output[output_index] = (litlen_entry2 >> 16) as u8;
497
96.1M
                    output[output_index + 1] = (litlen_entry2 >> 24) as u8;
498
96.1M
                    output_index += advance_output_bytes2;
499
500
96.1M
                    if litlen_entry3 & LITERAL_ENTRY != 0 {
501
93.0M
                        let advance_output_bytes3 = ((litlen_entry3 & 0xf00) >> 8) as usize;
502
93.0M
                        output[output_index] = (litlen_entry3 >> 16) as u8;
503
93.0M
                        output[output_index + 1] = (litlen_entry3 >> 24) as u8;
504
93.0M
                        output_index += advance_output_bytes3;
505
506
93.0M
                        litlen_entry = litlen_entry4;
507
93.0M
                        self.consume_bits(litlen_code_bits + litlen_code_bits2 + litlen_code_bits3);
508
93.0M
                        self.fill_buffer(remaining_input);
509
93.0M
                        continue;
510
3.10M
                    } else {
511
3.10M
                        self.consume_bits(litlen_code_bits + litlen_code_bits2);
512
3.10M
                        litlen_entry = litlen_entry3;
513
3.10M
                        litlen_code_bits = litlen_code_bits3;
514
3.10M
                        self.fill_buffer(remaining_input);
515
3.10M
                        bits = self.buffer;
516
3.10M
                    }
517
                } else {
518
17.2M
                    self.consume_bits(litlen_code_bits);
519
17.2M
                    bits = self.buffer;
520
17.2M
                    litlen_entry = litlen_entry2;
521
17.2M
                    litlen_code_bits = litlen_code_bits2;
522
17.2M
                    if self.nbits < 48 {
523
2.12M
                        self.fill_buffer(remaining_input);
524
15.1M
                    }
525
                }
526
9.43M
            } else {
527
9.43M
                bits = self.buffer;
528
9.43M
            }
529
530
            // The next symbol is either a 13+ bit literal, back-reference, or an EOF symbol.
531
29.6M
            let (length_base, length_extra_bits, litlen_code_bits) =
532
29.8M
                if litlen_entry & EXCEPTIONAL_ENTRY == 0 {
533
29.5M
                    (
534
29.5M
                        litlen_entry >> 16,
535
29.5M
                        (litlen_entry >> 8) as u8,
536
29.5M
                        litlen_code_bits,
537
29.5M
                    )
538
278k
                } else if litlen_entry & SECONDARY_TABLE_ENTRY != 0 {
539
263k
                    let secondary_table_index =
540
263k
                        (litlen_entry >> 16) + ((bits >> 12) as u32 & (litlen_entry & 0xff));
541
263k
                    let secondary_entry =
542
263k
                        self.compression.secondary_table[secondary_table_index as usize];
543
263k
                    let litlen_symbol = secondary_entry >> 4;
544
263k
                    let litlen_code_bits = (secondary_entry & 0xf) as u8;
545
546
263k
                    match litlen_symbol {
547
263k
                        0..=255 => {
548
120k
                            self.consume_bits(litlen_code_bits);
549
120k
                            litlen_entry =
550
120k
                                self.compression.litlen_table[(self.buffer & 0xfff) as usize];
551
120k
                            self.fill_buffer(remaining_input);
552
120k
                            output[output_index] = litlen_symbol as u8;
553
120k
                            output_index += 1;
554
120k
                            continue;
555
                        }
556
                        256 => {
557
8.06k
                            self.consume_bits(litlen_code_bits);
558
8.06k
                            self.state = match self.last_block {
559
3
                                true => State::Checksum,
560
8.06k
                                false => State::BlockHeader,
561
                            };
562
8.06k
                            break;
563
                        }
564
134k
                        _ => (
565
134k
                            LEN_SYM_TO_LEN_BASE[litlen_symbol as usize - 257] as u32,
566
134k
                            LEN_SYM_TO_LEN_EXTRA[litlen_symbol as usize - 257],
567
134k
                            litlen_code_bits,
568
134k
                        ),
569
                    }
570
15.9k
                } else if litlen_code_bits == 0 {
571
0
                    return Err(DecompressionError::InvalidLiteralLengthCode);
572
                } else {
573
15.9k
                    self.consume_bits(litlen_code_bits);
574
15.9k
                    self.state = match self.last_block {
575
378
                        true => State::Checksum,
576
15.5k
                        false => State::BlockHeader,
577
                    };
578
15.9k
                    break;
579
                };
580
29.6M
            bits >>= litlen_code_bits;
581
582
29.6M
            let length_extra_mask = (1 << length_extra_bits) - 1;
583
29.6M
            let length = length_base as usize + (bits & length_extra_mask) as usize;
584
29.6M
            bits >>= length_extra_bits;
585
586
29.6M
            let dist_entry = self.compression.dist_table[(bits & 0x1ff) as usize];
587
29.6M
            let (dist_base, dist_extra_bits, dist_code_bits) = if dist_entry & LITERAL_ENTRY != 0 {
588
29.1M
                (
589
29.1M
                    (dist_entry >> 16) as u16,
590
29.1M
                    (dist_entry >> 8) as u8 & 0xf,
591
29.1M
                    dist_entry as u8,
592
29.1M
                )
593
480k
            } else if dist_entry >> 8 == 0 {
594
31
                return Err(DecompressionError::InvalidDistanceCode);
595
            } else {
596
480k
                let secondary_table_index =
597
480k
                    (dist_entry >> 16) + ((bits >> 9) as u32 & (dist_entry & 0xff));
598
480k
                let secondary_entry =
599
480k
                    self.compression.dist_secondary_table[secondary_table_index as usize];
600
480k
                let dist_symbol = (secondary_entry >> 4) as usize;
601
480k
                if dist_symbol >= 30 {
602
0
                    return Err(DecompressionError::InvalidDistanceCode);
603
480k
                }
604
605
480k
                (
606
480k
                    DIST_SYM_TO_DIST_BASE[dist_symbol],
607
480k
                    DIST_SYM_TO_DIST_EXTRA[dist_symbol],
608
480k
                    (secondary_entry & 0xf) as u8,
609
480k
                )
610
            };
611
29.6M
            bits >>= dist_code_bits;
612
613
29.6M
            let dist = dist_base as usize + (bits & ((1 << dist_extra_bits) - 1)) as usize;
614
29.6M
            if dist > output_index {
615
103
                return Err(DecompressionError::DistanceTooFarBack);
616
29.6M
            }
617
618
29.6M
            self.consume_bits(
619
29.6M
                litlen_code_bits + length_extra_bits + dist_code_bits + dist_extra_bits,
620
            );
621
29.6M
            self.fill_buffer(remaining_input);
622
29.6M
            litlen_entry = self.compression.litlen_table[(self.buffer & 0xfff) as usize];
623
624
29.6M
            let copy_length = length.min(output.len() - output_index);
625
29.6M
            if dist == 1 {
626
1.80M
                let last = output[output_index - 1];
627
1.80M
                output[output_index..][..copy_length].fill(last);
628
629
1.80M
                if copy_length < length {
630
17.3k
                    self.queued_rle = Some((last, length - copy_length));
631
17.3k
                    output_index = output.len();
632
17.3k
                    break;
633
1.78M
                }
634
27.8M
            } else if output_index + length + 15 <= output.len() {
635
27.7M
                let start = output_index - dist;
636
27.7M
                output.copy_within(start..start + 16, output_index);
637
638
27.7M
                if length > 16 || dist < 16 {
639
99.6M
                    for i in (0..length).step_by(dist.min(16)).skip(1) {
640
99.6M
                        output.copy_within(start + i..start + i + 16, output_index + i);
641
99.6M
                    }
642
14.8M
                }
643
            } else {
644
82.4k
                if dist < copy_length {
645
5.29M
                    for i in 0..copy_length {
646
5.29M
                        output[output_index + i] = output[output_index + i - dist];
647
5.29M
                    }
648
                } else {
649
45.4k
                    output.copy_within(
650
45.4k
                        output_index - dist..output_index + copy_length - dist,
651
45.4k
                        output_index,
652
                    )
653
                }
654
655
82.4k
                if copy_length < length {
656
38.6k
                    self.queued_backref = Some((dist, length - copy_length));
657
38.6k
                    output_index = output.len();
658
38.6k
                    break;
659
43.7k
                }
660
            }
661
29.6M
            output_index += copy_length;
662
        }
663
664
        // Careful decoding loop.
665
        //
666
        // This loop processes the remaining input when we're too close to the end of the input or
667
        // output to use the fast loop.
668
7.25M
        while let State::CompressedData = self.state {
669
7.23M
            self.fill_buffer(remaining_input);
670
7.23M
            if output_index == output.len() {
671
92.0k
                break;
672
7.14M
            }
673
674
7.14M
            let mut bits = self.buffer;
675
7.14M
            let litlen_entry = self.compression.litlen_table[(bits & 0xfff) as usize];
676
7.14M
            let litlen_code_bits = litlen_entry as u8;
677
678
7.14M
            if litlen_entry & LITERAL_ENTRY != 0 {
679
                // Fast path: the next symbol is <= 12 bits and a literal, the table specifies the
680
                // output bytes and we can directly write them to the output buffer.
681
1.90M
                let advance_output_bytes = ((litlen_entry & 0xf00) >> 8) as usize;
682
683
1.90M
                if self.nbits < litlen_code_bits {
684
672k
                    break;
685
1.23M
                } else if output_index + 1 < output.len() {
686
1.19M
                    output[output_index] = (litlen_entry >> 16) as u8;
687
1.19M
                    output[output_index + 1] = (litlen_entry >> 24) as u8;
688
1.19M
                    output_index += advance_output_bytes;
689
1.19M
                    self.consume_bits(litlen_code_bits);
690
1.19M
                    continue;
691
36.4k
                } else if output_index + advance_output_bytes == output.len() {
692
25.8k
                    debug_assert_eq!(advance_output_bytes, 1);
693
25.8k
                    output[output_index] = (litlen_entry >> 16) as u8;
694
25.8k
                    output_index += 1;
695
25.8k
                    self.consume_bits(litlen_code_bits);
696
25.8k
                    break;
697
                } else {
698
10.6k
                    debug_assert_eq!(advance_output_bytes, 2);
699
10.6k
                    output[output_index] = (litlen_entry >> 16) as u8;
700
10.6k
                    self.queued_rle = Some(((litlen_entry >> 24) as u8, 1));
701
10.6k
                    output_index += 1;
702
10.6k
                    self.consume_bits(litlen_code_bits);
703
10.6k
                    break;
704
                }
705
5.23M
            }
706
707
5.18M
            let (length_base, length_extra_bits, litlen_code_bits) =
708
5.23M
                if litlen_entry & EXCEPTIONAL_ENTRY == 0 {
709
5.17M
                    (
710
5.17M
                        litlen_entry >> 16,
711
5.17M
                        (litlen_entry >> 8) as u8,
712
5.17M
                        litlen_code_bits,
713
5.17M
                    )
714
62.0k
                } else if litlen_entry & SECONDARY_TABLE_ENTRY != 0 {
715
27.9k
                    let secondary_table_index =
716
27.9k
                        (litlen_entry >> 16) + ((bits >> 12) as u32 & (litlen_entry & 0xff));
717
27.9k
                    let secondary_entry =
718
27.9k
                        self.compression.secondary_table[secondary_table_index as usize];
719
27.9k
                    let litlen_symbol = secondary_entry >> 4;
720
27.9k
                    let litlen_code_bits = (secondary_entry & 0xf) as u8;
721
722
27.9k
                    if self.nbits < litlen_code_bits {
723
6.40k
                        break;
724
21.5k
                    } else if litlen_symbol < 256 {
725
4.40k
                        self.consume_bits(litlen_code_bits);
726
4.40k
                        output[output_index] = litlen_symbol as u8;
727
4.40k
                        output_index += 1;
728
4.40k
                        continue;
729
17.1k
                    } else if litlen_symbol == 256 {
730
2.60k
                        self.consume_bits(litlen_code_bits);
731
2.60k
                        self.state = match self.last_block {
732
0
                            true => State::Checksum,
733
2.60k
                            false => State::BlockHeader,
734
                        };
735
2.60k
                        break;
736
14.5k
                    }
737
738
14.5k
                    (
739
14.5k
                        LEN_SYM_TO_LEN_BASE[litlen_symbol as usize - 257] as u32,
740
14.5k
                        LEN_SYM_TO_LEN_EXTRA[litlen_symbol as usize - 257],
741
14.5k
                        litlen_code_bits,
742
14.5k
                    )
743
34.0k
                } else if litlen_code_bits == 0 {
744
0
                    return Err(DecompressionError::InvalidLiteralLengthCode);
745
                } else {
746
34.0k
                    if self.nbits < litlen_code_bits {
747
21.9k
                        break;
748
12.0k
                    }
749
12.0k
                    self.consume_bits(litlen_code_bits);
750
12.0k
                    self.state = match self.last_block {
751
1.78k
                        true => State::Checksum,
752
10.2k
                        false => State::BlockHeader,
753
                    };
754
12.0k
                    break;
755
                };
756
5.18M
            bits >>= litlen_code_bits;
757
758
5.18M
            let length_extra_mask = (1 << length_extra_bits) - 1;
759
5.18M
            let length = length_base as usize + (bits & length_extra_mask) as usize;
760
5.18M
            bits >>= length_extra_bits;
761
762
5.18M
            let dist_entry = self.compression.dist_table[(bits & 0x1ff) as usize];
763
5.18M
            let (dist_base, dist_extra_bits, dist_code_bits) = if dist_entry & LITERAL_ENTRY != 0 {
764
5.06M
                (
765
5.06M
                    (dist_entry >> 16) as u16,
766
5.06M
                    (dist_entry >> 8) as u8 & 0xf,
767
5.06M
                    dist_entry as u8,
768
5.06M
                )
769
123k
            } else if self.nbits > litlen_code_bits + length_extra_bits + 9 {
770
119k
                if dist_entry >> 8 == 0 {
771
302
                    return Err(DecompressionError::InvalidDistanceCode);
772
119k
                }
773
774
119k
                let secondary_table_index =
775
119k
                    (dist_entry >> 16) + ((bits >> 9) as u32 & (dist_entry & 0xff));
776
119k
                let secondary_entry =
777
119k
                    self.compression.dist_secondary_table[secondary_table_index as usize];
778
119k
                let dist_symbol = (secondary_entry >> 4) as usize;
779
119k
                if dist_symbol >= 30 {
780
0
                    return Err(DecompressionError::InvalidDistanceCode);
781
119k
                }
782
783
119k
                (
784
119k
                    DIST_SYM_TO_DIST_BASE[dist_symbol],
785
119k
                    DIST_SYM_TO_DIST_EXTRA[dist_symbol],
786
119k
                    (secondary_entry & 0xf) as u8,
787
119k
                )
788
            } else {
789
4.26k
                break;
790
            };
791
5.18M
            bits >>= dist_code_bits;
792
793
5.18M
            let dist = dist_base as usize + (bits & ((1 << dist_extra_bits) - 1)) as usize;
794
5.18M
            let total_bits =
795
5.18M
                litlen_code_bits + length_extra_bits + dist_code_bits + dist_extra_bits;
796
797
5.18M
            if self.nbits < total_bits {
798
2.54M
                break;
799
2.63M
            } else if dist > output_index {
800
643
                return Err(DecompressionError::DistanceTooFarBack);
801
2.63M
            }
802
803
2.63M
            self.consume_bits(total_bits);
804
805
2.63M
            let copy_length = length.min(output.len() - output_index);
806
2.63M
            if dist == 1 {
807
631k
                let last = output[output_index - 1];
808
631k
                output[output_index..][..copy_length].fill(last);
809
810
631k
                if copy_length < length {
811
4.76k
                    self.queued_rle = Some((last, length - copy_length));
812
4.76k
                    output_index = output.len();
813
4.76k
                    break;
814
626k
                }
815
2.00M
            } else if output_index + length + 15 <= output.len() {
816
1.96M
                let start = output_index - dist;
817
1.96M
                output.copy_within(start..start + 16, output_index);
818
819
1.96M
                if length > 16 || dist < 16 {
820
95.2M
                    for i in (0..length).step_by(dist.min(16)).skip(1) {
821
95.2M
                        output.copy_within(start + i..start + i + 16, output_index + i);
822
95.2M
                    }
823
686k
                }
824
            } else {
825
34.4k
                if dist < copy_length {
826
496k
                    for i in 0..copy_length {
827
496k
                        output[output_index + i] = output[output_index + i - dist];
828
496k
                    }
829
                } else {
830
27.3k
                    output.copy_within(
831
27.3k
                        output_index - dist..output_index + copy_length - dist,
832
27.3k
                        output_index,
833
                    )
834
                }
835
836
34.4k
                if copy_length < length {
837
11.9k
                    self.queued_backref = Some((dist, length - copy_length));
838
11.9k
                    output_index = output.len();
839
11.9k
                    break;
840
22.5k
                }
841
            }
842
2.61M
            output_index += copy_length;
843
        }
844
845
3.43M
        if self.state == State::CompressedData
846
3.39M
            && self.queued_backref.is_none()
847
3.34M
            && self.queued_rle.is_none()
848
3.31M
            && self.nbits >= 15
849
493k
            && self.peak_bits(15) as u16 & self.compression.eof_mask == self.compression.eof_code
850
        {
851
9.85k
            self.consume_bits(self.compression.eof_bits);
852
9.85k
            self.state = match self.last_block {
853
9.50k
                true => State::Checksum,
854
353
                false => State::BlockHeader,
855
            };
856
3.42M
        }
857
858
3.43M
        Ok(output_index)
859
3.43M
    }
860
861
    /// Decompresses a chunk of data.
862
    ///
863
    /// Returns the number of bytes read from `input` and the number of bytes written to `output`,
864
    /// or an error if the deflate stream is not valid. `input` is the compressed data. `output` is
865
    /// the buffer to write the decompressed data to, starting at index `output_position`.
866
    /// `end_of_input` indicates whether more data may be available in the future.
867
    ///
868
    /// The contents of `output` after `output_position` are ignored. However, this function may
869
    /// write additional data to `output` past what is indicated by the return value.
870
    ///
871
    /// When this function returns `Ok`, at least one of the following is true:
872
    /// - The input is fully consumed.
873
    /// - The output is full but there are more bytes to output.
874
    /// - The deflate stream is complete (and `is_done` will return true).
875
    ///
876
    /// # Panics
877
    ///
878
    /// This function will panic if `output_position` is out of bounds.
879
4.64M
    pub fn read(
880
4.64M
        &mut self,
881
4.64M
        input: &[u8],
882
4.64M
        output: &mut [u8],
883
4.64M
        output_position: usize,
884
4.64M
        end_of_input: bool,
885
4.64M
    ) -> Result<(usize, usize), DecompressionError> {
886
4.64M
        if let State::Done = self.state {
887
0
            return Ok((0, 0));
888
4.64M
        }
889
890
4.64M
        assert!(output_position <= output.len());
891
892
4.64M
        let mut remaining_input = input;
893
4.64M
        let mut output_index = output_position;
894
895
4.64M
        if let Some((data, len)) = self.queued_rle.take() {
896
30.4k
            let n = len.min(output.len() - output_index);
897
30.4k
            output[output_index..][..n].fill(data);
898
30.4k
            output_index += n;
899
30.4k
            if n < len {
900
23
                self.queued_rle = Some((data, len - n));
901
23
                return Ok((0, n));
902
30.4k
            }
903
4.61M
        }
904
4.64M
        if let Some((dist, len)) = self.queued_backref.take() {
905
49.0k
            let n = len.min(output.len() - output_index);
906
5.51M
            for i in 0..n {
907
5.51M
                output[output_index + i] = output[output_index + i - dist];
908
5.51M
            }
909
49.0k
            output_index += n;
910
49.0k
            if n < len {
911
99
                self.queued_backref = Some((dist, len - n));
912
99
                return Ok((0, n));
913
48.9k
            }
914
4.59M
        }
915
916
        // Main decoding state machine.
917
4.64M
        let mut last_state = None;
918
9.50M
        while last_state != Some(self.state) {
919
4.88M
            last_state = Some(self.state);
920
4.88M
            match self.state {
921
                State::ZlibHeader => {
922
40.0k
                    self.fill_buffer(&mut remaining_input);
923
40.0k
                    if self.nbits < 16 {
924
10.9k
                        break;
925
29.1k
                    }
926
927
29.1k
                    let input0 = self.peak_bits(8);
928
29.1k
                    let input1 = self.peak_bits(16) >> 8 & 0xff;
929
29.1k
                    if input0 & 0x0f != 0x08
930
28.9k
                        || (input0 & 0xf0) > 0x70
931
28.9k
                        || input1 & 0x20 != 0
932
28.9k
                        || (input0 << 8 | input1) % 31 != 0
933
                    {
934
198
                        return Err(DecompressionError::BadZlibHeader);
935
28.9k
                    }
936
937
28.9k
                    self.consume_bits(16);
938
28.9k
                    self.state = State::BlockHeader;
939
                }
940
                State::BlockHeader => {
941
932k
                    self.read_block_header(&mut remaining_input)?;
942
                }
943
                State::CodeLengthCodes => {
944
114k
                    self.read_code_length_codes(&mut remaining_input)?;
945
                }
946
                State::CodeLengths => {
947
319k
                    self.read_code_lengths(&mut remaining_input)?;
948
                }
949
                State::CompressedData => {
950
                    output_index =
951
3.43M
                        self.read_compressed(&mut remaining_input, output, output_index)?
952
                }
953
                State::UncompressedData => {
954
                    // Drain any bytes from our buffer.
955
20.1k
                    debug_assert_eq!(self.nbits % 8, 0);
956
29.0k
                    while self.nbits > 0
957
9.72k
                        && self.uncompressed_bytes_left > 0
958
9.16k
                        && output_index < output.len()
959
8.95k
                    {
960
8.95k
                        output[output_index] = self.peak_bits(8) as u8;
961
8.95k
                        self.consume_bits(8);
962
8.95k
                        output_index += 1;
963
8.95k
                        self.uncompressed_bytes_left -= 1;
964
8.95k
                    }
965
                    // Buffer may contain one additional byte. Clear it to avoid confusion.
966
20.1k
                    if self.nbits == 0 {
967
19.3k
                        self.buffer = 0;
968
19.3k
                    }
969
970
                    // Copy subsequent bytes directly from the input.
971
20.1k
                    let copy_bytes = (self.uncompressed_bytes_left as usize)
972
20.1k
                        .min(remaining_input.len())
973
20.1k
                        .min(output.len() - output_index);
974
20.1k
                    output[output_index..][..copy_bytes]
975
20.1k
                        .copy_from_slice(&remaining_input[..copy_bytes]);
976
20.1k
                    remaining_input = &remaining_input[copy_bytes..];
977
20.1k
                    output_index += copy_bytes;
978
20.1k
                    self.uncompressed_bytes_left -= copy_bytes as u16;
979
980
20.1k
                    if self.uncompressed_bytes_left == 0 {
981
5.58k
                        self.state = if self.last_block {
982
1.86k
                            State::Checksum
983
                        } else {
984
3.72k
                            State::BlockHeader
985
                        };
986
14.5k
                    }
987
                }
988
                State::Checksum => {
989
16.8k
                    self.fill_buffer(&mut remaining_input);
990
991
16.8k
                    let align_bits = self.nbits % 8;
992
16.8k
                    if self.nbits >= 32 + align_bits {
993
13.3k
                        self.checksum.write(&output[output_position..output_index]);
994
13.3k
                        if align_bits != 0 {
995
9.92k
                            self.consume_bits(align_bits);
996
9.92k
                        }
997
                        #[cfg(not(fuzzing))]
998
                        if !self.ignore_adler32
999
                            && (self.peak_bits(32) as u32).swap_bytes() != self.checksum.finish()
1000
                        {
1001
                            return Err(DecompressionError::WrongChecksum);
1002
                        }
1003
13.3k
                        self.state = State::Done;
1004
13.3k
                        self.consume_bits(32);
1005
13.3k
                        break;
1006
3.45k
                    }
1007
                }
1008
0
                State::Done => unreachable!(),
1009
            }
1010
        }
1011
1012
4.64M
        if !self.ignore_adler32 && self.state != State::Done {
1013
1.98k
            self.checksum.write(&output[output_position..output_index]);
1014
4.63M
        }
1015
1016
4.64M
        if self.state == State::Done || !end_of_input || output_index == output.len() {
1017
4.64M
            let input_left = remaining_input.len();
1018
4.64M
            Ok((input.len() - input_left, output_index - output_position))
1019
        } else {
1020
380
            Err(DecompressionError::InsufficientInput)
1021
        }
1022
4.64M
    }
1023
1024
    /// Returns true if the decompressor has finished decompressing the input.
1025
11.1M
    pub fn is_done(&self) -> bool {
1026
11.1M
        self.state == State::Done
1027
11.1M
    }
1028
}
1029
1030
/// Decompress the given data.
1031
0
pub fn decompress_to_vec(input: &[u8]) -> Result<Vec<u8>, DecompressionError> {
1032
0
    match decompress_to_vec_bounded(input, usize::MAX) {
1033
0
        Ok(output) => Ok(output),
1034
0
        Err(BoundedDecompressionError::DecompressionError { inner }) => Err(inner),
1035
        Err(BoundedDecompressionError::OutputTooLarge { .. }) => {
1036
0
            unreachable!("Impossible to allocate more than isize::MAX bytes")
1037
        }
1038
    }
1039
0
}
1040
1041
/// An error encountered while decompressing a deflate stream given a bounded maximum output.
1042
pub enum BoundedDecompressionError {
1043
    /// The input is not a valid deflate stream.
1044
    DecompressionError {
1045
        /// The underlying error.
1046
        inner: DecompressionError,
1047
    },
1048
1049
    /// The output is too large.
1050
    OutputTooLarge {
1051
        /// The output decoded so far.
1052
        partial_output: Vec<u8>,
1053
    },
1054
}
1055
impl From<DecompressionError> for BoundedDecompressionError {
1056
633
    fn from(inner: DecompressionError) -> Self {
1057
633
        BoundedDecompressionError::DecompressionError { inner }
1058
633
    }
1059
}
1060
1061
/// Decompress the given data, returning an error if the output is larger than
1062
/// `maxlen` bytes.
1063
1.51k
pub fn decompress_to_vec_bounded(
1064
1.51k
    input: &[u8],
1065
1.51k
    maxlen: usize,
1066
1.51k
) -> Result<Vec<u8>, BoundedDecompressionError> {
1067
1.51k
    let mut decoder = Decompressor::new();
1068
1.51k
    let mut output = vec![0; 1024.min(maxlen)];
1069
1.51k
    let mut input_index = 0;
1070
1.51k
    let mut output_index = 0;
1071
    loop {
1072
2.27k
        let (consumed, produced) =
1073
2.90k
            decoder.read(&input[input_index..], &mut output, output_index, true)?;
1074
2.27k
        input_index += consumed;
1075
2.27k
        output_index += produced;
1076
2.27k
        if decoder.is_done() || output_index == maxlen {
1077
877
            break;
1078
1.39k
        }
1079
1.39k
        output.resize((output_index + 32 * 1024).min(maxlen), 0);
1080
    }
1081
877
    output.resize(output_index, 0);
1082
1083
877
    if decoder.is_done() {
1084
641
        Ok(output)
1085
    } else {
1086
236
        Err(BoundedDecompressionError::OutputTooLarge {
1087
236
            partial_output: output,
1088
236
        })
1089
    }
1090
1.51k
}
1091
1092
#[cfg(test)]
1093
mod tests {
1094
    use crate::tables::{LENGTH_TO_LEN_EXTRA, LENGTH_TO_SYMBOL};
1095
1096
    use super::*;
1097
    use rand::Rng;
1098
1099
    fn roundtrip(data: &[u8]) {
1100
        let compressed = crate::compress_to_vec(data);
1101
        let decompressed = decompress_to_vec(&compressed).unwrap();
1102
        assert_eq!(&decompressed, data);
1103
    }
1104
1105
    fn roundtrip_miniz_oxide(data: &[u8]) {
1106
        let compressed = miniz_oxide::deflate::compress_to_vec_zlib(data, 3);
1107
        let decompressed = decompress_to_vec(&compressed).unwrap();
1108
        assert_eq!(decompressed.len(), data.len());
1109
        for (i, (a, b)) in decompressed.chunks(1).zip(data.chunks(1)).enumerate() {
1110
            assert_eq!(a, b, "chunk {}..{}", i, i + 1);
1111
        }
1112
        assert_eq!(&decompressed, data);
1113
    }
1114
1115
    #[allow(unused)]
1116
    fn compare_decompression(data: &[u8]) {
1117
        // let decompressed0 = flate2::read::ZlibDecoder::new(std::io::Cursor::new(&data))
1118
        //     .bytes()
1119
        //     .collect::<Result<Vec<_>, _>>()
1120
        //     .unwrap();
1121
        let decompressed = decompress_to_vec(data).unwrap();
1122
        let decompressed2 = miniz_oxide::inflate::decompress_to_vec_zlib(data).unwrap();
1123
        for i in 0..decompressed.len().min(decompressed2.len()) {
1124
            if decompressed[i] != decompressed2[i] {
1125
                panic!(
1126
                    "mismatch at index {} {:?} {:?}",
1127
                    i,
1128
                    &decompressed[i.saturating_sub(1)..(i + 16).min(decompressed.len())],
1129
                    &decompressed2[i.saturating_sub(1)..(i + 16).min(decompressed2.len())]
1130
                );
1131
            }
1132
        }
1133
        if decompressed != decompressed2 {
1134
            panic!(
1135
                "length mismatch {} {} {:x?}",
1136
                decompressed.len(),
1137
                decompressed2.len(),
1138
                &decompressed2[decompressed.len()..][..16]
1139
            );
1140
        }
1141
        //assert_eq!(decompressed, decompressed2);
1142
    }
1143
1144
    #[test]
1145
    fn tables() {
1146
        for (i, &bits) in LEN_SYM_TO_LEN_EXTRA.iter().enumerate() {
1147
            let len_base = LEN_SYM_TO_LEN_BASE[i];
1148
            for j in 0..(1 << bits) {
1149
                if i == 27 && j == 31 {
1150
                    continue;
1151
                }
1152
                assert_eq!(LENGTH_TO_LEN_EXTRA[len_base + j - 3], bits, "{} {}", i, j);
1153
                assert_eq!(
1154
                    LENGTH_TO_SYMBOL[len_base + j - 3],
1155
                    i as u16 + 257,
1156
                    "{} {}",
1157
                    i,
1158
                    j
1159
                );
1160
            }
1161
        }
1162
    }
1163
1164
    #[test]
1165
    fn fixed_tables() {
1166
        let mut compression = CompressedBlock {
1167
            litlen_table: Box::new([0; 4096]),
1168
            dist_table: Box::new([0; 512]),
1169
            secondary_table: Vec::new(),
1170
            dist_secondary_table: Vec::new(),
1171
            eof_code: 0,
1172
            eof_mask: 0,
1173
            eof_bits: 0,
1174
        };
1175
        Decompressor::build_tables(288, &FIXED_CODE_LENGTHS, &mut compression).unwrap();
1176
1177
        assert_eq!(compression.litlen_table[..512], FIXED_LITLEN_TABLE);
1178
        assert_eq!(compression.dist_table[..32], FIXED_DIST_TABLE);
1179
    }
1180
1181
    #[test]
1182
    fn it_works() {
1183
        roundtrip(b"Hello world!");
1184
    }
1185
1186
    #[test]
1187
    fn constant() {
1188
        roundtrip_miniz_oxide(&[0; 50]);
1189
        roundtrip_miniz_oxide(&vec![5; 2048]);
1190
        roundtrip_miniz_oxide(&vec![128; 2048]);
1191
        roundtrip_miniz_oxide(&vec![254; 2048]);
1192
    }
1193
1194
    #[test]
1195
    fn random() {
1196
        let mut rng = rand::thread_rng();
1197
        let mut data = vec![0; 50000];
1198
        for _ in 0..10 {
1199
            for byte in &mut data {
1200
                *byte = rng.gen::<u8>() % 5;
1201
            }
1202
            println!("Random data: {:?}", data);
1203
            roundtrip_miniz_oxide(&data);
1204
        }
1205
    }
1206
1207
    #[test]
1208
    fn ignore_adler32() {
1209
        let mut compressed = crate::compress_to_vec(b"Hello world!");
1210
        let last_byte = compressed.len() - 1;
1211
        compressed[last_byte] = compressed[last_byte].wrapping_add(1);
1212
1213
        match decompress_to_vec(&compressed) {
1214
            Err(DecompressionError::WrongChecksum) => {}
1215
            r => panic!("expected WrongChecksum, got {:?}", r),
1216
        }
1217
1218
        let mut decompressor = Decompressor::new();
1219
        decompressor.ignore_adler32();
1220
        let mut decompressed = vec![0; 1024];
1221
        let decompressed_len = decompressor
1222
            .read(&compressed, &mut decompressed, 0, true)
1223
            .unwrap()
1224
            .1;
1225
        assert_eq!(&decompressed[..decompressed_len], b"Hello world!");
1226
    }
1227
1228
    #[test]
1229
    fn checksum_after_eof() {
1230
        let input = b"Hello world!";
1231
        let compressed = crate::compress_to_vec(input);
1232
1233
        let mut decompressor = Decompressor::new();
1234
        let mut decompressed = vec![0; 1024];
1235
        let (input_consumed, output_written) = decompressor
1236
            .read(
1237
                &compressed[..compressed.len() - 1],
1238
                &mut decompressed,
1239
                0,
1240
                false,
1241
            )
1242
            .unwrap();
1243
        assert_eq!(output_written, input.len());
1244
        assert_eq!(input_consumed, compressed.len() - 1);
1245
1246
        let (input_consumed, output_written) = decompressor
1247
            .read(
1248
                &compressed[input_consumed..],
1249
                &mut decompressed[..output_written],
1250
                output_written,
1251
                true,
1252
            )
1253
            .unwrap();
1254
        assert!(decompressor.is_done());
1255
        assert_eq!(input_consumed, 1);
1256
        assert_eq!(output_written, 0);
1257
1258
        assert_eq!(&decompressed[..input.len()], input);
1259
    }
1260
1261
    #[test]
1262
    fn zero_length() {
1263
        let mut compressed = crate::compress_to_vec(b"").to_vec();
1264
1265
        // Splice in zero-length non-compressed blocks.
1266
        for _ in 0..10 {
1267
            println!("compressed len: {}", compressed.len());
1268
            compressed.splice(2..2, [0u8, 0, 0, 0xff, 0xff].into_iter());
1269
        }
1270
1271
        // Ensure that the full input is decompressed, regardless of whether
1272
        // `end_of_input` is set.
1273
        for end_of_input in [true, false] {
1274
            let mut decompressor = Decompressor::new();
1275
            let (input_consumed, output_written) = decompressor
1276
                .read(&compressed, &mut [], 0, end_of_input)
1277
                .unwrap();
1278
1279
            assert!(decompressor.is_done());
1280
            assert_eq!(input_consumed, compressed.len());
1281
            assert_eq!(output_written, 0);
1282
        }
1283
    }
1284
1285
    mod test_utils;
1286
    use tables::FIXED_CODE_LENGTHS;
1287
    use test_utils::{decompress_by_chunks, TestDecompressionError};
1288
1289
    fn verify_no_sensitivity_to_input_chunking(
1290
        input: &[u8],
1291
    ) -> Result<Vec<u8>, TestDecompressionError> {
1292
        let r_whole = decompress_by_chunks(input, vec![input.len()], false);
1293
        let r_bytewise = decompress_by_chunks(input, std::iter::repeat(1), false);
1294
        assert_eq!(r_whole, r_bytewise);
1295
        r_whole // Returning an arbitrary result, since this is equal to `r_bytewise`.
1296
    }
1297
1298
    /// This is a regression test found by the `buf_independent` fuzzer from the `png` crate.  When
1299
    /// this test case was found, the results were unexpectedly different when 1) decompressing the
1300
    /// whole input (successful result) vs 2) decompressing byte-by-byte
1301
    /// (`Err(InvalidDistanceCode)`).
1302
    #[test]
1303
    fn test_input_chunking_sensitivity_when_handling_distance_codes() {
1304
        let result = verify_no_sensitivity_to_input_chunking(include_bytes!(
1305
            "../tests/input-chunking-sensitivity-example1.zz"
1306
        ))
1307
        .unwrap();
1308
        assert_eq!(result.len(), 281);
1309
        assert_eq!(simd_adler32::adler32(&result.as_slice()), 751299);
1310
    }
1311
1312
    /// This is a regression test found by the `inflate_bytewise3` fuzzer from the `fdeflate`
1313
    /// crate.  When this test case was found, the results were unexpectedly different when 1)
1314
    /// decompressing the whole input (`Err(DistanceTooFarBack)`) vs 2) decompressing byte-by-byte
1315
    /// (successful result)`).
1316
    #[test]
1317
    fn test_input_chunking_sensitivity_when_no_end_of_block_symbol_example1() {
1318
        let err = verify_no_sensitivity_to_input_chunking(include_bytes!(
1319
            "../tests/input-chunking-sensitivity-example2.zz"
1320
        ))
1321
        .unwrap_err();
1322
        assert_eq!(
1323
            err,
1324
            TestDecompressionError::ProdError(DecompressionError::BadLiteralLengthHuffmanTree)
1325
        );
1326
    }
1327
1328
    /// This is a regression test found by the `inflate_bytewise3` fuzzer from the `fdeflate`
1329
    /// crate.  When this test case was found, the results were unexpectedly different when 1)
1330
    /// decompressing the whole input (`Err(InvalidDistanceCode)`) vs 2) decompressing byte-by-byte
1331
    /// (successful result)`).
1332
    #[test]
1333
    fn test_input_chunking_sensitivity_when_no_end_of_block_symbol_example2() {
1334
        let err = verify_no_sensitivity_to_input_chunking(include_bytes!(
1335
            "../tests/input-chunking-sensitivity-example3.zz"
1336
        ))
1337
        .unwrap_err();
1338
        assert_eq!(
1339
            err,
1340
            TestDecompressionError::ProdError(DecompressionError::BadLiteralLengthHuffmanTree)
1341
        );
1342
    }
1343
}