zlib_rs/
inflate.rs

1#![allow(non_snake_case)] // TODO ultimately remove this
2#![allow(clippy::missing_safety_doc)] // obviously needs to be fixed long-term
3
4use core::ffi::{c_char, c_int, c_long, c_ulong};
5use core::marker::PhantomData;
6use core::mem::MaybeUninit;
7use core::ops::ControlFlow;
8
9mod bitreader;
10mod inffixed_tbl;
11mod inftrees;
12mod window;
13mod writer;
14
15use crate::allocate::Allocator;
16use crate::c_api::internal_state;
17use crate::cpu_features::CpuFeatures;
18use crate::{
19    adler32::adler32,
20    c_api::{gz_header, z_checksum, z_size, z_stream, Z_DEFLATED},
21    inflate::writer::Writer,
22    Code, InflateFlush, ReturnCode, DEF_WBITS, MAX_WBITS, MIN_WBITS,
23};
24
25use crate::crc32::{crc32, Crc32Fold};
26
27use self::{
28    bitreader::BitReader,
29    inftrees::{inflate_table, CodeType, InflateTable},
30    window::Window,
31};
32
33const INFLATE_STRICT: bool = false;
34
35// SAFETY: This struct must have the same layout as [`z_stream`], so that casts and transmutations
36// between the two can work without UB.
37#[repr(C)]
38pub struct InflateStream<'a> {
39    pub(crate) next_in: *mut crate::c_api::Bytef,
40    pub(crate) avail_in: crate::c_api::uInt,
41    pub(crate) total_in: crate::c_api::z_size,
42    pub(crate) next_out: *mut crate::c_api::Bytef,
43    pub(crate) avail_out: crate::c_api::uInt,
44    pub(crate) total_out: crate::c_api::z_size,
45    pub(crate) msg: *mut c_char,
46    pub(crate) state: &'a mut State<'a>,
47    pub(crate) alloc: Allocator<'a>,
48    pub(crate) data_type: c_int,
49    pub(crate) adler: crate::c_api::z_checksum,
50    pub(crate) reserved: crate::c_api::uLong,
51}
52
53#[cfg(feature = "__internal-test")]
54#[doc(hidden)]
55pub const INFLATE_STATE_SIZE: usize = core::mem::size_of::<crate::inflate::State>();
56
57#[cfg(feature = "__internal-test")]
58#[doc(hidden)]
59pub unsafe fn set_mode_dict(strm: &mut z_stream) {
60    unsafe {
61        (*(strm.state as *mut State)).mode = Mode::Dict;
62    }
63}
64
65impl<'a> InflateStream<'a> {
66    // z_stream and DeflateStream must have the same layout. Do our best to check if this is true.
67    // (imperfect check, but should catch most mistakes.)
68    const _S: () = assert!(core::mem::size_of::<z_stream>() == core::mem::size_of::<Self>());
69    const _A: () = assert!(core::mem::align_of::<z_stream>() == core::mem::align_of::<Self>());
70
71    /// # Safety
72    ///
73    /// Behavior is undefined if any of the following conditions are violated:
74    ///
75    /// - `strm` satisfies the conditions of [`pointer::as_ref`]
76    /// - if not `NULL`, `strm` as initialized using [`init`] or similar
77    ///
78    /// [`pointer::as_ref`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.as_ref
79    #[inline(always)]
80    pub unsafe fn from_stream_ref(strm: *const z_stream) -> Option<&'a Self> {
81        {
82            // Safety: ptr points to a valid value of type z_stream (if non-null)
83            let stream = unsafe { strm.as_ref() }?;
84
85            if stream.zalloc.is_none() || stream.zfree.is_none() {
86                return None;
87            }
88
89            if stream.state.is_null() {
90                return None;
91            }
92        }
93
94        // Safety: InflateStream has an equivalent layout as z_stream
95        strm.cast::<InflateStream>().as_ref()
96    }
97
98    /// # Safety
99    ///
100    /// Behavior is undefined if any of the following conditions are violated:
101    ///
102    /// - `strm` satisfies the conditions of [`pointer::as_mut`]
103    /// - if not `NULL`, `strm` as initialized using [`init`] or similar
104    ///
105    /// [`pointer::as_mut`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.as_mut
106    #[inline(always)]
107    pub unsafe fn from_stream_mut(strm: *mut z_stream) -> Option<&'a mut Self> {
108        {
109            // Safety: ptr points to a valid value of type z_stream (if non-null)
110            let stream = unsafe { strm.as_ref() }?;
111
112            if stream.zalloc.is_none() || stream.zfree.is_none() {
113                return None;
114            }
115
116            if stream.state.is_null() {
117                return None;
118            }
119        }
120
121        // Safety: InflateStream has an equivalent layout as z_stream
122        strm.cast::<InflateStream>().as_mut()
123    }
124
125    fn as_z_stream_mut(&mut self) -> &mut z_stream {
126        // safety: a valid &mut InflateStream is also a valid &mut z_stream
127        unsafe { &mut *(self as *mut _ as *mut z_stream) }
128    }
129}
130
131const MAX_BITS: u8 = 15; // maximum number of bits in a code
132const MAX_DIST_EXTRA_BITS: u8 = 13; // maximum number of extra distance bits
133                                    //
134pub fn uncompress_slice<'a>(
135    output: &'a mut [u8],
136    input: &[u8],
137    config: InflateConfig,
138) -> (&'a mut [u8], ReturnCode) {
139    // SAFETY: [u8] is also a valid [MaybeUninit<u8>]
140    let output_uninit = unsafe {
141        core::slice::from_raw_parts_mut(output.as_mut_ptr() as *mut MaybeUninit<u8>, output.len())
142    };
143
144    uncompress(output_uninit, input, config)
145}
146
147/// Inflates `source` into `dest`, and writes the final inflated size into `dest_len`.
148pub fn uncompress<'a>(
149    output: &'a mut [MaybeUninit<u8>],
150    input: &[u8],
151    config: InflateConfig,
152) -> (&'a mut [u8], ReturnCode) {
153    let mut dest_len_ptr = output.len() as z_checksum;
154
155    // for detection of incomplete stream when *destLen == 0
156    let mut buf = [0u8];
157
158    let mut left;
159    let mut len = input.len() as u64;
160
161    let dest = if output.is_empty() {
162        left = 1;
163
164        buf.as_mut_ptr()
165    } else {
166        left = output.len() as u64;
167        dest_len_ptr = 0;
168
169        output.as_mut_ptr() as *mut u8
170    };
171
172    let mut stream = z_stream {
173        next_in: input.as_ptr() as *mut u8,
174        avail_in: 0,
175
176        zalloc: None,
177        zfree: None,
178        opaque: core::ptr::null_mut(),
179
180        ..z_stream::default()
181    };
182
183    let err = init(&mut stream, config);
184    if err != ReturnCode::Ok {
185        return (&mut [], err);
186    }
187
188    stream.next_out = dest;
189    stream.avail_out = 0;
190
191    let Some(stream) = (unsafe { InflateStream::from_stream_mut(&mut stream) }) else {
192        return (&mut [], ReturnCode::StreamError);
193    };
194
195    let err = loop {
196        if stream.avail_out == 0 {
197            stream.avail_out = Ord::min(left, u32::MAX as u64) as u32;
198            left -= stream.avail_out as u64;
199        }
200
201        if stream.avail_in == 0 {
202            stream.avail_in = Ord::min(len, u32::MAX as u64) as u32;
203            len -= stream.avail_in as u64;
204        }
205
206        let err = unsafe { inflate(stream, InflateFlush::NoFlush) };
207
208        if err != ReturnCode::Ok {
209            break err;
210        }
211    };
212
213    if !output.is_empty() {
214        dest_len_ptr = stream.total_out;
215    } else if stream.total_out != 0 && err == ReturnCode::BufError {
216        left = 1;
217    }
218
219    let avail_out = stream.avail_out;
220
221    end(stream);
222
223    let ret = match err {
224        ReturnCode::StreamEnd => ReturnCode::Ok,
225        ReturnCode::NeedDict => ReturnCode::DataError,
226        ReturnCode::BufError if (left + avail_out as u64) != 0 => ReturnCode::DataError,
227        _ => err,
228    };
229
230    // SAFETY: we have now initialized these bytes
231    let output_slice = unsafe {
232        core::slice::from_raw_parts_mut(output.as_mut_ptr() as *mut u8, dest_len_ptr as usize)
233    };
234
235    (output_slice, ret)
236}
237
238#[derive(Debug, Clone, Copy)]
239#[repr(u8)]
240pub enum Mode {
241    Head,
242    Flags,
243    Time,
244    Os,
245    ExLen,
246    Extra,
247    Name,
248    Comment,
249    HCrc,
250    Sync,
251    Mem,
252    Length,
253    Type,
254    TypeDo,
255    Stored,
256    CopyBlock,
257    Check,
258    Len_,
259    Len,
260    Lit,
261    LenExt,
262    Dist,
263    DistExt,
264    Match,
265    Table,
266    LenLens,
267    CodeLens,
268    DictId,
269    Dict,
270    Done,
271    Bad,
272}
273
274#[derive(Default, Clone, Copy)]
275#[allow(clippy::enum_variant_names)]
276enum Codes {
277    #[default]
278    Fixed,
279    Codes,
280    Len,
281    Dist,
282}
283
284#[derive(Default, Clone, Copy)]
285struct Table {
286    codes: Codes,
287    bits: usize,
288}
289
290#[derive(Clone, Copy)]
291struct Flags(u8);
292
293impl Default for Flags {
294    fn default() -> Self {
295        Self::SANE
296    }
297}
298
299impl Flags {
300    /// set if currently processing the last block
301    const IS_LAST_BLOCK: Self = Self(0b0000_0001);
302
303    /// set if a custom dictionary was provided
304    const HAVE_DICT: Self = Self(0b0000_0010);
305
306    /// if false, allow invalid distance too far
307    const SANE: Self = Self(0b0000_0100);
308
309    pub(crate) const fn contains(self, other: Self) -> bool {
310        debug_assert!(other.0.count_ones() == 1);
311
312        self.0 & other.0 != 0
313    }
314
315    #[inline(always)]
316    pub(crate) fn update(&mut self, other: Self, value: bool) {
317        if value {
318            *self = Self(self.0 | other.0);
319        } else {
320            *self = Self(self.0 & !other.0);
321        }
322    }
323}
324
325#[repr(C, align(64))]
326pub(crate) struct State<'a> {
327    /// Current inflate mode
328    mode: Mode,
329
330    flags: Flags,
331
332    /// log base 2 of requested window size
333    wbits: u8,
334
335    /// bitflag
336    ///
337    /// - bit 0 true if zlib
338    /// - bit 1 true if gzip
339    /// - bit 2 true to validate check value
340    wrap: u8,
341
342    flush: InflateFlush,
343
344    // allocated window if needed (capacity == 0 if unused)
345    window: Window<'a>,
346
347    //
348    /// number of code length code lengths
349    ncode: usize,
350    /// number of length code lengths
351    nlen: usize,
352    /// number of distance code lengths
353    ndist: usize,
354    /// number of code lengths in lens[]
355    have: usize,
356    /// next available space in codes[]
357    next: usize, // represented as an index, don't want a self-referential structure here
358
359    // IO
360    bit_reader: BitReader<'a>,
361
362    writer: Writer<'a>,
363    total: usize,
364
365    /// length of a block to copy
366    length: usize,
367    /// distance back to copy the string from
368    offset: usize,
369
370    /// extra bits needed
371    extra: usize,
372
373    /// bits back of last unprocessed length/lit
374    back: usize,
375
376    /// initial length of match
377    was: usize,
378
379    /// size of memory copying chunk
380    chunksize: usize,
381
382    in_available: usize,
383    out_available: usize,
384
385    gzip_flags: i32,
386
387    checksum: u32,
388    crc_fold: Crc32Fold,
389
390    error_message: Option<&'static str>,
391
392    /// place to store gzip header if needed
393    head: Option<&'a mut gz_header>,
394    dmax: usize,
395
396    /// table for length/literal codes
397    len_table: Table,
398
399    /// table for dist codes
400    dist_table: Table,
401
402    codes_codes: [Code; crate::ENOUGH_LENS],
403    len_codes: [Code; crate::ENOUGH_LENS],
404    dist_codes: [Code; crate::ENOUGH_DISTS],
405
406    /// temporary storage space for code lengths
407    lens: [u16; 320],
408    /// work area for code table building
409    work: [u16; 288],
410}
411
412impl<'a> State<'a> {
413    fn new(reader: &'a [u8], writer: Writer<'a>) -> Self {
414        let in_available = reader.len();
415        let out_available = writer.capacity();
416
417        Self {
418            flush: InflateFlush::NoFlush,
419
420            flags: Flags::default(),
421            wrap: 0,
422            mode: Mode::Head,
423            length: 0,
424
425            len_table: Table::default(),
426            dist_table: Table::default(),
427
428            wbits: 0,
429            offset: 0,
430            extra: 0,
431            back: 0,
432            was: 0,
433            chunksize: 0,
434            in_available,
435            out_available,
436
437            bit_reader: BitReader::new(reader),
438
439            writer,
440            total: 0,
441
442            window: Window::empty(),
443            head: None,
444
445            lens: [0u16; 320],
446            work: [0u16; 288],
447
448            ncode: 0,
449            nlen: 0,
450            ndist: 0,
451            have: 0,
452            next: 0,
453
454            error_message: None,
455
456            checksum: 0,
457            crc_fold: Crc32Fold::new(),
458
459            dmax: 0,
460            gzip_flags: 0,
461
462            codes_codes: [Code::default(); crate::ENOUGH_LENS],
463            len_codes: [Code::default(); crate::ENOUGH_LENS],
464            dist_codes: [Code::default(); crate::ENOUGH_DISTS],
465        }
466    }
467
468    fn len_table_ref(&self) -> &[Code] {
469        match self.len_table.codes {
470            Codes::Fixed => &self::inffixed_tbl::LENFIX,
471            Codes::Codes => &self.codes_codes,
472            Codes::Len => &self.len_codes,
473            Codes::Dist => &self.dist_codes,
474        }
475    }
476
477    fn dist_table_ref(&self) -> &[Code] {
478        match self.dist_table.codes {
479            Codes::Fixed => &self::inffixed_tbl::DISTFIX,
480            Codes::Codes => &self.codes_codes,
481            Codes::Len => &self.len_codes,
482            Codes::Dist => &self.dist_codes,
483        }
484    }
485
486    fn len_table_get(&self, index: usize) -> Code {
487        self.len_table_ref()[index]
488    }
489
490    fn dist_table_get(&self, index: usize) -> Code {
491        self.dist_table_ref()[index]
492    }
493}
494
495macro_rules! pull_byte {
496    ($self:expr) => {
497        match $self.bit_reader.pull_byte() {
498            Err(return_code) => return $self.inflate_leave(return_code),
499            Ok(_) => (),
500        }
501    };
502}
503
504macro_rules! need_bits {
505    ($self:expr, $n:expr) => {
506        match $self.bit_reader.need_bits($n) {
507            Err(return_code) => return $self.inflate_leave(return_code),
508            Ok(v) => v,
509        }
510    };
511}
512
513// swaps endianness
514const fn zswap32(q: u32) -> u32 {
515    u32::from_be(q.to_le())
516}
517
518const INFLATE_FAST_MIN_HAVE: usize = 15;
519const INFLATE_FAST_MIN_LEFT: usize = 260;
520
521impl State<'_> {
522    // This logic is split into its own function for two reasons
523    //
524    // - We get to load state to the stack; doing this in all cases is expensive, but doing it just
525    //      for Len and related states is very helpful.
526    // - The `-Cllvm-args=-enable-dfa-jump-thread` llvm arg is able to optimize this function, but
527    //      not the entirity of `dispatch`. We get a massive boost from that pass.
528    //
529    // It unfortunately does duplicate the code for some of the states; deduplicating it by having
530    // more of the states call this function is slower.
531    fn len_and_friends(&mut self) -> ControlFlow<ReturnCode, ()> {
532        let avail_in = self.bit_reader.bytes_remaining();
533        let avail_out = self.writer.remaining();
534
535        if avail_in >= INFLATE_FAST_MIN_HAVE && avail_out >= INFLATE_FAST_MIN_LEFT {
536            inflate_fast_help(self, 0);
537            match self.mode {
538                Mode::Len => {}
539                _ => return ControlFlow::Continue(()),
540            }
541        }
542
543        let mut mode;
544        let mut writer;
545        let mut bit_reader;
546
547        macro_rules! load {
548            () => {
549                mode = self.mode;
550                writer = core::mem::replace(&mut self.writer, Writer::new(&mut []));
551                bit_reader = self.bit_reader;
552            };
553        }
554
555        macro_rules! restore {
556            () => {
557                self.mode = mode;
558                self.writer = writer;
559                self.bit_reader = bit_reader;
560            };
561        }
562
563        load!();
564
565        let len_table = match self.len_table.codes {
566            Codes::Fixed => &self::inffixed_tbl::LENFIX[..],
567            Codes::Codes => &self.codes_codes,
568            Codes::Len => &self.len_codes,
569            Codes::Dist => &self.dist_codes,
570        };
571
572        let dist_table = match self.dist_table.codes {
573            Codes::Fixed => &self::inffixed_tbl::DISTFIX[..],
574            Codes::Codes => &self.codes_codes,
575            Codes::Len => &self.len_codes,
576            Codes::Dist => &self.dist_codes,
577        };
578
579        'top: loop {
580            match mode {
581                Mode::Len => {
582                    let avail_in = bit_reader.bytes_remaining();
583                    let avail_out = writer.remaining();
584
585                    // INFLATE_FAST_MIN_LEFT is important. It makes sure there is at least 32 bytes of free
586                    // space available. This means for many SIMD operations we don't need to process a
587                    // remainder; we just copy blindly, and a later operation will overwrite the extra copied
588                    // bytes
589                    if avail_in >= INFLATE_FAST_MIN_HAVE && avail_out >= INFLATE_FAST_MIN_LEFT {
590                        restore!();
591                        inflate_fast_help(self, 0);
592                        return ControlFlow::Continue(());
593                    }
594
595                    self.back = 0;
596
597                    // get a literal, length, or end-of-block code
598                    let mut here;
599                    loop {
600                        let bits = bit_reader.bits(self.len_table.bits);
601                        here = len_table[bits as usize];
602
603                        if here.bits <= bit_reader.bits_in_buffer() {
604                            break;
605                        }
606
607                        if let Err(return_code) = bit_reader.pull_byte() {
608                            restore!();
609                            return ControlFlow::Break(return_code);
610                        };
611                    }
612
613                    if here.op != 0 && here.op & 0xf0 == 0 {
614                        let last = here;
615                        loop {
616                            let bits = bit_reader.bits((last.bits + last.op) as usize) as u16;
617                            here = len_table[(last.val + (bits >> last.bits)) as usize];
618                            if last.bits + here.bits <= bit_reader.bits_in_buffer() {
619                                break;
620                            }
621
622                            if let Err(return_code) = bit_reader.pull_byte() {
623                                restore!();
624                                return ControlFlow::Break(return_code);
625                            };
626                        }
627
628                        bit_reader.drop_bits(last.bits);
629                        self.back += last.bits as usize;
630                    }
631
632                    bit_reader.drop_bits(here.bits);
633                    self.back += here.bits as usize;
634                    self.length = here.val as usize;
635
636                    if here.op == 0 {
637                        mode = Mode::Lit;
638                        continue 'top;
639                    } else if here.op & 32 != 0 {
640                        // end of block
641
642                        // eprintln!("inflate:         end of block");
643
644                        self.back = usize::MAX;
645                        mode = Mode::Type;
646
647                        restore!();
648                        return ControlFlow::Continue(());
649                    } else if here.op & 64 != 0 {
650                        mode = Mode::Bad;
651                        {
652                            restore!();
653                            let this = &mut *self;
654                            let msg: &'static str = "invalid literal/length code\0";
655                            #[cfg(all(feature = "std", test))]
656                            dbg!(msg);
657                            this.error_message = Some(msg);
658                            return ControlFlow::Break(ReturnCode::DataError);
659                        }
660                    } else {
661                        // length code
662                        self.extra = (here.op & MAX_BITS) as usize;
663                        mode = Mode::LenExt;
664                        continue 'top;
665                    }
666                }
667                Mode::Lit => {
668                    // NOTE: this branch must be kept in sync with its counterpart in `dispatch`
669                    if writer.is_full() {
670                        restore!();
671                        #[cfg(all(test, feature = "std"))]
672                        eprintln!("Ok: writer is full ({} bytes)", self.writer.capacity());
673                        return ControlFlow::Break(ReturnCode::Ok);
674                    }
675
676                    writer.push(self.length as u8);
677
678                    mode = Mode::Len;
679
680                    continue 'top;
681                }
682                Mode::LenExt => {
683                    // NOTE: this branch must be kept in sync with its counterpart in `dispatch`
684                    let extra = self.extra;
685
686                    // get extra bits, if any
687                    if extra != 0 {
688                        match bit_reader.need_bits(extra) {
689                            Err(return_code) => {
690                                restore!();
691                                return ControlFlow::Break(return_code);
692                            }
693                            Ok(v) => v,
694                        };
695                        self.length += bit_reader.bits(extra) as usize;
696                        bit_reader.drop_bits(extra as u8);
697                        self.back += extra;
698                    }
699
700                    // eprintln!("inflate: length {}", state.length);
701
702                    self.was = self.length;
703                    mode = Mode::Dist;
704
705                    continue 'top;
706                }
707                Mode::Dist => {
708                    // NOTE: this branch must be kept in sync with its counterpart in `dispatch`
709
710                    // get distance code
711                    let mut here;
712                    loop {
713                        let bits = bit_reader.bits(self.dist_table.bits) as usize;
714                        here = dist_table[bits];
715                        if here.bits <= bit_reader.bits_in_buffer() {
716                            break;
717                        }
718
719                        if let Err(return_code) = bit_reader.pull_byte() {
720                            restore!();
721                            return ControlFlow::Break(return_code);
722                        };
723                    }
724
725                    if here.op & 0xf0 == 0 {
726                        let last = here;
727
728                        loop {
729                            let bits = bit_reader.bits((last.bits + last.op) as usize);
730                            here = dist_table[last.val as usize + ((bits as usize) >> last.bits)];
731
732                            if last.bits + here.bits <= bit_reader.bits_in_buffer() {
733                                break;
734                            }
735
736                            if let Err(return_code) = bit_reader.pull_byte() {
737                                restore!();
738                                return ControlFlow::Break(return_code);
739                            };
740                        }
741
742                        bit_reader.drop_bits(last.bits);
743                        self.back += last.bits as usize;
744                    }
745
746                    bit_reader.drop_bits(here.bits);
747
748                    if here.op & 64 != 0 {
749                        restore!();
750                        self.mode = Mode::Bad;
751                        return ControlFlow::Break(self.bad("invalid distance code\0"));
752                    }
753
754                    self.offset = here.val as usize;
755
756                    self.extra = (here.op & MAX_BITS) as usize;
757                    mode = Mode::DistExt;
758
759                    continue 'top;
760                }
761                Mode::DistExt => {
762                    // NOTE: this branch must be kept in sync with its counterpart in `dispatch`
763                    let extra = self.extra;
764
765                    if extra > 0 {
766                        match bit_reader.need_bits(extra) {
767                            Err(return_code) => {
768                                restore!();
769                                return ControlFlow::Break(return_code);
770                            }
771                            Ok(v) => v,
772                        };
773                        self.offset += bit_reader.bits(extra) as usize;
774                        bit_reader.drop_bits(extra as u8);
775                        self.back += extra;
776                    }
777
778                    if INFLATE_STRICT && self.offset > self.dmax {
779                        restore!();
780                        self.mode = Mode::Bad;
781                        return ControlFlow::Break(
782                            self.bad("invalid distance code too far back\0"),
783                        );
784                    }
785
786                    // eprintln!("inflate: distance {}", state.offset);
787
788                    mode = Mode::Match;
789
790                    continue 'top;
791                }
792                Mode::Match => {
793                    // NOTE: this branch must be kept in sync with its counterpart in `dispatch`
794                    if writer.is_full() {
795                        restore!();
796                        #[cfg(all(feature = "std", test))]
797                        eprintln!(
798                            "BufError: writer is full ({} bytes)",
799                            self.writer.capacity()
800                        );
801                        return ControlFlow::Break(ReturnCode::Ok);
802                    }
803
804                    let left = writer.remaining();
805                    let copy = writer.len();
806
807                    let copy = if self.offset > copy {
808                        // copy from window to output
809
810                        let mut copy = self.offset - copy;
811
812                        if copy > self.window.have() {
813                            if self.flags.contains(Flags::SANE) {
814                                restore!();
815                                self.mode = Mode::Bad;
816                                return ControlFlow::Break(
817                                    self.bad("invalid distance too far back\0"),
818                                );
819                            }
820
821                            // TODO INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
822                            panic!("INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR")
823                        }
824
825                        let wnext = self.window.next();
826                        let wsize = self.window.size();
827
828                        let from = if copy > wnext {
829                            copy -= wnext;
830                            wsize - copy
831                        } else {
832                            wnext - copy
833                        };
834
835                        copy = Ord::min(copy, self.length);
836                        copy = Ord::min(copy, left);
837
838                        writer.extend_from_window(&self.window, from..from + copy);
839
840                        copy
841                    } else {
842                        let copy = Ord::min(self.length, left);
843                        writer.copy_match(self.offset, copy);
844
845                        copy
846                    };
847
848                    self.length -= copy;
849
850                    if self.length == 0 {
851                        mode = Mode::Len;
852                        continue 'top;
853                    } else {
854                        // otherwise it seems to recurse?
855                        // self.match_()
856                        continue 'top;
857                    }
858                }
859                _ => unsafe { core::hint::unreachable_unchecked() },
860            }
861        }
862    }
863
864    fn dispatch(&mut self) -> ReturnCode {
865        'label: loop {
866            match self.mode {
867                Mode::Head => {
868                    if self.wrap == 0 {
869                        self.mode = Mode::TypeDo;
870
871                        continue 'label;
872                    }
873
874                    need_bits!(self, 16);
875
876                    // Gzip
877                    if (self.wrap & 2) != 0 && self.bit_reader.hold() == 0x8b1f {
878                        if self.wbits == 0 {
879                            self.wbits = 15;
880                        }
881
882                        let b0 = self.bit_reader.bits(8) as u8;
883                        let b1 = (self.bit_reader.hold() >> 8) as u8;
884                        self.checksum = crc32(crate::CRC32_INITIAL_VALUE, &[b0, b1]);
885                        self.bit_reader.init_bits();
886
887                        self.mode = Mode::Flags;
888
889                        continue 'label;
890                    }
891
892                    if let Some(header) = &mut self.head {
893                        header.done = -1;
894                    }
895
896                    // check if zlib header is allowed
897                    if (self.wrap & 1) == 0
898                        || ((self.bit_reader.bits(8) << 8) + (self.bit_reader.hold() >> 8)) % 31
899                            != 0
900                    {
901                        self.mode = Mode::Bad;
902                        break 'label self.bad("incorrect header check\0");
903                    }
904
905                    if self.bit_reader.bits(4) != Z_DEFLATED as u64 {
906                        self.mode = Mode::Bad;
907                        break 'label self.bad("unknown compression method\0");
908                    }
909
910                    self.bit_reader.drop_bits(4);
911                    let len = self.bit_reader.bits(4) as u8 + 8;
912
913                    if self.wbits == 0 {
914                        self.wbits = len;
915                    }
916
917                    if len as i32 > MAX_WBITS || len > self.wbits {
918                        self.mode = Mode::Bad;
919                        break 'label self.bad("invalid window size\0");
920                    }
921
922                    self.dmax = 1 << len;
923                    self.gzip_flags = 0; // indicate zlib header
924                    self.checksum = crate::ADLER32_INITIAL_VALUE as _;
925
926                    if self.bit_reader.hold() & 0x200 != 0 {
927                        self.bit_reader.init_bits();
928
929                        self.mode = Mode::DictId;
930
931                        continue 'label;
932                    } else {
933                        self.bit_reader.init_bits();
934
935                        self.mode = Mode::Type;
936
937                        continue 'label;
938                    }
939                }
940                Mode::Flags => {
941                    need_bits!(self, 16);
942                    self.gzip_flags = self.bit_reader.hold() as i32;
943
944                    // Z_DEFLATED = 8 is the only supported method
945                    if self.gzip_flags & 0xff != Z_DEFLATED {
946                        self.mode = Mode::Bad;
947                        break 'label self.bad("unknown compression method\0");
948                    }
949
950                    if self.gzip_flags & 0xe000 != 0 {
951                        self.mode = Mode::Bad;
952                        break 'label self.bad("unknown header flags set\0");
953                    }
954
955                    if let Some(head) = self.head.as_mut() {
956                        head.text = ((self.bit_reader.hold() >> 8) & 1) as i32;
957                    }
958
959                    if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
960                        let b0 = self.bit_reader.bits(8) as u8;
961                        let b1 = (self.bit_reader.hold() >> 8) as u8;
962                        self.checksum = crc32(self.checksum, &[b0, b1]);
963                    }
964
965                    self.bit_reader.init_bits();
966                    self.mode = Mode::Time;
967
968                    continue 'label;
969                }
970                Mode::Time => {
971                    need_bits!(self, 32);
972                    if let Some(head) = self.head.as_mut() {
973                        head.time = self.bit_reader.hold() as z_size;
974                    }
975
976                    if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
977                        let bytes = (self.bit_reader.hold() as u32).to_le_bytes();
978                        self.checksum = crc32(self.checksum, &bytes);
979                    }
980
981                    self.bit_reader.init_bits();
982                    self.mode = Mode::Os;
983
984                    continue 'label;
985                }
986                Mode::Os => {
987                    need_bits!(self, 16);
988                    if let Some(head) = self.head.as_mut() {
989                        head.xflags = (self.bit_reader.hold() & 0xff) as i32;
990                        head.os = (self.bit_reader.hold() >> 8) as i32;
991                    }
992
993                    if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
994                        let bytes = (self.bit_reader.hold() as u16).to_le_bytes();
995                        self.checksum = crc32(self.checksum, &bytes);
996                    }
997
998                    self.bit_reader.init_bits();
999                    self.mode = Mode::ExLen;
1000
1001                    continue 'label;
1002                }
1003                Mode::ExLen => {
1004                    if (self.gzip_flags & 0x0400) != 0 {
1005                        need_bits!(self, 16);
1006
1007                        // self.length (and head.extra_len) represent the length of the extra field
1008                        self.length = self.bit_reader.hold() as usize;
1009                        if let Some(head) = self.head.as_mut() {
1010                            head.extra_len = self.length as u32;
1011                        }
1012
1013                        if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1014                            let bytes = (self.bit_reader.hold() as u16).to_le_bytes();
1015                            self.checksum = crc32(self.checksum, &bytes);
1016                        }
1017                        self.bit_reader.init_bits();
1018                    } else if let Some(head) = self.head.as_mut() {
1019                        head.extra = core::ptr::null_mut();
1020                    }
1021
1022                    self.mode = Mode::Extra;
1023
1024                    continue 'label;
1025                }
1026                Mode::Extra => {
1027                    if (self.gzip_flags & 0x0400) != 0 {
1028                        // self.length is the number of remaining `extra` bytes. But they may not all be available
1029                        let extra_available =
1030                            Ord::min(self.length, self.bit_reader.bytes_remaining());
1031
1032                        if extra_available > 0 {
1033                            if let Some(head) = self.head.as_mut() {
1034                                if !head.extra.is_null() {
1035                                    // at `head.extra`, the caller has reserved `head.extra_max` bytes.
1036                                    // in the deflated byte stream, we've found a gzip header with
1037                                    // `head.extra_len` bytes of data. We must be careful because
1038                                    // `head.extra_len` may be larger than `head.extra_max`.
1039
1040                                    // how many bytes we've already written into `head.extra`
1041                                    let written_so_far = head.extra_len as usize - self.length;
1042
1043                                    // min of number of bytes available at dst and at src
1044                                    let count = Ord::min(
1045                                        (head.extra_max as usize).saturating_sub(written_so_far),
1046                                        extra_available,
1047                                    );
1048
1049                                    // SAFETY: location where we'll write: this saturates at the
1050                                    // `head.extra.add(head.extra.max)` to prevent UB
1051                                    let next_write_offset =
1052                                        Ord::min(written_so_far, head.extra_max as usize);
1053
1054                                    unsafe {
1055                                        // SAFETY: count is effectively bounded by head.extra_max
1056                                        // and bit_reader.bytes_remaining(), so the count won't
1057                                        // go out of bounds.
1058                                        core::ptr::copy_nonoverlapping(
1059                                            self.bit_reader.as_mut_ptr(),
1060                                            head.extra.add(next_write_offset),
1061                                            count,
1062                                        );
1063                                    }
1064                                }
1065                            }
1066
1067                            // Checksum
1068                            if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1069                                let extra_slice = &self.bit_reader.as_slice()[..extra_available];
1070                                self.checksum = crc32(self.checksum, extra_slice)
1071                            }
1072
1073                            self.in_available -= extra_available;
1074                            self.bit_reader.advance(extra_available);
1075                            self.length -= extra_available;
1076                        }
1077
1078                        // Checks for errors occur after returning
1079                        if self.length != 0 {
1080                            break 'label self.inflate_leave(ReturnCode::Ok);
1081                        }
1082                    }
1083
1084                    self.length = 0;
1085                    self.mode = Mode::Name;
1086
1087                    continue 'label;
1088                }
1089                Mode::Name => {
1090                    if (self.gzip_flags & 0x0800) != 0 {
1091                        if self.in_available == 0 {
1092                            break 'label self.inflate_leave(ReturnCode::Ok);
1093                        }
1094
1095                        // the name string will always be null-terminated, but might be longer than we have
1096                        // space for in the header struct. Nonetheless, we read the whole thing.
1097                        let slice = self.bit_reader.as_slice();
1098                        let null_terminator_index = slice.iter().position(|c| *c == 0);
1099
1100                        // we include the null terminator if it exists
1101                        let name_slice = match null_terminator_index {
1102                            Some(i) => &slice[..=i],
1103                            None => slice,
1104                        };
1105
1106                        // if the header has space, store as much as possible in there
1107                        if let Some(head) = self.head.as_mut() {
1108                            if !head.name.is_null() {
1109                                let remaining_name_bytes = (head.name_max as usize)
1110                                    .checked_sub(self.length)
1111                                    .expect("name out of bounds");
1112                                let copy = Ord::min(name_slice.len(), remaining_name_bytes);
1113
1114                                unsafe {
1115                                    // SAFETY: copy is effectively bound by the name length and
1116                                    // head.name_max, so this won't go out of bounds.
1117                                    core::ptr::copy_nonoverlapping(
1118                                        name_slice.as_ptr(),
1119                                        head.name.add(self.length),
1120                                        copy,
1121                                    )
1122                                };
1123
1124                                self.length += copy;
1125                            }
1126                        }
1127
1128                        if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1129                            self.checksum = crc32(self.checksum, name_slice);
1130                        }
1131
1132                        let reached_end = name_slice.last() == Some(&0);
1133                        self.bit_reader.advance(name_slice.len());
1134
1135                        if !reached_end && self.bit_reader.bytes_remaining() == 0 {
1136                            break 'label self.inflate_leave(ReturnCode::Ok);
1137                        }
1138                    } else if let Some(head) = self.head.as_mut() {
1139                        head.name = core::ptr::null_mut();
1140                    }
1141
1142                    self.length = 0;
1143                    self.mode = Mode::Comment;
1144
1145                    continue 'label;
1146                }
1147                Mode::Comment => {
1148                    if (self.gzip_flags & 0x01000) != 0 {
1149                        if self.in_available == 0 {
1150                            break 'label self.inflate_leave(ReturnCode::Ok);
1151                        }
1152
1153                        // the comment string will always be null-terminated, but might be longer than we have
1154                        // space for in the header struct. Nonetheless, we read the whole thing.
1155                        let slice = self.bit_reader.as_slice();
1156                        let null_terminator_index = slice.iter().position(|c| *c == 0);
1157
1158                        // we include the null terminator if it exists
1159                        let comment_slice = match null_terminator_index {
1160                            Some(i) => &slice[..=i],
1161                            None => slice,
1162                        };
1163
1164                        // if the header has space, store as much as possible in there
1165                        if let Some(head) = self.head.as_mut() {
1166                            if !head.comment.is_null() {
1167                                let remaining_comm_bytes = (head.comm_max as usize)
1168                                    .checked_sub(self.length)
1169                                    .expect("comm out of bounds");
1170                                let copy = Ord::min(comment_slice.len(), remaining_comm_bytes);
1171
1172                                unsafe {
1173                                    // SAFETY: copy is effectively bound by the comment length and
1174                                    // head.comm_max, so this won't go out of bounds.
1175                                    core::ptr::copy_nonoverlapping(
1176                                        comment_slice.as_ptr(),
1177                                        head.comment.add(self.length),
1178                                        copy,
1179                                    )
1180                                };
1181
1182                                self.length += copy;
1183                            }
1184                        }
1185
1186                        if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1187                            self.checksum = crc32(self.checksum, comment_slice);
1188                        }
1189
1190                        let reached_end = comment_slice.last() == Some(&0);
1191                        self.bit_reader.advance(comment_slice.len());
1192
1193                        if !reached_end && self.bit_reader.bytes_remaining() == 0 {
1194                            break 'label self.inflate_leave(ReturnCode::Ok);
1195                        }
1196                    } else if let Some(head) = self.head.as_mut() {
1197                        head.comment = core::ptr::null_mut();
1198                    }
1199
1200                    self.mode = Mode::HCrc;
1201
1202                    continue 'label;
1203                }
1204                Mode::HCrc => {
1205                    if (self.gzip_flags & 0x0200) != 0 {
1206                        need_bits!(self, 16);
1207
1208                        if (self.wrap & 4) != 0
1209                            && self.bit_reader.hold() as u32 != (self.checksum & 0xffff)
1210                        {
1211                            self.mode = Mode::Bad;
1212                            break 'label self.bad("header crc mismatch\0");
1213                        }
1214
1215                        self.bit_reader.init_bits();
1216                    }
1217
1218                    if let Some(head) = self.head.as_mut() {
1219                        head.hcrc = (self.gzip_flags >> 9) & 1;
1220                        head.done = 1;
1221                    }
1222
1223                    // compute crc32 checksum if not in raw mode
1224                    if (self.wrap & 4 != 0) && self.gzip_flags != 0 {
1225                        self.crc_fold = Crc32Fold::new();
1226                        self.checksum = crate::CRC32_INITIAL_VALUE;
1227                    }
1228
1229                    self.mode = Mode::Type;
1230
1231                    continue 'label;
1232                }
1233                Mode::Type => {
1234                    use InflateFlush::*;
1235
1236                    match self.flush {
1237                        Block | Trees => break 'label ReturnCode::Ok,
1238                        NoFlush | SyncFlush | Finish => {
1239                            // NOTE: this is slightly different to what zlib-rs does!
1240                            self.mode = Mode::TypeDo;
1241                            continue 'label;
1242                        }
1243                    }
1244                }
1245                Mode::TypeDo => {
1246                    if self.flags.contains(Flags::IS_LAST_BLOCK) {
1247                        self.bit_reader.next_byte_boundary();
1248                        self.mode = Mode::Check;
1249
1250                        continue 'label;
1251                    }
1252
1253                    need_bits!(self, 3);
1254                    // self.last = self.bit_reader.bits(1) != 0;
1255                    self.flags
1256                        .update(Flags::IS_LAST_BLOCK, self.bit_reader.bits(1) != 0);
1257                    self.bit_reader.drop_bits(1);
1258
1259                    match self.bit_reader.bits(2) {
1260                        0b00 => {
1261                            // eprintln!("inflate:     stored block (last = {last})");
1262
1263                            self.bit_reader.drop_bits(2);
1264
1265                            self.mode = Mode::Stored;
1266
1267                            continue 'label;
1268                        }
1269                        0b01 => {
1270                            // eprintln!("inflate:     fixed codes block (last = {last})");
1271
1272                            self.len_table = Table {
1273                                codes: Codes::Fixed,
1274                                bits: 9,
1275                            };
1276
1277                            self.dist_table = Table {
1278                                codes: Codes::Fixed,
1279                                bits: 5,
1280                            };
1281
1282                            self.mode = Mode::Len_;
1283
1284                            self.bit_reader.drop_bits(2);
1285
1286                            if let InflateFlush::Trees = self.flush {
1287                                break 'label self.inflate_leave(ReturnCode::Ok);
1288                            } else {
1289                                continue 'label;
1290                            }
1291                        }
1292                        0b10 => {
1293                            // eprintln!("inflate:     dynamic codes block (last = {last})");
1294
1295                            self.bit_reader.drop_bits(2);
1296
1297                            self.mode = Mode::Table;
1298
1299                            continue 'label;
1300                        }
1301                        0b11 => {
1302                            // eprintln!("inflate:     invalid block type");
1303
1304                            self.bit_reader.drop_bits(2);
1305
1306                            self.mode = Mode::Bad;
1307                            break 'label self.bad("invalid block type\0");
1308                        }
1309                        _ => {
1310                            // LLVM will optimize this branch away
1311                            unreachable!("BitReader::bits(2) only yields a value of two bits, so this match is already exhaustive")
1312                        }
1313                    }
1314                }
1315                Mode::Stored => {
1316                    self.bit_reader.next_byte_boundary();
1317
1318                    need_bits!(self, 32);
1319
1320                    let hold = self.bit_reader.bits(32) as u32;
1321
1322                    // eprintln!("hold {hold:#x}");
1323
1324                    if hold as u16 != !((hold >> 16) as u16) {
1325                        self.mode = Mode::Bad;
1326                        break 'label self.bad("invalid stored block lengths\0");
1327                    }
1328
1329                    self.length = hold as usize & 0xFFFF;
1330                    // eprintln!("inflate:     stored length {}", state.length);
1331
1332                    self.bit_reader.init_bits();
1333
1334                    if let InflateFlush::Trees = self.flush {
1335                        break 'label self.inflate_leave(ReturnCode::Ok);
1336                    } else {
1337                        self.mode = Mode::CopyBlock;
1338
1339                        continue 'label;
1340                    }
1341                }
1342                Mode::CopyBlock => {
1343                    loop {
1344                        let mut copy = self.length;
1345
1346                        if copy == 0 {
1347                            break;
1348                        }
1349
1350                        copy = Ord::min(copy, self.writer.remaining());
1351                        copy = Ord::min(copy, self.bit_reader.bytes_remaining());
1352
1353                        if copy == 0 {
1354                            break 'label self.inflate_leave(ReturnCode::Ok);
1355                        }
1356
1357                        self.writer.extend(&self.bit_reader.as_slice()[..copy]);
1358                        self.bit_reader.advance(copy);
1359
1360                        self.length -= copy;
1361                    }
1362
1363                    self.mode = Mode::Type;
1364
1365                    continue 'label;
1366                }
1367                Mode::Check => {
1368                    if !cfg!(feature = "__internal-fuzz-disable-checksum") && self.wrap != 0 {
1369                        need_bits!(self, 32);
1370
1371                        self.total += self.writer.len();
1372
1373                        if self.wrap & 4 != 0 {
1374                            if self.gzip_flags != 0 {
1375                                self.crc_fold.fold(self.writer.filled(), self.checksum);
1376                                self.checksum = self.crc_fold.finish();
1377                            } else {
1378                                self.checksum = adler32(self.checksum, self.writer.filled());
1379                            }
1380                        }
1381
1382                        let given_checksum = if self.gzip_flags != 0 {
1383                            self.bit_reader.hold() as u32
1384                        } else {
1385                            zswap32(self.bit_reader.hold() as u32)
1386                        };
1387
1388                        self.out_available = self.writer.capacity() - self.writer.len();
1389
1390                        if self.wrap & 4 != 0 && given_checksum != self.checksum {
1391                            self.mode = Mode::Bad;
1392                            break 'label self.bad("incorrect data check\0");
1393                        }
1394
1395                        self.bit_reader.init_bits();
1396                    }
1397                    self.mode = Mode::Length;
1398
1399                    continue 'label;
1400                }
1401                Mode::Len_ => {
1402                    self.mode = Mode::Len;
1403
1404                    continue 'label;
1405                }
1406                Mode::Len => match self.len_and_friends() {
1407                    ControlFlow::Break(return_code) => break 'label return_code,
1408                    ControlFlow::Continue(()) => continue 'label,
1409                },
1410                Mode::LenExt => {
1411                    // NOTE: this branch must be kept in sync with its counterpart in `len_and_friends`
1412                    let extra = self.extra;
1413
1414                    // get extra bits, if any
1415                    if extra != 0 {
1416                        need_bits!(self, extra);
1417                        self.length += self.bit_reader.bits(extra) as usize;
1418                        self.bit_reader.drop_bits(extra as u8);
1419                        self.back += extra;
1420                    }
1421
1422                    // eprintln!("inflate: length {}", state.length);
1423
1424                    self.was = self.length;
1425                    self.mode = Mode::Dist;
1426
1427                    continue 'label;
1428                }
1429                Mode::Lit => {
1430                    // NOTE: this branch must be kept in sync with its counterpart in `len_and_friends`
1431                    if self.writer.is_full() {
1432                        #[cfg(all(test, feature = "std"))]
1433                        eprintln!("Ok: writer is full ({} bytes)", self.writer.capacity());
1434                        break 'label self.inflate_leave(ReturnCode::Ok);
1435                    }
1436
1437                    self.writer.push(self.length as u8);
1438
1439                    self.mode = Mode::Len;
1440
1441                    continue 'label;
1442                }
1443                Mode::Dist => {
1444                    // NOTE: this branch must be kept in sync with its counterpart in `len_and_friends`
1445
1446                    // get distance code
1447                    let mut here;
1448                    loop {
1449                        let bits = self.bit_reader.bits(self.dist_table.bits) as usize;
1450                        here = self.dist_table_get(bits);
1451                        if here.bits <= self.bit_reader.bits_in_buffer() {
1452                            break;
1453                        }
1454
1455                        pull_byte!(self);
1456                    }
1457
1458                    if here.op & 0xf0 == 0 {
1459                        let last = here;
1460
1461                        loop {
1462                            let bits = self.bit_reader.bits((last.bits + last.op) as usize);
1463                            here = self
1464                                .dist_table_get(last.val as usize + ((bits as usize) >> last.bits));
1465
1466                            if last.bits + here.bits <= self.bit_reader.bits_in_buffer() {
1467                                break;
1468                            }
1469
1470                            pull_byte!(self);
1471                        }
1472
1473                        self.bit_reader.drop_bits(last.bits);
1474                        self.back += last.bits as usize;
1475                    }
1476
1477                    self.bit_reader.drop_bits(here.bits);
1478
1479                    if here.op & 64 != 0 {
1480                        self.mode = Mode::Bad;
1481                        break 'label self.bad("invalid distance code\0");
1482                    }
1483
1484                    self.offset = here.val as usize;
1485
1486                    self.extra = (here.op & MAX_BITS) as usize;
1487                    self.mode = Mode::DistExt;
1488
1489                    continue 'label;
1490                }
1491                Mode::DistExt => {
1492                    // NOTE: this branch must be kept in sync with its counterpart in `len_and_friends`
1493                    let extra = self.extra;
1494
1495                    if extra > 0 {
1496                        need_bits!(self, extra);
1497                        self.offset += self.bit_reader.bits(extra) as usize;
1498                        self.bit_reader.drop_bits(extra as u8);
1499                        self.back += extra;
1500                    }
1501
1502                    if INFLATE_STRICT && self.offset > self.dmax {
1503                        self.mode = Mode::Bad;
1504                        break 'label self.bad("invalid distance code too far back\0");
1505                    }
1506
1507                    // eprintln!("inflate: distance {}", state.offset);
1508
1509                    self.mode = Mode::Match;
1510
1511                    continue 'label;
1512                }
1513                Mode::Match => {
1514                    // NOTE: this branch must be kept in sync with its counterpart in `len_and_friends`
1515
1516                    'match_: loop {
1517                        if self.writer.is_full() {
1518                            #[cfg(all(feature = "std", test))]
1519                            eprintln!(
1520                                "BufError: writer is full ({} bytes)",
1521                                self.writer.capacity()
1522                            );
1523                            break 'label self.inflate_leave(ReturnCode::Ok);
1524                        }
1525
1526                        let left = self.writer.remaining();
1527                        let copy = self.writer.len();
1528
1529                        let copy = if self.offset > copy {
1530                            // copy from window to output
1531
1532                            let mut copy = self.offset - copy;
1533
1534                            if copy > self.window.have() {
1535                                if self.flags.contains(Flags::SANE) {
1536                                    self.mode = Mode::Bad;
1537                                    break 'label self.bad("invalid distance too far back\0");
1538                                }
1539
1540                                // TODO INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
1541                                panic!("INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR")
1542                            }
1543
1544                            let wnext = self.window.next();
1545                            let wsize = self.window.size();
1546
1547                            let from = if copy > wnext {
1548                                copy -= wnext;
1549                                wsize - copy
1550                            } else {
1551                                wnext - copy
1552                            };
1553
1554                            copy = Ord::min(copy, self.length);
1555                            copy = Ord::min(copy, left);
1556
1557                            self.writer
1558                                .extend_from_window(&self.window, from..from + copy);
1559
1560                            copy
1561                        } else {
1562                            let copy = Ord::min(self.length, left);
1563                            self.writer.copy_match(self.offset, copy);
1564
1565                            copy
1566                        };
1567
1568                        self.length -= copy;
1569
1570                        if self.length == 0 {
1571                            self.mode = Mode::Len;
1572
1573                            continue 'label;
1574                        } else {
1575                            // otherwise it seems to recurse?
1576                            continue 'match_;
1577                        }
1578                    }
1579                }
1580                Mode::Done => todo!(),
1581                Mode::Table => {
1582                    need_bits!(self, 14);
1583                    self.nlen = self.bit_reader.bits(5) as usize + 257;
1584                    self.bit_reader.drop_bits(5);
1585                    self.ndist = self.bit_reader.bits(5) as usize + 1;
1586                    self.bit_reader.drop_bits(5);
1587                    self.ncode = self.bit_reader.bits(4) as usize + 4;
1588                    self.bit_reader.drop_bits(4);
1589
1590                    // TODO pkzit_bug_workaround
1591                    if self.nlen > 286 || self.ndist > 30 {
1592                        self.mode = Mode::Bad;
1593                        break 'label self.bad("too many length or distance symbols\0");
1594                    }
1595
1596                    self.have = 0;
1597                    self.mode = Mode::LenLens;
1598
1599                    continue 'label;
1600                }
1601                Mode::LenLens => {
1602                    // permutation of code lengths ;
1603                    const ORDER: [u16; 19] = [
1604                        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
1605                    ];
1606
1607                    while self.have < self.ncode {
1608                        need_bits!(self, 3);
1609                        self.lens[ORDER[self.have] as usize] = self.bit_reader.bits(3) as u16;
1610                        self.have += 1;
1611                        self.bit_reader.drop_bits(3);
1612                    }
1613
1614                    while self.have < 19 {
1615                        self.lens[ORDER[self.have] as usize] = 0;
1616                        self.have += 1;
1617                    }
1618
1619                    self.len_table.bits = 7;
1620
1621                    let InflateTable::Success(root) = inflate_table(
1622                        CodeType::Codes,
1623                        &self.lens,
1624                        19,
1625                        &mut self.codes_codes,
1626                        self.len_table.bits,
1627                        &mut self.work,
1628                    ) else {
1629                        self.mode = Mode::Bad;
1630                        break 'label self.bad("invalid code lengths set\0");
1631                    };
1632
1633                    self.len_table.codes = Codes::Codes;
1634                    self.len_table.bits = root;
1635
1636                    self.have = 0;
1637                    self.mode = Mode::CodeLens;
1638
1639                    continue 'label;
1640                }
1641                Mode::CodeLens => {
1642                    while self.have < self.nlen + self.ndist {
1643                        let here = loop {
1644                            let bits = self.bit_reader.bits(self.len_table.bits);
1645                            let here = self.len_table_get(bits as usize);
1646                            if here.bits <= self.bit_reader.bits_in_buffer() {
1647                                break here;
1648                            }
1649
1650                            pull_byte!(self);
1651                        };
1652
1653                        let here_bits = here.bits;
1654
1655                        match here.val {
1656                            0..=15 => {
1657                                self.bit_reader.drop_bits(here_bits);
1658                                self.lens[self.have] = here.val;
1659                                self.have += 1;
1660                            }
1661                            16 => {
1662                                need_bits!(self, here_bits as usize + 2);
1663                                self.bit_reader.drop_bits(here_bits);
1664                                if self.have == 0 {
1665                                    self.mode = Mode::Bad;
1666                                    break 'label self.bad("invalid bit length repeat\0");
1667                                }
1668
1669                                let len = self.lens[self.have - 1];
1670                                let copy = 3 + self.bit_reader.bits(2) as usize;
1671                                self.bit_reader.drop_bits(2);
1672
1673                                if self.have + copy > self.nlen + self.ndist {
1674                                    self.mode = Mode::Bad;
1675                                    break 'label self.bad("invalid bit length repeat\0");
1676                                }
1677
1678                                for _ in 0..copy {
1679                                    self.lens[self.have] = len;
1680                                    self.have += 1;
1681                                }
1682                            }
1683                            17 => {
1684                                need_bits!(self, here_bits as usize + 3);
1685                                self.bit_reader.drop_bits(here_bits);
1686                                let len = 0;
1687                                let copy = 3 + self.bit_reader.bits(3) as usize;
1688                                self.bit_reader.drop_bits(3);
1689
1690                                if self.have + copy > self.nlen + self.ndist {
1691                                    self.mode = Mode::Bad;
1692                                    break 'label self.bad("invalid bit length repeat\0");
1693                                }
1694
1695                                for _ in 0..copy {
1696                                    self.lens[self.have] = len as u16;
1697                                    self.have += 1;
1698                                }
1699                            }
1700                            18.. => {
1701                                need_bits!(self, here_bits as usize + 7);
1702                                self.bit_reader.drop_bits(here_bits);
1703                                let len = 0;
1704                                let copy = 11 + self.bit_reader.bits(7) as usize;
1705                                self.bit_reader.drop_bits(7);
1706
1707                                if self.have + copy > self.nlen + self.ndist {
1708                                    self.mode = Mode::Bad;
1709                                    break 'label self.bad("invalid bit length repeat\0");
1710                                }
1711
1712                                for _ in 0..copy {
1713                                    self.lens[self.have] = len as u16;
1714                                    self.have += 1;
1715                                }
1716                            }
1717                        }
1718                    }
1719
1720                    // check for end-of-block code (better have one)
1721                    if self.lens[256] == 0 {
1722                        self.mode = Mode::Bad;
1723                        break 'label self.bad("invalid code -- missing end-of-block\0");
1724                    }
1725
1726                    // build code tables
1727
1728                    self.len_table.bits = 10;
1729
1730                    let InflateTable::Success(root) = inflate_table(
1731                        CodeType::Lens,
1732                        &self.lens,
1733                        self.nlen,
1734                        &mut self.len_codes,
1735                        self.len_table.bits,
1736                        &mut self.work,
1737                    ) else {
1738                        self.mode = Mode::Bad;
1739                        break 'label self.bad("invalid literal/lengths set\0");
1740                    };
1741
1742                    self.len_table.codes = Codes::Len;
1743                    self.len_table.bits = root;
1744
1745                    self.dist_table.bits = 9;
1746
1747                    let InflateTable::Success(root) = inflate_table(
1748                        CodeType::Dists,
1749                        &self.lens[self.nlen..],
1750                        self.ndist,
1751                        &mut self.dist_codes,
1752                        self.dist_table.bits,
1753                        &mut self.work,
1754                    ) else {
1755                        self.mode = Mode::Bad;
1756                        break 'label self.bad("invalid distances set\0");
1757                    };
1758
1759                    self.dist_table.bits = root;
1760                    self.dist_table.codes = Codes::Dist;
1761
1762                    self.mode = Mode::Len_;
1763
1764                    if matches!(self.flush, InflateFlush::Trees) {
1765                        break 'label self.inflate_leave(ReturnCode::Ok);
1766                    }
1767
1768                    continue 'label;
1769                }
1770                Mode::Dict => {
1771                    if !self.flags.contains(Flags::HAVE_DICT) {
1772                        break 'label self.inflate_leave(ReturnCode::NeedDict);
1773                    }
1774
1775                    self.checksum = crate::ADLER32_INITIAL_VALUE as _;
1776
1777                    self.mode = Mode::Type;
1778
1779                    continue 'label;
1780                }
1781                Mode::DictId => {
1782                    need_bits!(self, 32);
1783
1784                    self.checksum = zswap32(self.bit_reader.hold() as u32);
1785
1786                    self.bit_reader.init_bits();
1787
1788                    self.mode = Mode::Dict;
1789
1790                    continue 'label;
1791                }
1792                Mode::Bad => {
1793                    let msg = "repeated call with bad state\0";
1794                    #[cfg(all(feature = "std", test))]
1795                    dbg!(msg);
1796                    self.error_message = Some(msg);
1797
1798                    break 'label ReturnCode::DataError;
1799                }
1800                Mode::Mem => {
1801                    break 'label ReturnCode::MemError;
1802                }
1803                Mode::Sync => {
1804                    break 'label ReturnCode::StreamError;
1805                }
1806                Mode::Length => {
1807                    // for gzip, last bytes contain LENGTH
1808                    if self.wrap != 0 && self.gzip_flags != 0 {
1809                        need_bits!(self, 32);
1810                        if (self.wrap & 4) != 0 && self.bit_reader.hold() != self.total as u64 {
1811                            self.mode = Mode::Bad;
1812                            break 'label self.bad("incorrect length check\0");
1813                        }
1814
1815                        self.bit_reader.init_bits();
1816                    }
1817
1818                    // inflate stream terminated properly
1819                    break 'label ReturnCode::StreamEnd;
1820                }
1821            };
1822        }
1823    }
1824
1825    fn bad(&mut self, msg: &'static str) -> ReturnCode {
1826        #[cfg(all(feature = "std", test))]
1827        dbg!(msg);
1828        self.error_message = Some(msg);
1829        self.inflate_leave(ReturnCode::DataError)
1830    }
1831
1832    // NOTE: it is crucial for the internal bookkeeping that this is the only route for actually
1833    // leaving the inflate function call chain
1834    fn inflate_leave(&mut self, return_code: ReturnCode) -> ReturnCode {
1835        // actual logic is in `inflate` itself
1836        return_code
1837    }
1838
1839    /// Stored in the `z_stream.data_type` field
1840    fn decoding_state(&self) -> i32 {
1841        let bit_reader_bits = self.bit_reader.bits_in_buffer() as i32;
1842        debug_assert!(bit_reader_bits < 64);
1843
1844        let last = if self.flags.contains(Flags::IS_LAST_BLOCK) {
1845            64
1846        } else {
1847            0
1848        };
1849
1850        let mode = match self.mode {
1851            Mode::Type => 128,
1852            Mode::Len_ | Mode::CopyBlock => 256,
1853            _ => 0,
1854        };
1855
1856        bit_reader_bits | last | mode
1857    }
1858}
1859
1860fn inflate_fast_help(state: &mut State, start: usize) {
1861    #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
1862    if crate::cpu_features::is_enabled_avx2() {
1863        // SAFETY: we've verified the target features
1864        return unsafe { inflate_fast_help_avx2(state, start) };
1865    }
1866
1867    inflate_fast_help_vanilla(state, start);
1868}
1869
1870#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
1871#[target_feature(enable = "avx2")]
1872unsafe fn inflate_fast_help_avx2(state: &mut State, start: usize) {
1873    inflate_fast_help_impl::<{ CpuFeatures::AVX2 }>(state, start);
1874}
1875
1876fn inflate_fast_help_vanilla(state: &mut State, start: usize) {
1877    inflate_fast_help_impl::<{ CpuFeatures::NONE }>(state, start);
1878}
1879
1880#[inline(always)]
1881fn inflate_fast_help_impl<const FEATURES: usize>(state: &mut State, _start: usize) {
1882    let mut bit_reader = BitReader::new(&[]);
1883    core::mem::swap(&mut bit_reader, &mut state.bit_reader);
1884
1885    let mut writer = Writer::new(&mut []);
1886    core::mem::swap(&mut writer, &mut state.writer);
1887
1888    let lcode = state.len_table_ref();
1889    let dcode = state.dist_table_ref();
1890
1891    // IDEA: use const generics for the bits here?
1892    let lmask = (1u64 << state.len_table.bits) - 1;
1893    let dmask = (1u64 << state.dist_table.bits) - 1;
1894
1895    // TODO verify if this is relevant for us
1896    let extra_safe = false;
1897
1898    let window_size = state.window.size();
1899
1900    let mut bad = None;
1901
1902    if bit_reader.bits_in_buffer() < 10 {
1903        bit_reader.refill();
1904    }
1905
1906    'outer: loop {
1907        let mut here = {
1908            let bits = bit_reader.bits_in_buffer();
1909            let hold = bit_reader.hold();
1910
1911            bit_reader.refill();
1912
1913            // in most cases, the read can be interleaved with the logic
1914            // based on benchmarks this matters in practice. wild.
1915            if bits as usize >= state.len_table.bits {
1916                lcode[(hold & lmask) as usize]
1917            } else {
1918                lcode[(bit_reader.hold() & lmask) as usize]
1919            }
1920        };
1921
1922        if here.op == 0 {
1923            writer.push(here.val as u8);
1924            bit_reader.drop_bits(here.bits);
1925            here = lcode[(bit_reader.hold() & lmask) as usize];
1926
1927            if here.op == 0 {
1928                writer.push(here.val as u8);
1929                bit_reader.drop_bits(here.bits);
1930                here = lcode[(bit_reader.hold() & lmask) as usize];
1931            }
1932        }
1933
1934        'dolen: loop {
1935            bit_reader.drop_bits(here.bits);
1936            let op = here.op;
1937
1938            if op == 0 {
1939                writer.push(here.val as u8);
1940            } else if op & 16 != 0 {
1941                let op = op & MAX_BITS;
1942                let mut len = here.val + bit_reader.bits(op as usize) as u16;
1943                bit_reader.drop_bits(op);
1944
1945                here = dcode[(bit_reader.hold() & dmask) as usize];
1946
1947                // we have two fast-path loads: 10+10 + 15+5 = 40,
1948                // but we may need to refill here in the worst case
1949                if bit_reader.bits_in_buffer() < MAX_BITS + MAX_DIST_EXTRA_BITS {
1950                    bit_reader.refill();
1951                }
1952
1953                'dodist: loop {
1954                    bit_reader.drop_bits(here.bits);
1955                    let op = here.op;
1956
1957                    if op & 16 != 0 {
1958                        let op = op & MAX_BITS;
1959                        let dist = here.val + bit_reader.bits(op as usize) as u16;
1960
1961                        if INFLATE_STRICT && dist as usize > state.dmax {
1962                            bad = Some("invalid distance too far back\0");
1963                            state.mode = Mode::Bad;
1964                            break 'outer;
1965                        }
1966
1967                        bit_reader.drop_bits(op);
1968
1969                        // max distance in output
1970                        let written = writer.len();
1971
1972                        if dist as usize > written {
1973                            // copy fropm the window
1974                            if (dist as usize - written) > state.window.have() {
1975                                if state.flags.contains(Flags::SANE) {
1976                                    bad = Some("invalid distance too far back\0");
1977                                    state.mode = Mode::Bad;
1978                                    break 'outer;
1979                                }
1980
1981                                panic!("INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR")
1982                            }
1983
1984                            let mut op = dist as usize - written;
1985                            let mut from;
1986
1987                            let window_next = state.window.next();
1988
1989                            if window_next == 0 {
1990                                // This case is hit when the window has just wrapped around
1991                                // by logic in `Window::extend`. It is special-cased because
1992                                // apparently this is quite common.
1993                                //
1994                                // the match is at the end of the window, even though the next
1995                                // position has now wrapped around.
1996                                from = window_size - op;
1997                            } else if window_next >= op {
1998                                // the standard case: a contiguous copy from the window, no wrapping
1999                                from = window_next - op;
2000                            } else {
2001                                // This case is hit when the window has recently wrapped around
2002                                // by logic in `Window::extend`.
2003                                //
2004                                // The match is (partially) at the end of the window
2005                                op -= window_next;
2006                                from = window_size - op;
2007
2008                                if op < len as usize {
2009                                    // This case is hit when part of the match is at the end of the
2010                                    // window, and part of it has wrapped around to the start. Copy
2011                                    // the end section here, the start section will be copied below.
2012                                    len -= op as u16;
2013                                    writer.extend_from_window_with_features::<FEATURES>(
2014                                        &state.window,
2015                                        from..from + op,
2016                                    );
2017                                    from = 0;
2018                                    op = window_next;
2019                                }
2020                            }
2021
2022                            let copy = Ord::min(op, len as usize);
2023                            writer.extend_from_window_with_features::<FEATURES>(
2024                                &state.window,
2025                                from..from + copy,
2026                            );
2027
2028                            if op < len as usize {
2029                                // here we need some bytes from the output itself
2030                                writer.copy_match_with_features::<FEATURES>(
2031                                    dist as usize,
2032                                    len as usize - op,
2033                                );
2034                            }
2035                        } else if extra_safe {
2036                            todo!()
2037                        } else {
2038                            writer.copy_match_with_features::<FEATURES>(dist as usize, len as usize)
2039                        }
2040                    } else if (op & 64) == 0 {
2041                        // 2nd level distance code
2042                        here = dcode[(here.val + bit_reader.bits(op as usize) as u16) as usize];
2043                        continue 'dodist;
2044                    } else {
2045                        bad = Some("invalid distance code\0");
2046                        state.mode = Mode::Bad;
2047                        break 'outer;
2048                    }
2049
2050                    break 'dodist;
2051                }
2052            } else if (op & 64) == 0 {
2053                // 2nd level length code
2054                here = lcode[(here.val + bit_reader.bits(op as usize) as u16) as usize];
2055                continue 'dolen;
2056            } else if op & 32 != 0 {
2057                // end of block
2058                state.mode = Mode::Type;
2059                break 'outer;
2060            } else {
2061                bad = Some("invalid literal/length code\0");
2062                state.mode = Mode::Bad;
2063                break 'outer;
2064            }
2065
2066            break 'dolen;
2067        }
2068
2069        // include the bits in the bit_reader buffer in the count of available bytes
2070        let remaining = bit_reader.bytes_remaining_including_buffer();
2071        if remaining >= INFLATE_FAST_MIN_HAVE && writer.remaining() >= INFLATE_FAST_MIN_LEFT {
2072            continue;
2073        }
2074
2075        break 'outer;
2076    }
2077
2078    // return unused bytes (on entry, bits < 8, so in won't go too far back)
2079    bit_reader.return_unused_bytes();
2080
2081    state.bit_reader = bit_reader;
2082    state.writer = writer;
2083
2084    if let Some(error_message) = bad {
2085        debug_assert!(matches!(state.mode, Mode::Bad));
2086        state.bad(error_message);
2087    }
2088}
2089
2090pub fn prime(stream: &mut InflateStream, bits: i32, value: i32) -> ReturnCode {
2091    if bits == 0 {
2092        /* fall through */
2093    } else if bits < 0 {
2094        stream.state.bit_reader.init_bits();
2095    } else if bits > 16 || stream.state.bit_reader.bits_in_buffer() + bits as u8 > 32 {
2096        return ReturnCode::StreamError;
2097    } else {
2098        stream.state.bit_reader.prime(bits as u8, value as u64);
2099    }
2100
2101    ReturnCode::Ok
2102}
2103
2104#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
2105pub struct InflateConfig {
2106    pub window_bits: i32,
2107}
2108
2109impl Default for InflateConfig {
2110    fn default() -> Self {
2111        Self {
2112            window_bits: DEF_WBITS,
2113        }
2114    }
2115}
2116
2117/// Initialize the stream in an inflate state
2118pub fn init(stream: &mut z_stream, config: InflateConfig) -> ReturnCode {
2119    stream.msg = core::ptr::null_mut();
2120
2121    // for safety we must really make sure that alloc and free are consistent
2122    // this is a (slight) deviation from stock zlib. In this crate we pick the rust
2123    // allocator as the default, but `libz-rs-sys` configures the C allocator
2124    #[cfg(feature = "rust-allocator")]
2125    if stream.zalloc.is_none() || stream.zfree.is_none() {
2126        stream.configure_default_rust_allocator()
2127    }
2128
2129    #[cfg(feature = "c-allocator")]
2130    if stream.zalloc.is_none() || stream.zfree.is_none() {
2131        stream.configure_default_c_allocator()
2132    }
2133
2134    if stream.zalloc.is_none() || stream.zfree.is_none() {
2135        return ReturnCode::StreamError;
2136    }
2137
2138    let mut state = State::new(&[], Writer::new(&mut []));
2139
2140    // TODO this can change depending on the used/supported SIMD instructions
2141    state.chunksize = 32;
2142
2143    let alloc = Allocator {
2144        zalloc: stream.zalloc.unwrap(),
2145        zfree: stream.zfree.unwrap(),
2146        opaque: stream.opaque,
2147        _marker: PhantomData,
2148    };
2149
2150    // allocated here to have the same order as zlib
2151    let Some(state_allocation) = alloc.allocate_raw::<State>() else {
2152        return ReturnCode::MemError;
2153    };
2154
2155    // FIXME: write is stable for NonNull since 1.80.0
2156    unsafe { state_allocation.as_ptr().write(state) };
2157    stream.state = state_allocation.as_ptr() as *mut internal_state;
2158
2159    // SAFETY: we've correctly initialized the stream to be an InflateStream
2160    let ret = if let Some(stream) = unsafe { InflateStream::from_stream_mut(stream) } {
2161        reset_with_config(stream, config)
2162    } else {
2163        ReturnCode::StreamError
2164    };
2165
2166    if ret != ReturnCode::Ok {
2167        let ptr = stream.state;
2168        stream.state = core::ptr::null_mut();
2169        // SAFETY: we assume deallocation does not cause UB
2170        unsafe { alloc.deallocate(ptr, 1) };
2171    }
2172
2173    ret
2174}
2175
2176pub fn reset_with_config(stream: &mut InflateStream, config: InflateConfig) -> ReturnCode {
2177    let mut window_bits = config.window_bits;
2178    let wrap;
2179
2180    if window_bits < 0 {
2181        wrap = 0;
2182
2183        if window_bits < -MAX_WBITS {
2184            return ReturnCode::StreamError;
2185        }
2186
2187        window_bits = -window_bits;
2188    } else {
2189        wrap = (window_bits >> 4) + 5; // TODO wth?
2190
2191        if window_bits < 48 {
2192            window_bits &= MAX_WBITS;
2193        }
2194    }
2195
2196    if window_bits != 0 && !(MIN_WBITS..=MAX_WBITS).contains(&window_bits) {
2197        #[cfg(feature = "std")]
2198        eprintln!("invalid windowBits");
2199        return ReturnCode::StreamError;
2200    }
2201
2202    if stream.state.window.size() != 0 && stream.state.wbits as i32 != window_bits {
2203        let mut window = Window::empty();
2204        core::mem::swap(&mut window, &mut stream.state.window);
2205
2206        let (ptr, len) = window.into_raw_parts();
2207        assert_ne!(len, 0);
2208        // SAFETY: window is discarded after this deallocation.
2209        unsafe { stream.alloc.deallocate(ptr, len) };
2210    }
2211
2212    stream.state.wrap = wrap as u8;
2213    stream.state.wbits = window_bits as _;
2214
2215    reset(stream)
2216}
2217
2218pub fn reset(stream: &mut InflateStream) -> ReturnCode {
2219    // reset the state of the window
2220    stream.state.window.clear();
2221
2222    stream.state.error_message = None;
2223
2224    reset_keep(stream)
2225}
2226
2227pub fn reset_keep(stream: &mut InflateStream) -> ReturnCode {
2228    stream.total_in = 0;
2229    stream.total_out = 0;
2230    stream.state.total = 0;
2231
2232    stream.msg = core::ptr::null_mut();
2233
2234    let state = &mut stream.state;
2235
2236    if state.wrap != 0 {
2237        // to support ill-conceived Java test suite
2238        stream.adler = (state.wrap & 1) as _;
2239    }
2240
2241    state.mode = Mode::Head;
2242    state.checksum = crate::ADLER32_INITIAL_VALUE as u32;
2243
2244    state.flags.update(Flags::IS_LAST_BLOCK, false);
2245    state.flags.update(Flags::HAVE_DICT, false);
2246    state.flags.update(Flags::SANE, true);
2247    state.gzip_flags = -1;
2248    state.dmax = 32768;
2249    state.head = None;
2250    state.bit_reader = BitReader::new(&[]);
2251
2252    state.next = 0;
2253    state.len_table = Table::default();
2254    state.dist_table = Table::default();
2255
2256    state.back = usize::MAX;
2257
2258    ReturnCode::Ok
2259}
2260
2261pub unsafe fn inflate(stream: &mut InflateStream, flush: InflateFlush) -> ReturnCode {
2262    if stream.next_out.is_null() || (stream.next_in.is_null() && stream.avail_in != 0) {
2263        return ReturnCode::StreamError as _;
2264    }
2265
2266    let state = &mut stream.state;
2267
2268    // skip check
2269    if let Mode::Type = state.mode {
2270        state.mode = Mode::TypeDo;
2271    }
2272
2273    state.flush = flush;
2274
2275    unsafe {
2276        state
2277            .bit_reader
2278            .update_slice(stream.next_in, stream.avail_in as usize)
2279    };
2280    state.writer = Writer::new_uninit(stream.next_out.cast(), stream.avail_out as usize);
2281
2282    state.in_available = stream.avail_in as _;
2283    state.out_available = stream.avail_out as _;
2284
2285    let mut err = state.dispatch();
2286
2287    let in_read = state.bit_reader.as_ptr() as usize - stream.next_in as usize;
2288    let out_written = state.out_available - (state.writer.capacity() - state.writer.len());
2289
2290    stream.total_in += in_read as z_size;
2291    state.total += out_written;
2292    stream.total_out = state.total as _;
2293
2294    stream.avail_in = state.bit_reader.bytes_remaining() as u32;
2295    stream.next_in = state.bit_reader.as_ptr() as *mut u8;
2296
2297    stream.avail_out = (state.writer.capacity() - state.writer.len()) as u32;
2298    stream.next_out = state.writer.next_out() as *mut u8;
2299
2300    stream.adler = state.checksum as z_checksum;
2301
2302    let valid_mode = |mode| !matches!(mode, Mode::Bad | Mode::Mem | Mode::Sync);
2303    let not_done = |mode| {
2304        !matches!(
2305            mode,
2306            Mode::Check | Mode::Length | Mode::Bad | Mode::Mem | Mode::Sync
2307        )
2308    };
2309
2310    let must_update_window = state.window.size() != 0
2311        || (out_written != 0
2312            && valid_mode(state.mode)
2313            && (not_done(state.mode) || !matches!(state.flush, InflateFlush::Finish)));
2314
2315    let update_checksum = state.wrap & 4 != 0;
2316
2317    if must_update_window {
2318        'blk: {
2319            // initialize the window if needed
2320            if state.window.size() == 0 {
2321                match Window::new_in(&stream.alloc, state.wbits as usize) {
2322                    Some(window) => state.window = window,
2323                    None => {
2324                        state.mode = Mode::Mem;
2325                        err = ReturnCode::MemError;
2326                        break 'blk;
2327                    }
2328                }
2329            }
2330
2331            state.window.extend(
2332                &state.writer.filled()[..out_written],
2333                state.gzip_flags,
2334                update_checksum,
2335                &mut state.checksum,
2336                &mut state.crc_fold,
2337            );
2338        }
2339    }
2340
2341    if let Some(msg) = state.error_message {
2342        assert!(msg.ends_with('\0'));
2343        stream.msg = msg.as_ptr() as *mut u8 as *mut core::ffi::c_char;
2344    }
2345
2346    stream.data_type = state.decoding_state();
2347
2348    if ((in_read == 0 && out_written == 0) || flush == InflateFlush::Finish as _)
2349        && err == (ReturnCode::Ok as _)
2350    {
2351        ReturnCode::BufError as _
2352    } else {
2353        err as _
2354    }
2355}
2356
2357fn syncsearch(mut got: usize, buf: &[u8]) -> (usize, usize) {
2358    let len = buf.len();
2359    let mut next = 0;
2360
2361    while next < len && got < 4 {
2362        if buf[next] == if got < 2 { 0 } else { 0xff } {
2363            got += 1;
2364        } else if buf[next] != 0 {
2365            got = 0;
2366        } else {
2367            got = 4 - got;
2368        }
2369        next += 1;
2370    }
2371
2372    (got, next)
2373}
2374
2375pub fn sync(stream: &mut InflateStream) -> ReturnCode {
2376    let state = &mut stream.state;
2377
2378    if stream.avail_in == 0 && state.bit_reader.bits_in_buffer() < 8 {
2379        return ReturnCode::BufError;
2380    }
2381    /* if first time, start search in bit buffer */
2382    if !matches!(state.mode, Mode::Sync) {
2383        state.mode = Mode::Sync;
2384
2385        let (buf, len) = state.bit_reader.start_sync_search();
2386
2387        (state.have, _) = syncsearch(0, &buf[..len]);
2388    }
2389
2390    // search available input
2391    // SAFETY: user guarantees that pointer and length are valid.
2392    let slice = unsafe { core::slice::from_raw_parts(stream.next_in, stream.avail_in as usize) };
2393
2394    let len;
2395    (state.have, len) = syncsearch(state.have, slice);
2396    // SAFETY: syncsearch() returns an index that is in-bounds of the slice.
2397    stream.next_in = unsafe { stream.next_in.add(len) };
2398    stream.avail_in -= len as u32;
2399    stream.total_in += len as z_size;
2400
2401    /* return no joy or set up to restart inflate() on a new block */
2402    if state.have != 4 {
2403        return ReturnCode::DataError;
2404    }
2405
2406    if state.gzip_flags == -1 {
2407        state.wrap = 0; /* if no header yet, treat as raw */
2408    } else {
2409        state.wrap &= !4; /* no point in computing a check value now */
2410    }
2411
2412    let flags = state.gzip_flags;
2413    let total_in = stream.total_in;
2414    let total_out = stream.total_out;
2415
2416    reset(stream);
2417
2418    stream.total_in = total_in;
2419    stream.total_out = total_out;
2420
2421    stream.state.gzip_flags = flags;
2422    stream.state.mode = Mode::Type;
2423
2424    ReturnCode::Ok
2425}
2426
2427/*
2428  Returns true if inflate is currently at the end of a block generated by
2429  Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
2430  implementation to provide an additional safety check. PPP uses
2431  Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
2432  block. When decompressing, PPP checks that at the end of input packet,
2433  inflate is waiting for these length bytes.
2434*/
2435pub fn sync_point(stream: &mut InflateStream) -> bool {
2436    matches!(stream.state.mode, Mode::Stored) && stream.state.bit_reader.bits_in_buffer() == 0
2437}
2438
2439pub unsafe fn copy<'a>(
2440    dest: &mut MaybeUninit<InflateStream<'a>>,
2441    source: &InflateStream<'a>,
2442) -> ReturnCode {
2443    if source.next_out.is_null() || (source.next_in.is_null() && source.avail_in != 0) {
2444        return ReturnCode::StreamError;
2445    }
2446
2447    // Safety: source and dest are both mutable references, so guaranteed not to overlap.
2448    // dest being a reference to maybe uninitialized memory makes a copy of 1 DeflateStream valid.
2449    unsafe {
2450        core::ptr::copy_nonoverlapping(source, dest.as_mut_ptr(), 1);
2451    }
2452
2453    // allocated here to have the same order as zlib
2454    let Some(state_allocation) = source.alloc.allocate_raw::<State>() else {
2455        return ReturnCode::MemError;
2456    };
2457
2458    let state = &source.state;
2459
2460    // SAFETY: an initialized Writer is a valid MaybeUninit<Writer>.
2461    let writer: MaybeUninit<Writer> =
2462        unsafe { core::ptr::read(&state.writer as *const _ as *const MaybeUninit<Writer>) };
2463
2464    let mut copy = State {
2465        mode: state.mode,
2466        flags: state.flags,
2467        wrap: state.wrap,
2468        len_table: state.len_table,
2469        dist_table: state.dist_table,
2470        wbits: state.wbits,
2471        window: Window::empty(),
2472        head: None,
2473        ncode: state.ncode,
2474        nlen: state.nlen,
2475        ndist: state.ndist,
2476        have: state.have,
2477        next: state.next,
2478        bit_reader: state.bit_reader,
2479        writer: Writer::new(&mut []),
2480        total: state.total,
2481        length: state.length,
2482        offset: state.offset,
2483        extra: state.extra,
2484        back: state.back,
2485        was: state.was,
2486        chunksize: state.chunksize,
2487        in_available: state.in_available,
2488        out_available: state.out_available,
2489        lens: state.lens,
2490        work: state.work,
2491        error_message: state.error_message,
2492        flush: state.flush,
2493        checksum: state.checksum,
2494        crc_fold: state.crc_fold,
2495        dmax: state.dmax,
2496        gzip_flags: state.gzip_flags,
2497        codes_codes: state.codes_codes,
2498        len_codes: state.len_codes,
2499        dist_codes: state.dist_codes,
2500    };
2501
2502    if !state.window.is_empty() {
2503        let Some(window) = state.window.clone_in(&source.alloc) else {
2504            // SAFETY: state_allocation is not used again.
2505            source.alloc.deallocate(state_allocation.as_ptr(), 1);
2506            return ReturnCode::MemError;
2507        };
2508
2509        copy.window = window;
2510    }
2511
2512    // write the cloned state into state_ptr
2513    unsafe { state_allocation.as_ptr().write(copy) }; // FIXME: write is stable for NonNull since 1.80.0
2514
2515    // insert the state_ptr into `dest`
2516    let field_ptr = unsafe { core::ptr::addr_of_mut!((*dest.as_mut_ptr()).state) };
2517    unsafe { core::ptr::write(field_ptr as *mut *mut State, state_allocation.as_ptr()) };
2518
2519    // update the writer; it cannot be cloned so we need to use some shennanigans
2520    let field_ptr = unsafe { core::ptr::addr_of_mut!((*dest.as_mut_ptr()).state.writer) };
2521    unsafe { core::ptr::copy(writer.as_ptr(), field_ptr, 1) };
2522
2523    // update the gzhead field (it contains a mutable reference so we need to be careful
2524    let field_ptr = unsafe { core::ptr::addr_of_mut!((*dest.as_mut_ptr()).state.head) };
2525    unsafe { core::ptr::copy(&source.state.head, field_ptr, 1) };
2526
2527    ReturnCode::Ok
2528}
2529
2530pub fn undermine(stream: &mut InflateStream, subvert: i32) -> ReturnCode {
2531    stream.state.flags.update(Flags::SANE, (!subvert) != 0);
2532
2533    ReturnCode::Ok
2534}
2535
2536pub fn mark(stream: &InflateStream) -> c_long {
2537    if stream.next_out.is_null() || (stream.next_in.is_null() && stream.avail_in != 0) {
2538        return c_long::MIN;
2539    }
2540
2541    let state = &stream.state;
2542
2543    let length = match state.mode {
2544        Mode::CopyBlock => state.length,
2545        Mode::Match => state.was - state.length,
2546        _ => 0,
2547    };
2548
2549    (((state.back as c_long) as c_ulong) << 16) as c_long + length as c_long
2550}
2551
2552pub fn set_dictionary(stream: &mut InflateStream, dictionary: &[u8]) -> ReturnCode {
2553    if stream.state.wrap != 0 && !matches!(stream.state.mode, Mode::Dict) {
2554        return ReturnCode::StreamError;
2555    }
2556
2557    // check for correct dictionary identifier
2558    if matches!(stream.state.mode, Mode::Dict) {
2559        let dictid = adler32(1, dictionary);
2560
2561        if dictid != stream.state.checksum {
2562            return ReturnCode::DataError;
2563        }
2564    }
2565
2566    let err = 'blk: {
2567        // initialize the window if needed
2568        if stream.state.window.size() == 0 {
2569            match Window::new_in(&stream.alloc, stream.state.wbits as usize) {
2570                None => break 'blk ReturnCode::MemError,
2571                Some(window) => stream.state.window = window,
2572            }
2573        }
2574
2575        stream.state.window.extend(
2576            dictionary,
2577            stream.state.gzip_flags,
2578            false,
2579            &mut stream.state.checksum,
2580            &mut stream.state.crc_fold,
2581        );
2582
2583        ReturnCode::Ok
2584    };
2585
2586    if err != ReturnCode::Ok {
2587        stream.state.mode = Mode::Mem;
2588        return ReturnCode::MemError;
2589    }
2590
2591    stream.state.flags.update(Flags::HAVE_DICT, true);
2592
2593    ReturnCode::Ok
2594}
2595
2596pub fn end<'a>(stream: &'a mut InflateStream<'a>) -> &'a mut z_stream {
2597    let alloc = stream.alloc;
2598
2599    let mut window = Window::empty();
2600    core::mem::swap(&mut window, &mut stream.state.window);
2601
2602    // safety: window is not used again
2603    if !window.is_empty() {
2604        let (ptr, len) = window.into_raw_parts();
2605        unsafe { alloc.deallocate(ptr, len) };
2606    }
2607
2608    let stream = stream.as_z_stream_mut();
2609
2610    let state_ptr = core::mem::replace(&mut stream.state, core::ptr::null_mut());
2611
2612    // safety: state_ptr is not used again
2613    unsafe { alloc.deallocate(state_ptr as *mut State, 1) };
2614
2615    stream
2616}
2617
2618/// # Safety
2619///
2620/// The caller must guarantee:
2621///
2622/// * If `head` is `Some`:
2623///     - If `head.extra` is not NULL, it must be writable for at least `head.extra_max` bytes
2624///     - if `head.name` is not NULL, it must be writable for at least `head.name_max` bytes
2625///     - if `head.comment` is not NULL, it must be writable for at least `head.comm_max` bytes
2626pub unsafe fn get_header<'a>(
2627    stream: &mut InflateStream<'a>,
2628    head: Option<&'a mut gz_header>,
2629) -> ReturnCode {
2630    if (stream.state.wrap & 2) == 0 {
2631        return ReturnCode::StreamError;
2632    }
2633
2634    stream.state.head = head.map(|head| {
2635        head.done = 0;
2636        head
2637    });
2638    ReturnCode::Ok
2639}
2640#[cfg(test)]
2641mod tests {
2642    use super::*;
2643
2644    #[test]
2645    fn uncompress_buffer_overflow() {
2646        let mut output = [0; 1 << 13];
2647        let input = [
2648            72, 137, 58, 0, 3, 39, 255, 255, 255, 255, 255, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2649            14, 14, 184, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 184, 14, 14,
2650            14, 14, 14, 14, 14, 63, 14, 14, 14, 14, 14, 14, 14, 14, 184, 14, 14, 255, 14, 103, 14,
2651            14, 14, 14, 14, 14, 61, 14, 255, 255, 63, 14, 14, 14, 14, 14, 14, 14, 14, 184, 14, 14,
2652            255, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 6, 14, 14, 14, 14, 14, 14, 14, 14, 71,
2653            4, 137, 106,
2654        ];
2655
2656        let config = InflateConfig { window_bits: 15 };
2657
2658        let (_decompressed, err) = uncompress_slice(&mut output, &input, config);
2659        assert_eq!(err, ReturnCode::DataError);
2660    }
2661}