Coverage Report

Created: 2025-10-14 06:57

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
16.0k
    pub fn new() -> Self {
121
16.0k
        Self {
122
16.0k
            buffer: 0,
123
16.0k
            nbits: 0,
124
16.0k
            compression: CompressedBlock {
125
16.0k
                litlen_table: Box::new([0; 4096]),
126
16.0k
                dist_table: Box::new([0; 512]),
127
16.0k
                secondary_table: Vec::new(),
128
16.0k
                dist_secondary_table: Vec::new(),
129
16.0k
                eof_code: 0,
130
16.0k
                eof_mask: 0,
131
16.0k
                eof_bits: 0,
132
16.0k
            },
133
16.0k
            header: BlockHeader {
134
16.0k
                hlit: 0,
135
16.0k
                hdist: 0,
136
16.0k
                hclen: 0,
137
16.0k
                table: [0; 128],
138
16.0k
                num_lengths_read: 0,
139
16.0k
                code_lengths: [0; 320],
140
16.0k
            },
141
16.0k
            uncompressed_bytes_left: 0,
142
16.0k
            queued_rle: None,
143
16.0k
            queued_backref: None,
144
16.0k
            checksum: Adler32::new(),
145
16.0k
            state: State::ZlibHeader,
146
16.0k
            last_block: false,
147
16.0k
            ignore_adler32: false,
148
16.0k
            fixed_table: false,
149
16.0k
        }
150
16.0k
    }
151
152
    /// Ignore the checksum at the end of the stream.
153
7.42k
    pub fn ignore_adler32(&mut self) {
154
7.42k
        self.ignore_adler32 = true;
155
7.42k
    }
156
157
126M
    fn fill_buffer(&mut self, input: &mut &[u8]) {
158
126M
        if input.len() >= 8 {
159
126M
            self.buffer |= u64::from_le_bytes(input[..8].try_into().unwrap()) << self.nbits;
160
126M
            *input = &input[(63 - self.nbits as usize) / 8..];
161
126M
            self.nbits |= 56;
162
126M
        } else {
163
159k
            let nbytes = input.len().min((63 - self.nbits as usize) / 8);
164
159k
            let mut input_data = [0; 8];
165
159k
            input_data[..nbytes].copy_from_slice(&input[..nbytes]);
166
159k
            self.buffer |= u64::from_le_bytes(input_data)
167
159k
                .checked_shl(self.nbits as u32)
168
159k
                .unwrap_or(0);
169
159k
            self.nbits += nbytes as u8 * 8;
170
159k
            *input = &input[nbytes..];
171
159k
        }
172
126M
    }
173
174
2.37M
    fn peak_bits(&mut self, nbits: u8) -> u64 {
175
2.37M
        debug_assert!(nbits <= 56 && nbits <= self.nbits);
176
2.37M
        self.buffer & ((1u64 << nbits) - 1)
177
2.37M
    }
178
122M
    fn consume_bits(&mut self, nbits: u8) {
179
122M
        debug_assert!(self.nbits >= nbits);
180
122M
        self.buffer >>= nbits;
181
122M
        self.nbits -= nbits;
182
122M
    }
183
184
119k
    fn read_block_header(&mut self, remaining_input: &mut &[u8]) -> Result<(), DecompressionError> {
185
119k
        self.fill_buffer(remaining_input);
186
119k
        if self.nbits < 10 {
187
1.03k
            return Ok(());
188
118k
        }
189
190
118k
        let start = self.peak_bits(3);
191
118k
        self.last_block = start & 1 != 0;
192
118k
        match start >> 1 {
193
            0b00 => {
194
13.8k
                let align_bits = (self.nbits - 3) % 8;
195
13.8k
                let header_bits = 3 + 32 + align_bits;
196
13.8k
                if self.nbits < header_bits {
197
203
                    return Ok(());
198
13.6k
                }
199
200
13.6k
                let len = (self.peak_bits(align_bits + 19) >> (align_bits + 3)) as u16;
201
13.6k
                let nlen = (self.peak_bits(header_bits) >> (align_bits + 19)) as u16;
202
13.6k
                if nlen != !len {
203
219
                    return Err(DecompressionError::InvalidUncompressedBlockLength);
204
13.3k
                }
205
206
13.3k
                self.state = State::UncompressedData;
207
13.3k
                self.uncompressed_bytes_left = len;
208
13.3k
                self.consume_bits(header_bits);
209
13.3k
                Ok(())
210
            }
211
            0b01 => {
212
83.7k
                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
83.7k
                if self.peak_bits(7) == 0 {
218
26.5k
                    self.consume_bits(7);
219
26.5k
                    if self.last_block {
220
31
                        self.state = State::Checksum;
221
31
                        return Ok(());
222
26.4k
                    }
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
52.8k
                    while self.nbits >= 10 && self.peak_bits(10) == 0b010 {
230
26.3k
                        self.consume_bits(10);
231
26.3k
                        self.fill_buffer(remaining_input);
232
26.3k
                    }
233
26.4k
                    return self.read_block_header(remaining_input);
234
57.2k
                }
235
236
                // Build decoding tables if the previous block wasn't also a fixed block.
237
57.2k
                if !self.fixed_table {
238
12.0k
                    self.fixed_table = true;
239
96.4k
                    for chunk in self.compression.litlen_table.chunks_exact_mut(512) {
240
96.4k
                        chunk.copy_from_slice(&FIXED_LITLEN_TABLE);
241
96.4k
                    }
242
192k
                    for chunk in self.compression.dist_table.chunks_exact_mut(32) {
243
192k
                        chunk.copy_from_slice(&FIXED_DIST_TABLE);
244
192k
                    }
245
12.0k
                    self.compression.eof_bits = 7;
246
12.0k
                    self.compression.eof_code = 0;
247
12.0k
                    self.compression.eof_mask = 0x7f;
248
45.1k
                }
249
250
57.2k
                self.state = State::CompressedData;
251
57.2k
                Ok(())
252
            }
253
            0b10 => {
254
20.9k
                if self.nbits < 17 {
255
175
                    return Ok(());
256
20.7k
                }
257
258
20.7k
                self.header.hlit = (self.peak_bits(8) >> 3) as usize + 257;
259
20.7k
                self.header.hdist = (self.peak_bits(13) >> 8) as usize + 1;
260
20.7k
                self.header.hclen = (self.peak_bits(17) >> 13) as usize + 4;
261
20.7k
                if self.header.hlit > 286 {
262
18
                    return Err(DecompressionError::InvalidHlit);
263
20.7k
                }
264
20.7k
                if self.header.hdist > 30 {
265
7
                    return Err(DecompressionError::InvalidHdist);
266
20.7k
                }
267
268
20.7k
                self.consume_bits(17);
269
20.7k
                self.state = State::CodeLengthCodes;
270
20.7k
                self.fixed_table = false;
271
20.7k
                Ok(())
272
            }
273
63
            0b11 => Err(DecompressionError::InvalidBlockType),
274
0
            _ => unreachable!(),
275
        }
276
119k
    }
277
278
21.0k
    fn read_code_length_codes(
279
21.0k
        &mut self,
280
21.0k
        remaining_input: &mut &[u8],
281
21.0k
    ) -> Result<(), DecompressionError> {
282
21.0k
        self.fill_buffer(remaining_input);
283
21.0k
        if self.nbits as usize + remaining_input.len() * 8 < 3 * self.header.hclen {
284
409
            return Ok(());
285
20.6k
        }
286
287
20.6k
        let mut code_length_lengths = [0; 19];
288
370k
        for i in 0..self.header.hclen {
289
370k
            code_length_lengths[CLCL_ORDER[i]] = self.peak_bits(3) as u8;
290
370k
            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
370k
            if i == 17 {
295
17.0k
                self.fill_buffer(remaining_input);
296
353k
            }
297
        }
298
299
20.6k
        let mut codes = [0; 19];
300
20.6k
        if !build_table(
301
20.6k
            &code_length_lengths,
302
20.6k
            &[],
303
20.6k
            &mut codes,
304
20.6k
            &mut self.header.table,
305
20.6k
            &mut Vec::new(),
306
20.6k
            false,
307
20.6k
            false,
308
20.6k
        ) {
309
207
            return Err(DecompressionError::BadCodeLengthHuffmanTree);
310
20.4k
        }
311
312
20.4k
        self.state = State::CodeLengths;
313
20.4k
        self.header.num_lengths_read = 0;
314
20.4k
        Ok(())
315
21.0k
    }
316
317
21.3k
    fn read_code_lengths(&mut self, remaining_input: &mut &[u8]) -> Result<(), DecompressionError> {
318
21.3k
        let total_lengths = self.header.hlit + self.header.hdist;
319
1.42M
        while self.header.num_lengths_read < total_lengths {
320
1.40M
            self.fill_buffer(remaining_input);
321
1.40M
            if self.nbits < 7 {
322
821
                return Ok(());
323
1.40M
            }
324
325
1.40M
            let code = self.peak_bits(7);
326
1.40M
            let entry = self.header.table[code as usize];
327
1.40M
            let length = (entry & 0x7) as u8;
328
1.40M
            let symbol = (entry >> 16) as u8;
329
330
1.40M
            debug_assert!(length != 0);
331
1.40M
            match symbol {
332
1.40M
                0..=15 => {
333
1.18M
                    self.header.code_lengths[self.header.num_lengths_read] = symbol;
334
1.18M
                    self.header.num_lengths_read += 1;
335
1.18M
                    self.consume_bits(length);
336
1.18M
                }
337
213k
                16..=18 => {
338
213k
                    let (base_repeat, extra_bits) = match symbol {
339
65.9k
                        16 => (3, 2),
340
92.6k
                        17 => (3, 3),
341
54.7k
                        18 => (11, 7),
342
0
                        _ => unreachable!(),
343
                    };
344
345
213k
                    if self.nbits < length + extra_bits {
346
303
                        return Ok(());
347
213k
                    }
348
349
213k
                    let value = match symbol {
350
                        16 => {
351
65.9k
                            self.header.code_lengths[self
352
65.9k
                                .header
353
65.9k
                                .num_lengths_read
354
65.9k
                                .checked_sub(1)
355
65.9k
                                .ok_or(DecompressionError::InvalidCodeLengthRepeat)?]
356
                            // TODO: is this right?
357
                        }
358
92.6k
                        17 => 0,
359
54.5k
                        18 => 0,
360
0
                        _ => unreachable!(),
361
                    };
362
363
213k
                    let repeat =
364
213k
                        (self.peak_bits(length + extra_bits) >> length) as usize + base_repeat;
365
213k
                    if self.header.num_lengths_read + repeat > total_lengths {
366
85
                        return Err(DecompressionError::InvalidCodeLengthRepeat);
367
212k
                    }
368
369
4.80M
                    for i in 0..repeat {
370
4.80M
                        self.header.code_lengths[self.header.num_lengths_read + i] = value;
371
4.80M
                    }
372
212k
                    self.header.num_lengths_read += repeat;
373
212k
                    self.consume_bits(length + extra_bits);
374
                }
375
0
                _ => unreachable!(),
376
            }
377
        }
378
379
20.1k
        self.header
380
20.1k
            .code_lengths
381
20.1k
            .copy_within(self.header.hlit..total_lengths, 288);
382
220k
        for i in self.header.hlit..288 {
383
220k
            self.header.code_lengths[i] = 0;
384
220k
        }
385
268k
        for i in 288 + self.header.hdist..320 {
386
268k
            self.header.code_lengths[i] = 0;
387
268k
        }
388
389
20.1k
        Self::build_tables(
390
20.1k
            self.header.hlit,
391
20.1k
            &self.header.code_lengths,
392
20.1k
            &mut self.compression,
393
391
        )?;
394
19.7k
        self.state = State::CompressedData;
395
19.7k
        Ok(())
396
21.3k
    }
397
398
20.1k
    fn build_tables(
399
20.1k
        hlit: usize,
400
20.1k
        code_lengths: &[u8],
401
20.1k
        compression: &mut CompressedBlock,
402
20.1k
    ) -> Result<(), DecompressionError> {
403
        // If there is no code assigned for the EOF symbol then the bitstream is invalid.
404
20.1k
        if code_lengths[256] == 0 {
405
            // TODO: Return a dedicated error in this case.
406
32
            return Err(DecompressionError::BadLiteralLengthHuffmanTree);
407
20.0k
        }
408
409
20.0k
        let mut codes = [0; 288];
410
20.0k
        compression.secondary_table.clear();
411
20.0k
        if !huffman::build_table(
412
20.0k
            &code_lengths[..hlit],
413
20.0k
            &LITLEN_TABLE_ENTRIES,
414
20.0k
            &mut codes[..hlit],
415
20.0k
            &mut *compression.litlen_table,
416
20.0k
            &mut compression.secondary_table,
417
20.0k
            false,
418
20.0k
            true,
419
20.0k
        ) {
420
146
            return Err(DecompressionError::BadCodeLengthHuffmanTree);
421
19.9k
        }
422
423
19.9k
        compression.eof_code = codes[256];
424
19.9k
        compression.eof_mask = (1 << code_lengths[256]) - 1;
425
19.9k
        compression.eof_bits = code_lengths[256];
426
427
        // Build the distance code table.
428
19.9k
        let lengths = &code_lengths[288..320];
429
19.9k
        if lengths == [0; 32] {
430
4.11k
            compression.dist_table.fill(0);
431
4.11k
        } else {
432
15.8k
            let mut dist_codes = [0; 32];
433
15.8k
            if !huffman::build_table(
434
15.8k
                lengths,
435
15.8k
                &tables::DISTANCE_TABLE_ENTRIES,
436
15.8k
                &mut dist_codes,
437
15.8k
                &mut *compression.dist_table,
438
15.8k
                &mut compression.dist_secondary_table,
439
15.8k
                true,
440
15.8k
                false,
441
15.8k
            ) {
442
213
                return Err(DecompressionError::BadDistanceHuffmanTree);
443
15.6k
            }
444
        }
445
446
19.7k
        Ok(())
447
20.1k
    }
448
449
2.72M
    fn read_compressed(
450
2.72M
        &mut self,
451
2.72M
        remaining_input: &mut &[u8],
452
2.72M
        output: &mut [u8],
453
2.72M
        mut output_index: usize,
454
2.72M
    ) -> 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
2.72M
        self.fill_buffer(remaining_input);
468
2.72M
        let mut litlen_entry = self.compression.litlen_table[(self.buffer & 0xfff) as usize];
469
118M
        while self.state == State::CompressedData
470
118M
            && output_index + 8 <= output.len()
471
118M
            && 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
118M
            let mut litlen_code_bits = litlen_entry as u8;
477
118M
            if litlen_entry & LITERAL_ENTRY != 0 {
478
20.0M
                let litlen_entry2 = self.compression.litlen_table
479
20.0M
                    [(self.buffer >> litlen_code_bits & 0xfff) as usize];
480
20.0M
                let litlen_code_bits2 = litlen_entry2 as u8;
481
20.0M
                let litlen_entry3 = self.compression.litlen_table
482
20.0M
                    [(self.buffer >> (litlen_code_bits + litlen_code_bits2) & 0xfff) as usize];
483
20.0M
                let litlen_code_bits3 = litlen_entry3 as u8;
484
20.0M
                let litlen_entry4 = self.compression.litlen_table[(self.buffer
485
20.0M
                    >> (litlen_code_bits + litlen_code_bits2 + litlen_code_bits3)
486
20.0M
                    & 0xfff)
487
20.0M
                    as usize];
488
489
20.0M
                let advance_output_bytes = ((litlen_entry & 0xf00) >> 8) as usize;
490
20.0M
                output[output_index] = (litlen_entry >> 16) as u8;
491
20.0M
                output[output_index + 1] = (litlen_entry >> 24) as u8;
492
20.0M
                output_index += advance_output_bytes;
493
494
20.0M
                if litlen_entry2 & LITERAL_ENTRY != 0 {
495
18.6M
                    let advance_output_bytes2 = ((litlen_entry2 & 0xf00) >> 8) as usize;
496
18.6M
                    output[output_index] = (litlen_entry2 >> 16) as u8;
497
18.6M
                    output[output_index + 1] = (litlen_entry2 >> 24) as u8;
498
18.6M
                    output_index += advance_output_bytes2;
499
500
18.6M
                    if litlen_entry3 & LITERAL_ENTRY != 0 {
501
18.3M
                        let advance_output_bytes3 = ((litlen_entry3 & 0xf00) >> 8) as usize;
502
18.3M
                        output[output_index] = (litlen_entry3 >> 16) as u8;
503
18.3M
                        output[output_index + 1] = (litlen_entry3 >> 24) as u8;
504
18.3M
                        output_index += advance_output_bytes3;
505
506
18.3M
                        litlen_entry = litlen_entry4;
507
18.3M
                        self.consume_bits(litlen_code_bits + litlen_code_bits2 + litlen_code_bits3);
508
18.3M
                        self.fill_buffer(remaining_input);
509
18.3M
                        continue;
510
317k
                    } else {
511
317k
                        self.consume_bits(litlen_code_bits + litlen_code_bits2);
512
317k
                        litlen_entry = litlen_entry3;
513
317k
                        litlen_code_bits = litlen_code_bits3;
514
317k
                        self.fill_buffer(remaining_input);
515
317k
                        bits = self.buffer;
516
317k
                    }
517
                } else {
518
1.39M
                    self.consume_bits(litlen_code_bits);
519
1.39M
                    bits = self.buffer;
520
1.39M
                    litlen_entry = litlen_entry2;
521
1.39M
                    litlen_code_bits = litlen_code_bits2;
522
1.39M
                    if self.nbits < 48 {
523
60.2k
                        self.fill_buffer(remaining_input);
524
1.33M
                    }
525
                }
526
98.8M
            } else {
527
98.8M
                bits = self.buffer;
528
98.8M
            }
529
530
            // The next symbol is either a 13+ bit literal, back-reference, or an EOF symbol.
531
100M
            let (length_base, length_extra_bits, litlen_code_bits) =
532
100M
                if litlen_entry & EXCEPTIONAL_ENTRY == 0 {
533
100M
                    (
534
100M
                        litlen_entry >> 16,
535
100M
                        (litlen_entry >> 8) as u8,
536
100M
                        litlen_code_bits,
537
100M
                    )
538
235k
                } else if litlen_entry & SECONDARY_TABLE_ENTRY != 0 {
539
167k
                    let secondary_table_index =
540
167k
                        (litlen_entry >> 16) + ((bits >> 12) as u32 & (litlen_entry & 0xff));
541
167k
                    let secondary_entry =
542
167k
                        self.compression.secondary_table[secondary_table_index as usize];
543
167k
                    let litlen_symbol = secondary_entry >> 4;
544
167k
                    let litlen_code_bits = (secondary_entry & 0xf) as u8;
545
546
167k
                    match litlen_symbol {
547
167k
                        0..=255 => {
548
83.8k
                            self.consume_bits(litlen_code_bits);
549
83.8k
                            litlen_entry =
550
83.8k
                                self.compression.litlen_table[(self.buffer & 0xfff) as usize];
551
83.8k
                            self.fill_buffer(remaining_input);
552
83.8k
                            output[output_index] = litlen_symbol as u8;
553
83.8k
                            output_index += 1;
554
83.8k
                            continue;
555
                        }
556
                        256 => {
557
2.46k
                            self.consume_bits(litlen_code_bits);
558
2.46k
                            self.state = match self.last_block {
559
2
                                true => State::Checksum,
560
2.46k
                                false => State::BlockHeader,
561
                            };
562
2.46k
                            break;
563
                        }
564
80.7k
                        _ => (
565
80.7k
                            LEN_SYM_TO_LEN_BASE[litlen_symbol as usize - 257] as u32,
566
80.7k
                            LEN_SYM_TO_LEN_EXTRA[litlen_symbol as usize - 257],
567
80.7k
                            litlen_code_bits,
568
80.7k
                        ),
569
                    }
570
68.3k
                } else if litlen_code_bits == 0 {
571
0
                    return Err(DecompressionError::InvalidLiteralLengthCode);
572
                } else {
573
68.3k
                    self.consume_bits(litlen_code_bits);
574
68.3k
                    self.state = match self.last_block {
575
1.11k
                        true => State::Checksum,
576
67.2k
                        false => State::BlockHeader,
577
                    };
578
68.3k
                    break;
579
                };
580
100M
            bits >>= litlen_code_bits;
581
582
100M
            let length_extra_mask = (1 << length_extra_bits) - 1;
583
100M
            let length = length_base as usize + (bits & length_extra_mask) as usize;
584
100M
            bits >>= length_extra_bits;
585
586
100M
            let dist_entry = self.compression.dist_table[(bits & 0x1ff) as usize];
587
100M
            let (dist_base, dist_extra_bits, dist_code_bits) = if dist_entry & LITERAL_ENTRY != 0 {
588
99.7M
                (
589
99.7M
                    (dist_entry >> 16) as u16,
590
99.7M
                    (dist_entry >> 8) as u8 & 0xf,
591
99.7M
                    dist_entry as u8,
592
99.7M
                )
593
626k
            } else if dist_entry >> 8 == 0 {
594
48
                return Err(DecompressionError::InvalidDistanceCode);
595
            } else {
596
626k
                let secondary_table_index =
597
626k
                    (dist_entry >> 16) + ((bits >> 9) as u32 & (dist_entry & 0xff));
598
626k
                let secondary_entry =
599
626k
                    self.compression.dist_secondary_table[secondary_table_index as usize];
600
626k
                let dist_symbol = (secondary_entry >> 4) as usize;
601
626k
                if dist_symbol >= 30 {
602
0
                    return Err(DecompressionError::InvalidDistanceCode);
603
626k
                }
604
605
626k
                (
606
626k
                    DIST_SYM_TO_DIST_BASE[dist_symbol],
607
626k
                    DIST_SYM_TO_DIST_EXTRA[dist_symbol],
608
626k
                    (secondary_entry & 0xf) as u8,
609
626k
                )
610
            };
611
100M
            bits >>= dist_code_bits;
612
613
100M
            let dist = dist_base as usize + (bits & ((1 << dist_extra_bits) - 1)) as usize;
614
100M
            if dist > output_index {
615
118
                return Err(DecompressionError::DistanceTooFarBack);
616
100M
            }
617
618
100M
            self.consume_bits(
619
100M
                litlen_code_bits + length_extra_bits + dist_code_bits + dist_extra_bits,
620
            );
621
100M
            self.fill_buffer(remaining_input);
622
100M
            litlen_entry = self.compression.litlen_table[(self.buffer & 0xfff) as usize];
623
624
100M
            let copy_length = length.min(output.len() - output_index);
625
100M
            if dist == 1 {
626
60.5M
                let last = output[output_index - 1];
627
60.5M
                output[output_index..][..copy_length].fill(last);
628
629
60.5M
                if copy_length < length {
630
1.61M
                    self.queued_rle = Some((last, length - copy_length));
631
1.61M
                    output_index = output.len();
632
1.61M
                    break;
633
58.8M
                }
634
39.8M
            } else if output_index + length + 15 <= output.len() {
635
38.8M
                let start = output_index - dist;
636
38.8M
                output.copy_within(start..start + 16, output_index);
637
638
38.8M
                if length > 16 || dist < 16 {
639
2.18G
                    for i in (0..length).step_by(dist.min(16)).skip(1) {
640
2.18G
                        output.copy_within(start + i..start + i + 16, output_index + i);
641
2.18G
                    }
642
2.48M
                }
643
            } else {
644
989k
                if dist < copy_length {
645
108M
                    for i in 0..copy_length {
646
108M
                        output[output_index + i] = output[output_index + i - dist];
647
108M
                    }
648
                } else {
649
210k
                    output.copy_within(
650
210k
                        output_index - dist..output_index + copy_length - dist,
651
210k
                        output_index,
652
                    )
653
                }
654
655
989k
                if copy_length < length {
656
924k
                    self.queued_backref = Some((dist, length - copy_length));
657
924k
                    output_index = output.len();
658
924k
                    break;
659
65.8k
                }
660
            }
661
97.8M
            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
2.85M
        while let State::CompressedData = self.state {
669
2.78M
            self.fill_buffer(remaining_input);
670
2.78M
            if output_index == output.len() {
671
2.55M
                break;
672
224k
            }
673
674
224k
            let mut bits = self.buffer;
675
224k
            let litlen_entry = self.compression.litlen_table[(bits & 0xfff) as usize];
676
224k
            let litlen_code_bits = litlen_entry as u8;
677
678
224k
            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
76.3k
                let advance_output_bytes = ((litlen_entry & 0xf00) >> 8) as usize;
682
683
76.3k
                if self.nbits < litlen_code_bits {
684
4.32k
                    break;
685
71.9k
                } else if output_index + 1 < output.len() {
686
66.1k
                    output[output_index] = (litlen_entry >> 16) as u8;
687
66.1k
                    output[output_index + 1] = (litlen_entry >> 24) as u8;
688
66.1k
                    output_index += advance_output_bytes;
689
66.1k
                    self.consume_bits(litlen_code_bits);
690
66.1k
                    continue;
691
5.85k
                } else if output_index + advance_output_bytes == output.len() {
692
904
                    debug_assert_eq!(advance_output_bytes, 1);
693
904
                    output[output_index] = (litlen_entry >> 16) as u8;
694
904
                    output_index += 1;
695
904
                    self.consume_bits(litlen_code_bits);
696
904
                    break;
697
                } else {
698
4.94k
                    debug_assert_eq!(advance_output_bytes, 2);
699
4.94k
                    output[output_index] = (litlen_entry >> 16) as u8;
700
4.94k
                    self.queued_rle = Some(((litlen_entry >> 24) as u8, 1));
701
4.94k
                    output_index += 1;
702
4.94k
                    self.consume_bits(litlen_code_bits);
703
4.94k
                    break;
704
                }
705
147k
            }
706
707
143k
            let (length_base, length_extra_bits, litlen_code_bits) =
708
147k
                if litlen_entry & EXCEPTIONAL_ENTRY == 0 {
709
143k
                    (
710
143k
                        litlen_entry >> 16,
711
143k
                        (litlen_entry >> 8) as u8,
712
143k
                        litlen_code_bits,
713
143k
                    )
714
4.40k
                } else if litlen_entry & SECONDARY_TABLE_ENTRY != 0 {
715
864
                    let secondary_table_index =
716
864
                        (litlen_entry >> 16) + ((bits >> 12) as u32 & (litlen_entry & 0xff));
717
864
                    let secondary_entry =
718
864
                        self.compression.secondary_table[secondary_table_index as usize];
719
864
                    let litlen_symbol = secondary_entry >> 4;
720
864
                    let litlen_code_bits = (secondary_entry & 0xf) as u8;
721
722
864
                    if self.nbits < litlen_code_bits {
723
26
                        break;
724
838
                    } else if litlen_symbol < 256 {
725
535
                        self.consume_bits(litlen_code_bits);
726
535
                        output[output_index] = litlen_symbol as u8;
727
535
                        output_index += 1;
728
535
                        continue;
729
303
                    } else if litlen_symbol == 256 {
730
26
                        self.consume_bits(litlen_code_bits);
731
26
                        self.state = match self.last_block {
732
2
                            true => State::Checksum,
733
24
                            false => State::BlockHeader,
734
                        };
735
26
                        break;
736
277
                    }
737
738
277
                    (
739
277
                        LEN_SYM_TO_LEN_BASE[litlen_symbol as usize - 257] as u32,
740
277
                        LEN_SYM_TO_LEN_EXTRA[litlen_symbol as usize - 257],
741
277
                        litlen_code_bits,
742
277
                    )
743
3.54k
                } else if litlen_code_bits == 0 {
744
0
                    return Err(DecompressionError::InvalidLiteralLengthCode);
745
                } else {
746
3.54k
                    if self.nbits < litlen_code_bits {
747
503
                        break;
748
3.03k
                    }
749
3.03k
                    self.consume_bits(litlen_code_bits);
750
3.03k
                    self.state = match self.last_block {
751
2.15k
                        true => State::Checksum,
752
886
                        false => State::BlockHeader,
753
                    };
754
3.03k
                    break;
755
                };
756
143k
            bits >>= litlen_code_bits;
757
758
143k
            let length_extra_mask = (1 << length_extra_bits) - 1;
759
143k
            let length = length_base as usize + (bits & length_extra_mask) as usize;
760
143k
            bits >>= length_extra_bits;
761
762
143k
            let dist_entry = self.compression.dist_table[(bits & 0x1ff) as usize];
763
143k
            let (dist_base, dist_extra_bits, dist_code_bits) = if dist_entry & LITERAL_ENTRY != 0 {
764
142k
                (
765
142k
                    (dist_entry >> 16) as u16,
766
142k
                    (dist_entry >> 8) as u8 & 0xf,
767
142k
                    dist_entry as u8,
768
142k
                )
769
1.34k
            } else if self.nbits > litlen_code_bits + length_extra_bits + 9 {
770
1.17k
                if dist_entry >> 8 == 0 {
771
56
                    return Err(DecompressionError::InvalidDistanceCode);
772
1.11k
                }
773
774
1.11k
                let secondary_table_index =
775
1.11k
                    (dist_entry >> 16) + ((bits >> 9) as u32 & (dist_entry & 0xff));
776
1.11k
                let secondary_entry =
777
1.11k
                    self.compression.dist_secondary_table[secondary_table_index as usize];
778
1.11k
                let dist_symbol = (secondary_entry >> 4) as usize;
779
1.11k
                if dist_symbol >= 30 {
780
0
                    return Err(DecompressionError::InvalidDistanceCode);
781
1.11k
                }
782
783
1.11k
                (
784
1.11k
                    DIST_SYM_TO_DIST_BASE[dist_symbol],
785
1.11k
                    DIST_SYM_TO_DIST_EXTRA[dist_symbol],
786
1.11k
                    (secondary_entry & 0xf) as u8,
787
1.11k
                )
788
            } else {
789
172
                break;
790
            };
791
143k
            bits >>= dist_code_bits;
792
793
143k
            let dist = dist_base as usize + (bits & ((1 << dist_extra_bits) - 1)) as usize;
794
143k
            let total_bits =
795
143k
                litlen_code_bits + length_extra_bits + dist_code_bits + dist_extra_bits;
796
797
143k
            if self.nbits < total_bits {
798
2.89k
                break;
799
140k
            } else if dist > output_index {
800
172
                return Err(DecompressionError::DistanceTooFarBack);
801
140k
            }
802
803
140k
            self.consume_bits(total_bits);
804
805
140k
            let copy_length = length.min(output.len() - output_index);
806
140k
            if dist == 1 {
807
65.1k
                let last = output[output_index - 1];
808
65.1k
                output[output_index..][..copy_length].fill(last);
809
810
65.1k
                if copy_length < length {
811
47.4k
                    self.queued_rle = Some((last, length - copy_length));
812
47.4k
                    output_index = output.len();
813
47.4k
                    break;
814
17.6k
                }
815
75.1k
            } else if output_index + length + 15 <= output.len() {
816
42.4k
                let start = output_index - dist;
817
42.4k
                output.copy_within(start..start + 16, output_index);
818
819
42.4k
                if length > 16 || dist < 16 {
820
2.95M
                    for i in (0..length).step_by(dist.min(16)).skip(1) {
821
2.95M
                        output.copy_within(start + i..start + i + 16, output_index + i);
822
2.95M
                    }
823
1.75k
                }
824
            } else {
825
32.6k
                if dist < copy_length {
826
235k
                    for i in 0..copy_length {
827
235k
                        output[output_index + i] = output[output_index + i - dist];
828
235k
                    }
829
                } else {
830
19.7k
                    output.copy_within(
831
19.7k
                        output_index - dist..output_index + copy_length - dist,
832
19.7k
                        output_index,
833
                    )
834
                }
835
836
32.6k
                if copy_length < length {
837
31.5k
                    self.queued_backref = Some((dist, length - copy_length));
838
31.5k
                    output_index = output.len();
839
31.5k
                    break;
840
1.12k
                }
841
            }
842
61.2k
            output_index += copy_length;
843
        }
844
845
2.72M
        if self.state == State::CompressedData
846
2.65M
            && self.queued_backref.is_none()
847
1.69M
            && self.queued_rle.is_none()
848
25.7k
            && self.nbits >= 15
849
18.2k
            && self.peak_bits(15) as u16 & self.compression.eof_mask == self.compression.eof_code
850
        {
851
48
            self.consume_bits(self.compression.eof_bits);
852
48
            self.state = match self.last_block {
853
8
                true => State::Checksum,
854
40
                false => State::BlockHeader,
855
            };
856
2.72M
        }
857
858
2.72M
        Ok(output_index)
859
2.72M
    }
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
2.66M
    pub fn read(
880
2.66M
        &mut self,
881
2.66M
        input: &[u8],
882
2.66M
        output: &mut [u8],
883
2.66M
        output_position: usize,
884
2.66M
        end_of_input: bool,
885
2.66M
    ) -> Result<(usize, usize), DecompressionError> {
886
2.66M
        if let State::Done = self.state {
887
0
            return Ok((0, 0));
888
2.66M
        }
889
890
2.66M
        assert!(output_position <= output.len());
891
892
2.66M
        let mut remaining_input = input;
893
2.66M
        let mut output_index = output_position;
894
895
2.66M
        if let Some((data, len)) = self.queued_rle.take() {
896
1.66M
            let n = len.min(output.len() - output_index);
897
1.66M
            output[output_index..][..n].fill(data);
898
1.66M
            output_index += n;
899
1.66M
            if n < len {
900
0
                self.queued_rle = Some((data, len - n));
901
0
                return Ok((0, n));
902
1.66M
            }
903
992k
        }
904
2.66M
        if let Some((dist, len)) = self.queued_backref.take() {
905
955k
            let n = len.min(output.len() - output_index);
906
121M
            for i in 0..n {
907
121M
                output[output_index + i] = output[output_index + i - dist];
908
121M
            }
909
955k
            output_index += n;
910
955k
            if n < len {
911
0
                self.queued_backref = Some((dist, len - n));
912
0
                return Ok((0, n));
913
955k
            }
914
1.70M
        }
915
916
        // Main decoding state machine.
917
2.66M
        let mut last_state = None;
918
5.54M
        while last_state != Some(self.state) {
919
2.88M
            last_state = Some(self.state);
920
2.88M
            match self.state {
921
                State::ZlibHeader => {
922
10.2k
                    self.fill_buffer(&mut remaining_input);
923
10.2k
                    if self.nbits < 16 {
924
2.17k
                        break;
925
8.10k
                    }
926
927
8.10k
                    let input0 = self.peak_bits(8);
928
8.10k
                    let input1 = self.peak_bits(16) >> 8 & 0xff;
929
8.10k
                    if input0 & 0x0f != 0x08
930
8.04k
                        || (input0 & 0xf0) > 0x70
931
8.03k
                        || input1 & 0x20 != 0
932
8.02k
                        || (input0 << 8 | input1) % 31 != 0
933
                    {
934
101
                        return Err(DecompressionError::BadZlibHeader);
935
8.00k
                    }
936
937
8.00k
                    self.consume_bits(16);
938
8.00k
                    self.state = State::BlockHeader;
939
                }
940
                State::BlockHeader => {
941
93.0k
                    self.read_block_header(&mut remaining_input)?;
942
                }
943
                State::CodeLengthCodes => {
944
21.0k
                    self.read_code_length_codes(&mut remaining_input)?;
945
                }
946
                State::CodeLengths => {
947
21.3k
                    self.read_code_lengths(&mut remaining_input)?;
948
                }
949
                State::CompressedData => {
950
                    output_index =
951
2.72M
                        self.read_compressed(&mut remaining_input, output, output_index)?
952
                }
953
                State::UncompressedData => {
954
                    // Drain any bytes from our buffer.
955
14.4k
                    debug_assert_eq!(self.nbits % 8, 0);
956
26.1k
                    while self.nbits > 0
957
20.6k
                        && self.uncompressed_bytes_left > 0
958
11.7k
                        && output_index < output.len()
959
11.6k
                    {
960
11.6k
                        output[output_index] = self.peak_bits(8) as u8;
961
11.6k
                        self.consume_bits(8);
962
11.6k
                        output_index += 1;
963
11.6k
                        self.uncompressed_bytes_left -= 1;
964
11.6k
                    }
965
                    // Buffer may contain one additional byte. Clear it to avoid confusion.
966
14.4k
                    if self.nbits == 0 {
967
5.48k
                        self.buffer = 0;
968
8.95k
                    }
969
970
                    // Copy subsequent bytes directly from the input.
971
14.4k
                    let copy_bytes = (self.uncompressed_bytes_left as usize)
972
14.4k
                        .min(remaining_input.len())
973
14.4k
                        .min(output.len() - output_index);
974
14.4k
                    output[output_index..][..copy_bytes]
975
14.4k
                        .copy_from_slice(&remaining_input[..copy_bytes]);
976
14.4k
                    remaining_input = &remaining_input[copy_bytes..];
977
14.4k
                    output_index += copy_bytes;
978
14.4k
                    self.uncompressed_bytes_left -= copy_bytes as u16;
979
980
14.4k
                    if self.uncompressed_bytes_left == 0 {
981
13.2k
                        self.state = if self.last_block {
982
1
                            State::Checksum
983
                        } else {
984
13.2k
                            State::BlockHeader
985
                        };
986
1.16k
                    }
987
                }
988
                State::Checksum => {
989
3.68k
                    self.fill_buffer(&mut remaining_input);
990
991
3.68k
                    let align_bits = self.nbits % 8;
992
3.68k
                    if self.nbits >= 32 + align_bits {
993
3.19k
                        self.checksum.write(&output[output_position..output_index]);
994
3.19k
                        if align_bits != 0 {
995
2.77k
                            self.consume_bits(align_bits);
996
2.77k
                        }
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
3.19k
                        self.state = State::Done;
1004
3.19k
                        self.consume_bits(32);
1005
3.19k
                        break;
1006
482
                    }
1007
                }
1008
0
                State::Done => unreachable!(),
1009
            }
1010
        }
1011
1012
2.66M
        if !self.ignore_adler32 && self.state != State::Done {
1013
97.1k
            self.checksum.write(&output[output_position..output_index]);
1014
2.56M
        }
1015
1016
2.66M
        if self.state == State::Done || !end_of_input || output_index == output.len() {
1017
2.65M
            let input_left = remaining_input.len();
1018
2.65M
            Ok((input.len() - input_left, output_index - output_position))
1019
        } else {
1020
726
            Err(DecompressionError::InsufficientInput)
1021
        }
1022
2.66M
    }
1023
1024
    /// Returns true if the decompressor has finished decompressing the input.
1025
5.22M
    pub fn is_done(&self) -> bool {
1026
5.22M
        self.state == State::Done
1027
5.22M
    }
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
570
    fn from(inner: DecompressionError) -> Self {
1057
570
        BoundedDecompressionError::DecompressionError { inner }
1058
570
    }
1059
}
1060
1061
/// Decompress the given data, returning an error if the output is larger than
1062
/// `maxlen` bytes.
1063
905
pub fn decompress_to_vec_bounded(
1064
905
    input: &[u8],
1065
905
    maxlen: usize,
1066
905
) -> Result<Vec<u8>, BoundedDecompressionError> {
1067
905
    let mut decoder = Decompressor::new();
1068
905
    let mut output = vec![0; 1024.min(maxlen)];
1069
905
    let mut input_index = 0;
1070
905
    let mut output_index = 0;
1071
    loop {
1072
97.0k
        let (consumed, produced) =
1073
97.6k
            decoder.read(&input[input_index..], &mut output, output_index, true)?;
1074
97.0k
        input_index += consumed;
1075
97.0k
        output_index += produced;
1076
97.0k
        if decoder.is_done() || output_index == maxlen {
1077
335
            break;
1078
96.7k
        }
1079
96.7k
        output.resize((output_index + 32 * 1024).min(maxlen), 0);
1080
    }
1081
335
    output.resize(output_index, 0);
1082
1083
335
    if decoder.is_done() {
1084
335
        Ok(output)
1085
    } else {
1086
0
        Err(BoundedDecompressionError::OutputTooLarge {
1087
0
            partial_output: output,
1088
0
        })
1089
    }
1090
905
}
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
}