1#![allow(non_snake_case)] #![allow(clippy::missing_safety_doc)] use 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 infback;
11mod inffixed_tbl;
12mod inftrees;
13mod window;
14mod writer;
15
16use crate::allocate::Allocator;
17use crate::c_api::internal_state;
18use crate::cpu_features::CpuFeatures;
19use crate::{
20 adler32::adler32,
21 c_api::{gz_header, z_checksum, z_size, z_stream, Z_DEFLATED},
22 inflate::writer::Writer,
23 traceln, Code, InflateFlush, ReturnCode, DEF_WBITS, MAX_WBITS, MIN_WBITS,
24};
25
26use crate::crc32::{crc32, Crc32Fold};
27
28pub use self::infback::{back, back_end, back_init};
29pub use self::window::Window;
30use self::{
31 bitreader::BitReader,
32 inftrees::{inflate_table, CodeType, InflateTable},
33};
34
35const INFLATE_STRICT: bool = false;
36
37#[repr(C)]
40pub struct InflateStream<'a> {
41 pub(crate) next_in: *mut crate::c_api::Bytef,
42 pub(crate) avail_in: crate::c_api::uInt,
43 pub(crate) total_in: crate::c_api::z_size,
44 pub(crate) next_out: *mut crate::c_api::Bytef,
45 pub(crate) avail_out: crate::c_api::uInt,
46 pub(crate) total_out: crate::c_api::z_size,
47 pub(crate) msg: *mut c_char,
48 pub(crate) state: &'a mut State<'a>,
49 pub(crate) alloc: Allocator<'a>,
50 pub(crate) data_type: c_int,
51 pub(crate) adler: crate::c_api::z_checksum,
52 pub(crate) reserved: crate::c_api::uLong,
53}
54
55unsafe impl Sync for InflateStream<'_> {}
56unsafe impl Send for InflateStream<'_> {}
57
58#[cfg(feature = "__internal-test")]
59#[doc(hidden)]
60pub const INFLATE_STATE_SIZE: usize = core::mem::size_of::<crate::inflate::State>();
61
62#[cfg(feature = "__internal-test")]
63#[doc(hidden)]
64pub unsafe fn set_mode_dict(strm: &mut z_stream) {
65 unsafe {
66 (*(strm.state as *mut State)).mode = Mode::Dict;
67 }
68}
69
70#[cfg(feature = "__internal-test")]
71#[doc(hidden)]
72pub unsafe fn set_mode_sync(strm: *mut z_stream) {
73 unsafe {
74 (*((*strm).state as *mut State)).mode = Mode::Sync;
75 }
76}
77
78impl<'a> InflateStream<'a> {
79 const _S: () = assert!(core::mem::size_of::<z_stream>() == core::mem::size_of::<Self>());
82 const _A: () = assert!(core::mem::align_of::<z_stream>() == core::mem::align_of::<Self>());
83
84 #[inline(always)]
93 pub unsafe fn from_stream_ref(strm: *const z_stream) -> Option<&'a Self> {
94 {
95 let stream = unsafe { strm.as_ref() }?;
97
98 if stream.zalloc.is_none() || stream.zfree.is_none() {
99 return None;
100 }
101
102 if stream.state.is_null() {
103 return None;
104 }
105 }
106
107 unsafe { strm.cast::<InflateStream>().as_ref() }
109 }
110
111 #[inline(always)]
120 pub unsafe fn from_stream_mut(strm: *mut z_stream) -> Option<&'a mut Self> {
121 {
122 let stream = unsafe { strm.as_ref() }?;
124
125 if stream.zalloc.is_none() || stream.zfree.is_none() {
126 return None;
127 }
128
129 if stream.state.is_null() {
130 return None;
131 }
132 }
133
134 unsafe { strm.cast::<InflateStream>().as_mut() }
136 }
137
138 fn as_z_stream_mut(&mut self) -> &mut z_stream {
139 unsafe { &mut *(self as *mut _ as *mut z_stream) }
141 }
142
143 pub fn new(config: InflateConfig) -> Self {
144 let mut inner = crate::c_api::z_stream::default();
145
146 let ret = crate::inflate::init(&mut inner, config);
147 assert_eq!(ret, ReturnCode::Ok);
148
149 unsafe { core::mem::transmute(inner) }
150 }
151}
152
153const MAX_BITS: u8 = 15; const MAX_DIST_EXTRA_BITS: u8 = 13; pub fn decompress_slice<'a>(
173 output: &'a mut [u8],
174 input: &[u8],
175 config: InflateConfig,
176) -> (&'a mut [u8], ReturnCode) {
177 let output_uninit = unsafe {
179 core::slice::from_raw_parts_mut(output.as_mut_ptr() as *mut MaybeUninit<u8>, output.len())
180 };
181
182 uncompress(output_uninit, input, config)
183}
184
185pub fn uncompress<'a>(
187 output: &'a mut [MaybeUninit<u8>],
188 input: &[u8],
189 config: InflateConfig,
190) -> (&'a mut [u8], ReturnCode) {
191 let (_consumed, output, ret) = uncompress2(output, input, config);
192 (output, ret)
193}
194
195pub fn uncompress2<'a>(
196 output: &'a mut [MaybeUninit<u8>],
197 input: &[u8],
198 config: InflateConfig,
199) -> (u64, &'a mut [u8], ReturnCode) {
200 let mut dest_len_ptr = output.len() as z_checksum;
201
202 let mut buf = [0u8];
204
205 let mut left;
206 let mut len = input.len() as u64;
207
208 let dest = if output.is_empty() {
209 left = 1;
210
211 buf.as_mut_ptr()
212 } else {
213 left = output.len() as u64;
214 dest_len_ptr = 0;
215
216 output.as_mut_ptr() as *mut u8
217 };
218
219 let mut stream = z_stream {
220 next_in: input.as_ptr() as *mut u8,
221 avail_in: 0,
222
223 zalloc: None,
224 zfree: None,
225 opaque: core::ptr::null_mut(),
226
227 ..z_stream::default()
228 };
229
230 let err = init(&mut stream, config);
231 if err != ReturnCode::Ok {
232 return (0, &mut [], err);
233 }
234
235 stream.next_out = dest;
236 stream.avail_out = 0;
237
238 let Some(stream) = (unsafe { InflateStream::from_stream_mut(&mut stream) }) else {
239 return (0, &mut [], ReturnCode::StreamError);
240 };
241
242 let err = loop {
243 if stream.avail_out == 0 {
244 stream.avail_out = Ord::min(left, u32::MAX as u64) as u32;
245 left -= stream.avail_out as u64;
246 }
247
248 if stream.avail_in == 0 {
249 stream.avail_in = Ord::min(len, u32::MAX as u64) as u32;
250 len -= stream.avail_in as u64;
251 }
252
253 let err = unsafe { inflate(stream, InflateFlush::NoFlush) };
254
255 if err != ReturnCode::Ok {
256 break err;
257 }
258 };
259
260 let consumed = len + u64::from(stream.avail_in);
261 if !output.is_empty() {
262 dest_len_ptr = stream.total_out;
263 } else if stream.total_out != 0 && err == ReturnCode::BufError {
264 left = 1;
265 }
266
267 let avail_out = stream.avail_out;
268
269 end(stream);
270
271 let ret = match err {
272 ReturnCode::StreamEnd => ReturnCode::Ok,
273 ReturnCode::NeedDict => ReturnCode::DataError,
274 ReturnCode::BufError if (left + avail_out as u64) != 0 => ReturnCode::DataError,
275 _ => err,
276 };
277
278 let output_slice = unsafe {
280 core::slice::from_raw_parts_mut(output.as_mut_ptr() as *mut u8, dest_len_ptr as usize)
281 };
282
283 (consumed, output_slice, ret)
284}
285
286#[derive(Debug, Clone, Copy)]
287#[repr(u8)]
288pub enum Mode {
289 Head,
290 Flags,
291 Time,
292 Os,
293 ExLen,
294 Extra,
295 Name,
296 Comment,
297 HCrc,
298 Sync,
299 Mem,
300 Length,
301 Type,
302 TypeDo,
303 Stored,
304 CopyBlock,
305 Check,
306 Len_,
307 Len,
308 Lit,
309 LenExt,
310 Dist,
311 DistExt,
312 Match,
313 Table,
314 LenLens,
315 CodeLens,
316 DictId,
317 Dict,
318 Done,
319 Bad,
320}
321
322#[derive(Default, Clone, Copy)]
323#[allow(clippy::enum_variant_names)]
324enum Codes {
325 #[default]
326 Fixed,
327 Codes,
328 Len,
329 Dist,
330}
331
332#[derive(Default, Clone, Copy)]
333struct Table {
334 codes: Codes,
335 bits: usize,
336}
337
338#[derive(Clone, Copy)]
339struct Flags(u8);
340
341impl Default for Flags {
342 fn default() -> Self {
343 Self::SANE
344 }
345}
346
347impl Flags {
348 const IS_LAST_BLOCK: Self = Self(0b0000_0001);
350
351 const HAVE_DICT: Self = Self(0b0000_0010);
353
354 const SANE: Self = Self(0b0000_0100);
356
357 pub(crate) const fn contains(self, other: Self) -> bool {
358 debug_assert!(other.0.count_ones() == 1);
359
360 self.0 & other.0 != 0
361 }
362
363 #[inline(always)]
364 pub(crate) fn update(&mut self, other: Self, value: bool) {
365 if value {
366 *self = Self(self.0 | other.0);
367 } else {
368 *self = Self(self.0 & !other.0);
369 }
370 }
371}
372
373#[repr(C, align(64))]
374pub(crate) struct State<'a> {
375 mode: Mode,
377
378 flags: Flags,
379
380 wbits: u8,
382
383 wrap: u8,
389
390 flush: InflateFlush,
391
392 window: Window<'a>,
394
395 ncode: usize,
398 nlen: usize,
400 ndist: usize,
402 have: usize,
404 next: usize, bit_reader: BitReader<'a>,
409
410 writer: Writer<'a>,
411 total: usize,
412
413 length: usize,
415 offset: usize,
417
418 extra: usize,
420
421 back: usize,
423
424 was: usize,
426
427 chunksize: usize,
429
430 in_available: usize,
431 out_available: usize,
432
433 gzip_flags: i32,
434
435 checksum: u32,
436 crc_fold: Crc32Fold,
437
438 error_message: Option<&'static str>,
439
440 head: Option<&'a mut gz_header>,
442 dmax: usize,
443
444 len_table: Table,
446
447 dist_table: Table,
449
450 codes_codes: [Code; crate::ENOUGH_LENS],
451 len_codes: [Code; crate::ENOUGH_LENS],
452 dist_codes: [Code; crate::ENOUGH_DISTS],
453
454 lens: [u16; 320],
456 work: [u16; 288],
458
459 allocation_start: *mut u8,
460 total_allocation_size: usize,
461}
462
463impl<'a> State<'a> {
464 fn new(reader: &'a [u8], writer: Writer<'a>) -> Self {
465 let in_available = reader.len();
466 let out_available = writer.capacity();
467
468 Self {
469 flush: InflateFlush::NoFlush,
470
471 flags: Flags::default(),
472 wrap: 0,
473 mode: Mode::Head,
474 length: 0,
475
476 len_table: Table::default(),
477 dist_table: Table::default(),
478
479 wbits: 0,
480 offset: 0,
481 extra: 0,
482 back: 0,
483 was: 0,
484 chunksize: 0,
485 in_available,
486 out_available,
487
488 bit_reader: BitReader::new(reader),
489
490 writer,
491 total: 0,
492
493 window: Window::empty(),
494 head: None,
495
496 lens: [0u16; 320],
497 work: [0u16; 288],
498
499 ncode: 0,
500 nlen: 0,
501 ndist: 0,
502 have: 0,
503 next: 0,
504
505 error_message: None,
506
507 checksum: 0,
508 crc_fold: Crc32Fold::new(),
509
510 dmax: 0,
511 gzip_flags: 0,
512
513 codes_codes: [Code::default(); crate::ENOUGH_LENS],
514 len_codes: [Code::default(); crate::ENOUGH_LENS],
515 dist_codes: [Code::default(); crate::ENOUGH_DISTS],
516
517 allocation_start: core::ptr::null_mut(),
518 total_allocation_size: 0,
519 }
520 }
521
522 fn len_table_ref(&self) -> &[Code] {
523 match self.len_table.codes {
524 Codes::Fixed => &self::inffixed_tbl::LENFIX,
525 Codes::Codes => &self.codes_codes,
526 Codes::Len => &self.len_codes,
527 Codes::Dist => &self.dist_codes,
528 }
529 }
530
531 fn dist_table_ref(&self) -> &[Code] {
532 match self.dist_table.codes {
533 Codes::Fixed => &self::inffixed_tbl::DISTFIX,
534 Codes::Codes => &self.codes_codes,
535 Codes::Len => &self.len_codes,
536 Codes::Dist => &self.dist_codes,
537 }
538 }
539
540 fn len_table_get(&self, index: usize) -> Code {
541 self.len_table_ref()[index]
542 }
543
544 fn dist_table_get(&self, index: usize) -> Code {
545 self.dist_table_ref()[index]
546 }
547}
548
549const fn zswap32(q: u32) -> u32 {
551 u32::from_be(q.to_le())
552}
553
554const INFLATE_FAST_MIN_HAVE: usize = 15;
555const INFLATE_FAST_MIN_LEFT: usize = 260;
556
557impl State<'_> {
558 fn len_and_friends(&mut self) -> ControlFlow<ReturnCode, ()> {
568 let avail_in = self.bit_reader.bytes_remaining();
569 let avail_out = self.writer.remaining();
570
571 if avail_in >= INFLATE_FAST_MIN_HAVE && avail_out >= INFLATE_FAST_MIN_LEFT {
572 unsafe { inflate_fast_help(self, 0) };
574 match self.mode {
575 Mode::Len => {}
576 _ => return ControlFlow::Continue(()),
577 }
578 }
579
580 let mut mode;
581 let mut writer;
582 let mut bit_reader;
583
584 macro_rules! load {
585 () => {
586 mode = self.mode;
587 writer = core::mem::replace(&mut self.writer, Writer::new(&mut []));
588 bit_reader = self.bit_reader;
589 };
590 }
591
592 macro_rules! restore {
593 () => {
594 self.mode = mode;
595 self.writer = writer;
596 self.bit_reader = bit_reader;
597 };
598 }
599
600 load!();
601
602 let len_table = match self.len_table.codes {
603 Codes::Fixed => &self::inffixed_tbl::LENFIX[..],
604 Codes::Codes => &self.codes_codes,
605 Codes::Len => &self.len_codes,
606 Codes::Dist => &self.dist_codes,
607 };
608
609 let dist_table = match self.dist_table.codes {
610 Codes::Fixed => &self::inffixed_tbl::DISTFIX[..],
611 Codes::Codes => &self.codes_codes,
612 Codes::Len => &self.len_codes,
613 Codes::Dist => &self.dist_codes,
614 };
615
616 loop {
617 mode = 'top: {
618 match mode {
619 Mode::Len => {
620 let avail_in = bit_reader.bytes_remaining();
621 let avail_out = writer.remaining();
622
623 if avail_in >= INFLATE_FAST_MIN_HAVE && avail_out >= INFLATE_FAST_MIN_LEFT {
628 restore!();
629 unsafe { inflate_fast_help(self, 0) };
633 return ControlFlow::Continue(());
634 }
635
636 self.back = 0;
637
638 let mut here;
640 loop {
641 let bits = bit_reader.bits(self.len_table.bits);
642 here = len_table[bits as usize];
643
644 if here.bits <= bit_reader.bits_in_buffer() {
645 break;
646 }
647
648 if let Err(return_code) = bit_reader.pull_byte() {
649 restore!();
650 return ControlFlow::Break(return_code);
651 };
652 }
653
654 if here.op != 0 && here.op & 0xf0 == 0 {
655 let last = here;
656 loop {
657 let bits = bit_reader.bits((last.bits + last.op) as usize) as u16;
658 here = len_table[(last.val + (bits >> last.bits)) as usize];
659 if last.bits + here.bits <= bit_reader.bits_in_buffer() {
660 break;
661 }
662
663 if let Err(return_code) = bit_reader.pull_byte() {
664 restore!();
665 return ControlFlow::Break(return_code);
666 };
667 }
668
669 bit_reader.drop_bits(last.bits);
670 self.back += last.bits as usize;
671 }
672
673 bit_reader.drop_bits(here.bits);
674 self.back += here.bits as usize;
675 self.length = here.val as usize;
676
677 if here.op == 0 {
678 break 'top Mode::Lit;
679 } else if here.op & 32 != 0 {
680 traceln!("inflate: end of block");
683
684 self.back = usize::MAX;
685 mode = Mode::Type;
686
687 restore!();
688 return ControlFlow::Continue(());
689 } else if here.op & 64 != 0 {
690 mode = Mode::Bad;
691 {
692 restore!();
693 let this = &mut *self;
694 let msg: &'static str = "invalid literal/length code\0";
695 #[cfg(all(feature = "std", test))]
696 dbg!(msg);
697 this.error_message = Some(msg);
698 return ControlFlow::Break(ReturnCode::DataError);
699 }
700 } else {
701 self.extra = (here.op & MAX_BITS) as usize;
703 break 'top Mode::LenExt;
704 }
705 }
706 Mode::Lit => {
707 if writer.is_full() {
709 restore!();
710 traceln!("Ok: writer is full ({} bytes)", self.writer.capacity());
711 return ControlFlow::Break(ReturnCode::Ok);
712 }
713
714 writer.push(self.length as u8);
715
716 break 'top Mode::Len;
717 }
718 Mode::LenExt => {
719 let extra = self.extra;
721
722 if extra != 0 {
724 match bit_reader.need_bits(extra) {
725 Err(return_code) => {
726 restore!();
727 return ControlFlow::Break(return_code);
728 }
729 Ok(v) => v,
730 };
731 self.length += bit_reader.bits(extra) as usize;
732 bit_reader.drop_bits(extra as u8);
733 self.back += extra;
734 }
735
736 traceln!("inflate: length {}", state.length);
737
738 self.was = self.length;
739
740 break 'top Mode::Dist;
741 }
742 Mode::Dist => {
743 let mut here;
747 loop {
748 let bits = bit_reader.bits(self.dist_table.bits) as usize;
749 here = dist_table[bits];
750 if here.bits <= bit_reader.bits_in_buffer() {
751 break;
752 }
753
754 if let Err(return_code) = bit_reader.pull_byte() {
755 restore!();
756 return ControlFlow::Break(return_code);
757 };
758 }
759
760 if here.op & 0xf0 == 0 {
761 let last = here;
762
763 loop {
764 let bits = bit_reader.bits((last.bits + last.op) as usize);
765 here =
766 dist_table[last.val as usize + ((bits as usize) >> last.bits)];
767
768 if last.bits + here.bits <= bit_reader.bits_in_buffer() {
769 break;
770 }
771
772 if let Err(return_code) = bit_reader.pull_byte() {
773 restore!();
774 return ControlFlow::Break(return_code);
775 };
776 }
777
778 bit_reader.drop_bits(last.bits);
779 self.back += last.bits as usize;
780 }
781
782 bit_reader.drop_bits(here.bits);
783
784 if here.op & 64 != 0 {
785 restore!();
786 self.mode = Mode::Bad;
787 return ControlFlow::Break(self.bad("invalid distance code\0"));
788 }
789
790 self.offset = here.val as usize;
791
792 self.extra = (here.op & MAX_BITS) as usize;
793
794 break 'top Mode::DistExt;
795 }
796 Mode::DistExt => {
797 let extra = self.extra;
799
800 if extra > 0 {
801 match bit_reader.need_bits(extra) {
802 Err(return_code) => {
803 restore!();
804 return ControlFlow::Break(return_code);
805 }
806 Ok(v) => v,
807 };
808 self.offset += bit_reader.bits(extra) as usize;
809 bit_reader.drop_bits(extra as u8);
810 self.back += extra;
811 }
812
813 if INFLATE_STRICT && self.offset > self.dmax {
814 restore!();
815 self.mode = Mode::Bad;
816 return ControlFlow::Break(
817 self.bad("invalid distance code too far back\0"),
818 );
819 }
820
821 traceln!("inflate: distance {}", state.offset);
822
823 break 'top Mode::Match;
824 }
825 Mode::Match => {
826 if writer.is_full() {
828 restore!();
829 traceln!(
830 "BufError: writer is full ({} bytes)",
831 self.writer.capacity()
832 );
833 return ControlFlow::Break(ReturnCode::Ok);
834 }
835
836 let left = writer.remaining();
837 let copy = writer.len();
838
839 let copy = if self.offset > copy {
840 let mut copy = self.offset - copy;
843
844 if copy > self.window.have() {
845 if self.flags.contains(Flags::SANE) {
846 restore!();
847 self.mode = Mode::Bad;
848 return ControlFlow::Break(
849 self.bad("invalid distance too far back\0"),
850 );
851 }
852
853 panic!("INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR")
855 }
856
857 let wnext = self.window.next();
858 let wsize = self.window.size();
859
860 let from = if copy > wnext {
861 copy -= wnext;
862 wsize - copy
863 } else {
864 wnext - copy
865 };
866
867 copy = Ord::min(copy, self.length);
868 copy = Ord::min(copy, left);
869
870 writer.extend_from_window(&self.window, from..from + copy);
871
872 copy
873 } else {
874 let copy = Ord::min(self.length, left);
875 writer.copy_match(self.offset, copy);
876
877 copy
878 };
879
880 self.length -= copy;
881
882 if self.length == 0 {
883 break 'top Mode::Len;
884 } else {
885 break 'top Mode::Match;
888 }
889 }
890 _ => unsafe { core::hint::unreachable_unchecked() },
891 }
892 }
893 }
894 }
895
896 fn dispatch(&mut self) -> ReturnCode {
897 let mut mode = self.mode;
899
900 macro_rules! pull_byte {
901 ($self:expr) => {
902 match $self.bit_reader.pull_byte() {
903 Err(return_code) => {
904 self.mode = mode;
905 return $self.inflate_leave(return_code);
906 }
907 Ok(_) => (),
908 }
909 };
910 }
911
912 macro_rules! need_bits {
913 ($self:expr, $n:expr) => {
914 match $self.bit_reader.need_bits($n) {
915 Err(return_code) => {
916 self.mode = mode;
917 return $self.inflate_leave(return_code);
918 }
919 Ok(v) => v,
920 }
921 };
922 }
923
924 let ret = 'label: loop {
925 mode = 'blk: {
926 match mode {
927 Mode::Head => {
928 if self.wrap == 0 {
929 break 'blk Mode::TypeDo;
930 }
931
932 need_bits!(self, 16);
933
934 if (self.wrap & 2) != 0 && self.bit_reader.hold() == 0x8b1f {
936 if self.wbits == 0 {
937 self.wbits = 15;
938 }
939
940 let b0 = self.bit_reader.bits(8) as u8;
941 let b1 = (self.bit_reader.hold() >> 8) as u8;
942 self.checksum = crc32(crate::CRC32_INITIAL_VALUE, &[b0, b1]);
943 self.bit_reader.init_bits();
944
945 break 'blk Mode::Flags;
946 }
947
948 if let Some(header) = &mut self.head {
949 header.done = -1;
950 }
951
952 if (self.wrap & 1) == 0
954 || ((self.bit_reader.bits(8) << 8) + (self.bit_reader.hold() >> 8)) % 31
955 != 0
956 {
957 mode = Mode::Bad;
958 break 'label self.bad("incorrect header check\0");
959 }
960
961 if self.bit_reader.bits(4) != Z_DEFLATED as u64 {
962 mode = Mode::Bad;
963 break 'label self.bad("unknown compression method\0");
964 }
965
966 self.bit_reader.drop_bits(4);
967 let len = self.bit_reader.bits(4) as u8 + 8;
968
969 if self.wbits == 0 {
970 self.wbits = len;
971 }
972
973 if len as i32 > MAX_WBITS || len > self.wbits {
974 mode = Mode::Bad;
975 break 'label self.bad("invalid window size\0");
976 }
977
978 self.dmax = 1 << len;
979 self.gzip_flags = 0; self.checksum = crate::ADLER32_INITIAL_VALUE as _;
981
982 if self.bit_reader.hold() & 0x200 != 0 {
983 self.bit_reader.init_bits();
984
985 break 'blk Mode::DictId;
986 } else {
987 self.bit_reader.init_bits();
988
989 break 'blk Mode::Type;
990 }
991 }
992 Mode::Flags => {
993 need_bits!(self, 16);
994 self.gzip_flags = self.bit_reader.hold() as i32;
995
996 if self.gzip_flags & 0xff != Z_DEFLATED {
998 mode = Mode::Bad;
999 break 'label self.bad("unknown compression method\0");
1000 }
1001
1002 if self.gzip_flags & 0xe000 != 0 {
1003 mode = Mode::Bad;
1004 break 'label self.bad("unknown header flags set\0");
1005 }
1006
1007 if let Some(head) = self.head.as_mut() {
1008 head.text = ((self.bit_reader.hold() >> 8) & 1) as i32;
1009 }
1010
1011 if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1012 let b0 = self.bit_reader.bits(8) as u8;
1013 let b1 = (self.bit_reader.hold() >> 8) as u8;
1014 self.checksum = crc32(self.checksum, &[b0, b1]);
1015 }
1016
1017 self.bit_reader.init_bits();
1018
1019 break 'blk Mode::Time;
1020 }
1021 Mode::Time => {
1022 need_bits!(self, 32);
1023 if let Some(head) = self.head.as_mut() {
1024 head.time = self.bit_reader.hold() as z_size;
1025 }
1026
1027 if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1028 let bytes = (self.bit_reader.hold() as u32).to_le_bytes();
1029 self.checksum = crc32(self.checksum, &bytes);
1030 }
1031
1032 self.bit_reader.init_bits();
1033
1034 break 'blk Mode::Os;
1035 }
1036 Mode::Os => {
1037 need_bits!(self, 16);
1038 if let Some(head) = self.head.as_mut() {
1039 head.xflags = (self.bit_reader.hold() & 0xff) as i32;
1040 head.os = (self.bit_reader.hold() >> 8) as i32;
1041 }
1042
1043 if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1044 let bytes = (self.bit_reader.hold() as u16).to_le_bytes();
1045 self.checksum = crc32(self.checksum, &bytes);
1046 }
1047
1048 self.bit_reader.init_bits();
1049
1050 break 'blk Mode::ExLen;
1051 }
1052 Mode::ExLen => {
1053 if (self.gzip_flags & 0x0400) != 0 {
1054 need_bits!(self, 16);
1055
1056 self.length = self.bit_reader.hold() as usize;
1058 if let Some(head) = self.head.as_mut() {
1059 head.extra_len = self.length as u32;
1060 }
1061
1062 if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1063 let bytes = (self.bit_reader.hold() as u16).to_le_bytes();
1064 self.checksum = crc32(self.checksum, &bytes);
1065 }
1066 self.bit_reader.init_bits();
1067 } else if let Some(head) = self.head.as_mut() {
1068 head.extra = core::ptr::null_mut();
1069 }
1070
1071 break 'blk Mode::Extra;
1072 }
1073 Mode::Extra => {
1074 if (self.gzip_flags & 0x0400) != 0 {
1075 let extra_available =
1077 Ord::min(self.length, self.bit_reader.bytes_remaining());
1078
1079 if extra_available > 0 {
1080 if let Some(head) = self.head.as_mut() {
1081 if !head.extra.is_null() {
1082 let written_so_far = head.extra_len as usize - self.length;
1089
1090 let count = Ord::min(
1092 (head.extra_max as usize)
1093 .saturating_sub(written_so_far),
1094 extra_available,
1095 );
1096
1097 let next_write_offset =
1100 Ord::min(written_so_far, head.extra_max as usize);
1101
1102 unsafe {
1103 core::ptr::copy_nonoverlapping(
1107 self.bit_reader.as_mut_ptr(),
1108 head.extra.add(next_write_offset),
1109 count,
1110 );
1111 }
1112 }
1113 }
1114
1115 if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1117 let extra_slice =
1118 &self.bit_reader.as_slice()[..extra_available];
1119 self.checksum = crc32(self.checksum, extra_slice)
1120 }
1121
1122 self.in_available -= extra_available;
1123 self.bit_reader.advance(extra_available);
1124 self.length -= extra_available;
1125 }
1126
1127 if self.length != 0 {
1129 break 'label self.inflate_leave(ReturnCode::Ok);
1130 }
1131 }
1132
1133 self.length = 0;
1134
1135 break 'blk Mode::Name;
1136 }
1137 Mode::Name => {
1138 if (self.gzip_flags & 0x0800) != 0 {
1139 if self.in_available == 0 {
1140 break 'label self.inflate_leave(ReturnCode::Ok);
1141 }
1142
1143 let slice = self.bit_reader.as_slice();
1146 let null_terminator_index = slice.iter().position(|c| *c == 0);
1147
1148 let name_slice = match null_terminator_index {
1150 Some(i) => &slice[..=i],
1151 None => slice,
1152 };
1153
1154 if let Some(head) = self.head.as_mut() {
1156 if !head.name.is_null() {
1157 let remaining_name_bytes = (head.name_max as usize)
1158 .checked_sub(self.length)
1159 .expect("name out of bounds");
1160 let copy = Ord::min(name_slice.len(), remaining_name_bytes);
1161
1162 unsafe {
1163 core::ptr::copy_nonoverlapping(
1166 name_slice.as_ptr(),
1167 head.name.add(self.length),
1168 copy,
1169 )
1170 };
1171
1172 self.length += copy;
1173 }
1174 }
1175
1176 if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1177 self.checksum = crc32(self.checksum, name_slice);
1178 }
1179
1180 let reached_end = name_slice.last() == Some(&0);
1181 self.bit_reader.advance(name_slice.len());
1182
1183 if !reached_end && self.bit_reader.bytes_remaining() == 0 {
1184 break 'label self.inflate_leave(ReturnCode::Ok);
1185 }
1186 } else if let Some(head) = self.head.as_mut() {
1187 head.name = core::ptr::null_mut();
1188 }
1189
1190 self.length = 0;
1191
1192 break 'blk Mode::Comment;
1193 }
1194 Mode::Comment => {
1195 if (self.gzip_flags & 0x01000) != 0 {
1196 if self.in_available == 0 {
1197 break 'label self.inflate_leave(ReturnCode::Ok);
1198 }
1199
1200 let slice = self.bit_reader.as_slice();
1203 let null_terminator_index = slice.iter().position(|c| *c == 0);
1204
1205 let comment_slice = match null_terminator_index {
1207 Some(i) => &slice[..=i],
1208 None => slice,
1209 };
1210
1211 if let Some(head) = self.head.as_mut() {
1213 if !head.comment.is_null() {
1214 let remaining_comm_bytes = (head.comm_max as usize)
1215 .checked_sub(self.length)
1216 .expect("comm out of bounds");
1217 let copy = Ord::min(comment_slice.len(), remaining_comm_bytes);
1218
1219 unsafe {
1220 core::ptr::copy_nonoverlapping(
1223 comment_slice.as_ptr(),
1224 head.comment.add(self.length),
1225 copy,
1226 )
1227 };
1228
1229 self.length += copy;
1230 }
1231 }
1232
1233 if (self.gzip_flags & 0x0200) != 0 && (self.wrap & 4) != 0 {
1234 self.checksum = crc32(self.checksum, comment_slice);
1235 }
1236
1237 let reached_end = comment_slice.last() == Some(&0);
1238 self.bit_reader.advance(comment_slice.len());
1239
1240 if !reached_end && self.bit_reader.bytes_remaining() == 0 {
1241 break 'label self.inflate_leave(ReturnCode::Ok);
1242 }
1243 } else if let Some(head) = self.head.as_mut() {
1244 head.comment = core::ptr::null_mut();
1245 }
1246
1247 break 'blk Mode::HCrc;
1248 }
1249 Mode::HCrc => {
1250 if (self.gzip_flags & 0x0200) != 0 {
1251 need_bits!(self, 16);
1252
1253 if (self.wrap & 4) != 0
1254 && self.bit_reader.hold() as u32 != (self.checksum & 0xffff)
1255 {
1256 mode = Mode::Bad;
1257 break 'label self.bad("header crc mismatch\0");
1258 }
1259
1260 self.bit_reader.init_bits();
1261 }
1262
1263 if let Some(head) = self.head.as_mut() {
1264 head.hcrc = (self.gzip_flags >> 9) & 1;
1265 head.done = 1;
1266 }
1267
1268 if (self.wrap & 4 != 0) && self.gzip_flags != 0 {
1270 self.crc_fold = Crc32Fold::new();
1271 self.checksum = crate::CRC32_INITIAL_VALUE;
1272 }
1273
1274 break 'blk Mode::Type;
1275 }
1276 Mode::Type => {
1277 use InflateFlush::*;
1278
1279 match self.flush {
1280 Block | Trees => break 'label ReturnCode::Ok,
1281 NoFlush | SyncFlush | Finish => {
1282 break 'blk Mode::TypeDo;
1284 }
1285 }
1286 }
1287 Mode::TypeDo => {
1288 if self.flags.contains(Flags::IS_LAST_BLOCK) {
1289 self.bit_reader.next_byte_boundary();
1290 break 'blk Mode::Check;
1291 }
1292
1293 need_bits!(self, 3);
1294 self.flags
1296 .update(Flags::IS_LAST_BLOCK, self.bit_reader.bits(1) != 0);
1297 self.bit_reader.drop_bits(1);
1298
1299 match self.bit_reader.bits(2) {
1300 0b00 => {
1301 traceln!("inflate: stored block (last = {last})");
1302
1303 self.bit_reader.drop_bits(2);
1304
1305 break 'blk Mode::Stored;
1306 }
1307 0b01 => {
1308 traceln!("inflate: fixed codes block (last = {last})");
1309
1310 self.len_table = Table {
1311 codes: Codes::Fixed,
1312 bits: 9,
1313 };
1314
1315 self.dist_table = Table {
1316 codes: Codes::Fixed,
1317 bits: 5,
1318 };
1319
1320 mode = Mode::Len_;
1321
1322 self.bit_reader.drop_bits(2);
1323
1324 if let InflateFlush::Trees = self.flush {
1325 break 'label self.inflate_leave(ReturnCode::Ok);
1326 } else {
1327 break 'blk Mode::Len_;
1328 }
1329 }
1330 0b10 => {
1331 traceln!("inflate: dynamic codes block (last = {last})");
1332
1333 self.bit_reader.drop_bits(2);
1334
1335 break 'blk Mode::Table;
1336 }
1337 0b11 => {
1338 traceln!("inflate: invalid block type");
1339
1340 self.bit_reader.drop_bits(2);
1341
1342 mode = Mode::Bad;
1343 break 'label self.bad("invalid block type\0");
1344 }
1345 _ => {
1346 unreachable!("BitReader::bits(2) only yields a value of two bits, so this match is already exhaustive")
1348 }
1349 }
1350 }
1351 Mode::Stored => {
1352 self.bit_reader.next_byte_boundary();
1353
1354 need_bits!(self, 32);
1355
1356 let hold = self.bit_reader.bits(32) as u32;
1357
1358 traceln!("hold {hold:#x}");
1359
1360 if hold as u16 != !((hold >> 16) as u16) {
1361 mode = Mode::Bad;
1362 break 'label self.bad("invalid stored block lengths\0");
1363 }
1364
1365 self.length = hold as usize & 0xFFFF;
1366 traceln!("inflate: stored length {}", state.length);
1367
1368 self.bit_reader.init_bits();
1369
1370 if let InflateFlush::Trees = self.flush {
1371 break 'label self.inflate_leave(ReturnCode::Ok);
1372 } else {
1373 break 'blk Mode::CopyBlock;
1374 }
1375 }
1376 Mode::CopyBlock => {
1377 loop {
1378 let mut copy = self.length;
1379
1380 if copy == 0 {
1381 break;
1382 }
1383
1384 copy = Ord::min(copy, self.writer.remaining());
1385 copy = Ord::min(copy, self.bit_reader.bytes_remaining());
1386
1387 if copy == 0 {
1388 break 'label self.inflate_leave(ReturnCode::Ok);
1389 }
1390
1391 self.writer.extend(&self.bit_reader.as_slice()[..copy]);
1392 self.bit_reader.advance(copy);
1393
1394 self.length -= copy;
1395 }
1396
1397 break 'blk Mode::Type;
1398 }
1399 Mode::Check => {
1400 if !cfg!(feature = "__internal-fuzz-disable-checksum") && self.wrap != 0 {
1401 need_bits!(self, 32);
1402
1403 self.total += self.writer.len();
1404
1405 if self.wrap & 4 != 0 {
1406 if self.gzip_flags != 0 {
1407 self.crc_fold.fold(self.writer.filled(), self.checksum);
1408 self.checksum = self.crc_fold.finish();
1409 } else {
1410 self.checksum = adler32(self.checksum, self.writer.filled());
1411 }
1412 }
1413
1414 let given_checksum = if self.gzip_flags != 0 {
1415 self.bit_reader.hold() as u32
1416 } else {
1417 zswap32(self.bit_reader.hold() as u32)
1418 };
1419
1420 self.out_available = self.writer.capacity() - self.writer.len();
1421
1422 if self.wrap & 4 != 0 && given_checksum != self.checksum {
1423 mode = Mode::Bad;
1424 break 'label self.bad("incorrect data check\0");
1425 }
1426
1427 self.bit_reader.init_bits();
1428 }
1429
1430 break 'blk Mode::Length;
1431 }
1432 Mode::Len_ => {
1433 break 'blk Mode::Len;
1434 }
1435 Mode::Len => {
1436 self.mode = mode;
1437 let val = self.len_and_friends();
1438 mode = self.mode;
1439 match val {
1440 ControlFlow::Break(return_code) => break 'label return_code,
1441 ControlFlow::Continue(()) => continue 'label,
1442 }
1443 }
1444 Mode::LenExt => {
1445 let extra = self.extra;
1447
1448 if extra != 0 {
1450 need_bits!(self, extra);
1451 self.length += self.bit_reader.bits(extra) as usize;
1452 self.bit_reader.drop_bits(extra as u8);
1453 self.back += extra;
1454 }
1455
1456 traceln!("inflate: length {}", state.length);
1457
1458 self.was = self.length;
1459
1460 break 'blk Mode::Dist;
1461 }
1462 Mode::Lit => {
1463 if self.writer.is_full() {
1465 traceln!("Ok: writer is full ({} bytes)", self.writer.capacity());
1466 break 'label self.inflate_leave(ReturnCode::Ok);
1467 }
1468
1469 self.writer.push(self.length as u8);
1470
1471 break 'blk Mode::Len;
1472 }
1473 Mode::Dist => {
1474 let mut here;
1478 loop {
1479 let bits = self.bit_reader.bits(self.dist_table.bits) as usize;
1480 here = self.dist_table_get(bits);
1481 if here.bits <= self.bit_reader.bits_in_buffer() {
1482 break;
1483 }
1484
1485 pull_byte!(self);
1486 }
1487
1488 if here.op & 0xf0 == 0 {
1489 let last = here;
1490
1491 loop {
1492 let bits = self.bit_reader.bits((last.bits + last.op) as usize);
1493 here = self.dist_table_get(
1494 last.val as usize + ((bits as usize) >> last.bits),
1495 );
1496
1497 if last.bits + here.bits <= self.bit_reader.bits_in_buffer() {
1498 break;
1499 }
1500
1501 pull_byte!(self);
1502 }
1503
1504 self.bit_reader.drop_bits(last.bits);
1505 self.back += last.bits as usize;
1506 }
1507
1508 self.bit_reader.drop_bits(here.bits);
1509
1510 if here.op & 64 != 0 {
1511 mode = Mode::Bad;
1512 break 'label self.bad("invalid distance code\0");
1513 }
1514
1515 self.offset = here.val as usize;
1516
1517 self.extra = (here.op & MAX_BITS) as usize;
1518
1519 break 'blk Mode::DistExt;
1520 }
1521 Mode::DistExt => {
1522 let extra = self.extra;
1524
1525 if extra > 0 {
1526 need_bits!(self, extra);
1527 self.offset += self.bit_reader.bits(extra) as usize;
1528 self.bit_reader.drop_bits(extra as u8);
1529 self.back += extra;
1530 }
1531
1532 if INFLATE_STRICT && self.offset > self.dmax {
1533 mode = Mode::Bad;
1534 break 'label self.bad("invalid distance code too far back\0");
1535 }
1536
1537 traceln!("inflate: distance {}", state.offset);
1538
1539 break 'blk Mode::Match;
1540 }
1541 Mode::Match => {
1542 'match_: loop {
1545 if self.writer.is_full() {
1546 traceln!(
1547 "BufError: writer is full ({} bytes)",
1548 self.writer.capacity()
1549 );
1550 break 'label self.inflate_leave(ReturnCode::Ok);
1551 }
1552
1553 let left = self.writer.remaining();
1554 let copy = self.writer.len();
1555
1556 let copy = if self.offset > copy {
1557 let mut copy = self.offset - copy;
1560
1561 if copy > self.window.have() {
1562 if self.flags.contains(Flags::SANE) {
1563 mode = Mode::Bad;
1564 break 'label self.bad("invalid distance too far back\0");
1565 }
1566
1567 panic!("INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR")
1569 }
1570
1571 let wnext = self.window.next();
1572 let wsize = self.window.size();
1573
1574 let from = if copy > wnext {
1575 copy -= wnext;
1576 wsize - copy
1577 } else {
1578 wnext - copy
1579 };
1580
1581 copy = Ord::min(copy, self.length);
1582 copy = Ord::min(copy, left);
1583
1584 self.writer
1585 .extend_from_window(&self.window, from..from + copy);
1586
1587 copy
1588 } else {
1589 let copy = Ord::min(self.length, left);
1590 self.writer.copy_match(self.offset, copy);
1591
1592 copy
1593 };
1594
1595 self.length -= copy;
1596
1597 if self.length == 0 {
1598 break 'blk Mode::Len;
1599 } else {
1600 continue 'match_;
1602 }
1603 }
1604 }
1605 Mode::Table => {
1606 need_bits!(self, 14);
1607 self.nlen = self.bit_reader.bits(5) as usize + 257;
1608 self.bit_reader.drop_bits(5);
1609 self.ndist = self.bit_reader.bits(5) as usize + 1;
1610 self.bit_reader.drop_bits(5);
1611 self.ncode = self.bit_reader.bits(4) as usize + 4;
1612 self.bit_reader.drop_bits(4);
1613
1614 if self.nlen > 286 || self.ndist > 30 {
1616 mode = Mode::Bad;
1617 break 'label self.bad("too many length or distance symbols\0");
1618 }
1619
1620 self.have = 0;
1621
1622 break 'blk Mode::LenLens;
1623 }
1624 Mode::LenLens => {
1625 const ORDER: [u8; 19] = [
1627 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
1628 ];
1629
1630 while self.have < self.ncode {
1631 need_bits!(self, 3);
1632 self.lens[usize::from(ORDER[self.have])] =
1633 self.bit_reader.bits(3) as u16;
1634 self.have += 1;
1635 self.bit_reader.drop_bits(3);
1636 }
1637
1638 while self.have < 19 {
1639 self.lens[usize::from(ORDER[self.have])] = 0;
1640 self.have += 1;
1641 }
1642
1643 let InflateTable::Success { root, used } = inflate_table(
1644 CodeType::Codes,
1645 &self.lens[..19],
1646 &mut self.codes_codes,
1647 7,
1648 &mut self.work,
1649 ) else {
1650 mode = Mode::Bad;
1651 break 'label self.bad("invalid code lengths set\0");
1652 };
1653
1654 self.next = used;
1655 self.len_table.codes = Codes::Codes;
1656 self.len_table.bits = root;
1657
1658 self.have = 0;
1659
1660 break 'blk Mode::CodeLens;
1661 }
1662 Mode::CodeLens => {
1663 while self.have < self.nlen + self.ndist {
1664 let here = loop {
1665 let bits = self.bit_reader.bits(self.len_table.bits);
1666 let here = self.len_table_get(bits as usize);
1667 if here.bits <= self.bit_reader.bits_in_buffer() {
1668 break here;
1669 }
1670
1671 pull_byte!(self);
1672 };
1673
1674 let here_bits = here.bits;
1675
1676 match here.val {
1677 0..=15 => {
1678 self.bit_reader.drop_bits(here_bits);
1679 self.lens[self.have] = here.val;
1680 self.have += 1;
1681 }
1682 16 => {
1683 need_bits!(self, usize::from(here_bits) + 2);
1684 self.bit_reader.drop_bits(here_bits);
1685 if self.have == 0 {
1686 mode = Mode::Bad;
1687 break 'label self.bad("invalid bit length repeat\0");
1688 }
1689
1690 let len = self.lens[self.have - 1];
1691 let copy = 3 + self.bit_reader.bits(2) as usize;
1692 self.bit_reader.drop_bits(2);
1693
1694 if self.have + copy > self.nlen + self.ndist {
1695 mode = Mode::Bad;
1696 break 'label self.bad("invalid bit length repeat\0");
1697 }
1698
1699 self.lens[self.have..][..copy].fill(len);
1700 self.have += copy;
1701 }
1702 17 => {
1703 need_bits!(self, usize::from(here_bits) + 3);
1704 self.bit_reader.drop_bits(here_bits);
1705 let copy = 3 + self.bit_reader.bits(3) as usize;
1706 self.bit_reader.drop_bits(3);
1707
1708 if self.have + copy > self.nlen + self.ndist {
1709 mode = Mode::Bad;
1710 break 'label self.bad("invalid bit length repeat\0");
1711 }
1712
1713 self.lens[self.have..][..copy].fill(0);
1714 self.have += copy;
1715 }
1716 18.. => {
1717 need_bits!(self, usize::from(here_bits) + 7);
1718 self.bit_reader.drop_bits(here_bits);
1719 let copy = 11 + self.bit_reader.bits(7) as usize;
1720 self.bit_reader.drop_bits(7);
1721
1722 if self.have + copy > self.nlen + self.ndist {
1723 mode = Mode::Bad;
1724 break 'label self.bad("invalid bit length repeat\0");
1725 }
1726
1727 self.lens[self.have..][..copy].fill(0);
1728 self.have += copy;
1729 }
1730 }
1731 }
1732
1733 if self.lens[256] == 0 {
1735 mode = Mode::Bad;
1736 break 'label self.bad("invalid code -- missing end-of-block\0");
1737 }
1738
1739 let InflateTable::Success { root, used } = inflate_table(
1742 CodeType::Lens,
1743 &self.lens[..self.nlen],
1744 &mut self.len_codes,
1745 10,
1746 &mut self.work,
1747 ) else {
1748 mode = Mode::Bad;
1749 break 'label self.bad("invalid literal/lengths set\0");
1750 };
1751
1752 self.len_table.codes = Codes::Len;
1753 self.len_table.bits = root;
1754 self.next = used;
1755
1756 let InflateTable::Success { root, used } = inflate_table(
1757 CodeType::Dists,
1758 &self.lens[self.nlen..][..self.ndist],
1759 &mut self.dist_codes,
1760 9,
1761 &mut self.work,
1762 ) else {
1763 mode = Mode::Bad;
1764 break 'label self.bad("invalid distances set\0");
1765 };
1766
1767 self.dist_table.bits = root;
1768 self.dist_table.codes = Codes::Dist;
1769 self.next += used;
1770
1771 mode = Mode::Len_;
1772
1773 if matches!(self.flush, InflateFlush::Trees) {
1774 break 'label self.inflate_leave(ReturnCode::Ok);
1775 }
1776
1777 break 'blk Mode::Len_;
1778 }
1779 Mode::Dict => {
1780 if !self.flags.contains(Flags::HAVE_DICT) {
1781 break 'label self.inflate_leave(ReturnCode::NeedDict);
1782 }
1783
1784 self.checksum = crate::ADLER32_INITIAL_VALUE as _;
1785
1786 break 'blk Mode::Type;
1787 }
1788 Mode::DictId => {
1789 need_bits!(self, 32);
1790
1791 self.checksum = zswap32(self.bit_reader.hold() as u32);
1792
1793 self.bit_reader.init_bits();
1794
1795 break 'blk Mode::Dict;
1796 }
1797 Mode::Done => {
1798 break 'label ReturnCode::StreamEnd;
1800 }
1801 Mode::Bad => {
1802 let msg = "repeated call with bad state\0";
1803 #[cfg(all(feature = "std", test))]
1804 dbg!(msg);
1805 self.error_message = Some(msg);
1806
1807 break 'label ReturnCode::DataError;
1808 }
1809 Mode::Mem => {
1810 break 'label ReturnCode::MemError;
1811 }
1812 Mode::Sync => {
1813 break 'label ReturnCode::StreamError;
1814 }
1815 Mode::Length => {
1816 if self.wrap != 0 && self.gzip_flags != 0 {
1818 need_bits!(self, 32);
1819 if (self.wrap & 0b100) != 0
1820 && self.bit_reader.hold() as u32 != self.total as u32
1821 {
1822 mode = Mode::Bad;
1823 break 'label self.bad("incorrect length check\0");
1824 }
1825
1826 self.bit_reader.init_bits();
1827 }
1828
1829 mode = Mode::Done;
1830 break 'label ReturnCode::StreamEnd;
1832 }
1833 };
1834 }
1835 };
1836
1837 self.mode = mode;
1838
1839 ret
1840 }
1841
1842 fn bad(&mut self, msg: &'static str) -> ReturnCode {
1843 #[cfg(all(feature = "std", test))]
1844 dbg!(msg);
1845 self.error_message = Some(msg);
1846 self.inflate_leave(ReturnCode::DataError)
1847 }
1848
1849 fn inflate_leave(&mut self, return_code: ReturnCode) -> ReturnCode {
1852 return_code
1854 }
1855
1856 fn decoding_state(&self) -> i32 {
1858 let bit_reader_bits = self.bit_reader.bits_in_buffer() as i32;
1859 debug_assert!(bit_reader_bits < 64);
1860
1861 let last = if self.flags.contains(Flags::IS_LAST_BLOCK) {
1862 64
1863 } else {
1864 0
1865 };
1866
1867 let mode = match self.mode {
1868 Mode::Type => 128,
1869 Mode::Len_ | Mode::CopyBlock => 256,
1870 _ => 0,
1871 };
1872
1873 bit_reader_bits | last | mode
1874 }
1875}
1876
1877unsafe fn inflate_fast_help(state: &mut State, start: usize) {
1882 #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
1883 if crate::cpu_features::is_enabled_avx2_and_bmi2() {
1884 return unsafe { inflate_fast_help_avx2(state, start) };
1886 }
1887
1888 unsafe { inflate_fast_help_vanilla(state, start) };
1890}
1891
1892#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
1897#[target_feature(enable = "avx2")]
1898#[target_feature(enable = "bmi2")]
1899#[target_feature(enable = "bmi1")]
1900unsafe fn inflate_fast_help_avx2(state: &mut State, start: usize) {
1901 unsafe { inflate_fast_help_impl::<{ CpuFeatures::AVX2 }>(state, start) };
1903}
1904
1905unsafe fn inflate_fast_help_vanilla(state: &mut State, start: usize) {
1910 unsafe { inflate_fast_help_impl::<{ CpuFeatures::NONE }>(state, start) };
1912}
1913
1914#[inline(always)]
1919unsafe fn inflate_fast_help_impl<const FEATURES: usize>(state: &mut State, _start: usize) {
1920 let mut bit_reader = BitReader::new(&[]);
1921 core::mem::swap(&mut bit_reader, &mut state.bit_reader);
1922 debug_assert!(bit_reader.bytes_remaining() >= 15);
1923
1924 let mut writer = Writer::new(&mut []);
1925 core::mem::swap(&mut writer, &mut state.writer);
1926
1927 let lcode = state.len_table_ref();
1928 let dcode = state.dist_table_ref();
1929
1930 let lmask = (1u64 << state.len_table.bits) - 1;
1932 let dmask = (1u64 << state.dist_table.bits) - 1;
1933
1934 let extra_safe = false;
1936
1937 let window_size = state.window.size();
1938
1939 let mut bad = None;
1940
1941 if bit_reader.bits_in_buffer() < 10 {
1942 debug_assert!(bit_reader.bytes_remaining() >= 15);
1943 unsafe { bit_reader.refill() };
1945 }
1946 debug_assert!(
1949 bit_reader.bytes_remaining() >= 8 && bit_reader.bytes_remaining_including_buffer() >= 15
1950 );
1951
1952 'outer: loop {
1953 debug_assert!(
1959 bit_reader.bytes_remaining() >= 8
1960 && bit_reader.bytes_remaining_including_buffer() >= 15
1961 );
1962
1963 let mut here = {
1964 let bits = bit_reader.bits_in_buffer();
1965 let hold = bit_reader.hold();
1966
1967 unsafe { bit_reader.refill() };
1974 debug_assert!(bit_reader.bytes_remaining() >= 8);
1976
1977 if bits as usize >= state.len_table.bits {
1980 lcode[(hold & lmask) as usize]
1981 } else {
1982 lcode[(bit_reader.hold() & lmask) as usize]
1983 }
1984 };
1985
1986 if here.op == 0 {
1987 writer.push(here.val as u8);
1988 bit_reader.drop_bits(here.bits);
1989 here = lcode[(bit_reader.hold() & lmask) as usize];
1990
1991 if here.op == 0 {
1992 writer.push(here.val as u8);
1993 bit_reader.drop_bits(here.bits);
1994 here = lcode[(bit_reader.hold() & lmask) as usize];
1995 }
1996 }
1997
1998 'dolen: loop {
1999 bit_reader.drop_bits(here.bits);
2000 let op = here.op;
2001
2002 if op == 0 {
2003 writer.push(here.val as u8);
2004 } else if op & 16 != 0 {
2005 let op = op & MAX_BITS;
2006 let mut len = here.val + bit_reader.bits(op as usize) as u16;
2007 bit_reader.drop_bits(op);
2008
2009 here = dcode[(bit_reader.hold() & dmask) as usize];
2010
2011 if bit_reader.bits_in_buffer() < MAX_BITS + MAX_DIST_EXTRA_BITS {
2014 debug_assert!(bit_reader.bytes_remaining() >= 8);
2015 unsafe { bit_reader.refill() };
2022 }
2023
2024 'dodist: loop {
2025 bit_reader.drop_bits(here.bits);
2026 let op = here.op;
2027
2028 if op & 16 != 0 {
2029 let op = op & MAX_BITS;
2030 let dist = here.val + bit_reader.bits(op as usize) as u16;
2031
2032 if INFLATE_STRICT && dist as usize > state.dmax {
2033 bad = Some("invalid distance too far back\0");
2034 state.mode = Mode::Bad;
2035 break 'outer;
2036 }
2037
2038 bit_reader.drop_bits(op);
2039
2040 let written = writer.len();
2042
2043 if dist as usize > written {
2044 if (dist as usize - written) > state.window.have() {
2046 if state.flags.contains(Flags::SANE) {
2047 bad = Some("invalid distance too far back\0");
2048 state.mode = Mode::Bad;
2049 break 'outer;
2050 }
2051
2052 panic!("INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR")
2053 }
2054
2055 let mut op = dist as usize - written;
2056 let mut from;
2057
2058 let window_next = state.window.next();
2059
2060 if window_next == 0 {
2061 from = window_size - op;
2068 } else if window_next >= op {
2069 from = window_next - op;
2071 } else {
2072 op -= window_next;
2077 from = window_size - op;
2078
2079 if op < len as usize {
2080 len -= op as u16;
2084 writer.extend_from_window_with_features::<FEATURES>(
2085 &state.window,
2086 from..from + op,
2087 );
2088 from = 0;
2089 op = window_next;
2090 }
2091 }
2092
2093 let copy = Ord::min(op, len as usize);
2094 writer.extend_from_window_with_features::<FEATURES>(
2095 &state.window,
2096 from..from + copy,
2097 );
2098
2099 if op < len as usize {
2100 writer.copy_match_with_features::<FEATURES>(
2102 dist as usize,
2103 len as usize - op,
2104 );
2105 }
2106 } else if extra_safe {
2107 todo!()
2108 } else {
2109 writer.copy_match_with_features::<FEATURES>(dist as usize, len as usize)
2110 }
2111 } else if (op & 64) == 0 {
2112 here = dcode[(here.val + bit_reader.bits(op as usize) as u16) as usize];
2114 continue 'dodist;
2115 } else {
2116 bad = Some("invalid distance code\0");
2117 state.mode = Mode::Bad;
2118 break 'outer;
2119 }
2120
2121 break 'dodist;
2122 }
2123 } else if (op & 64) == 0 {
2124 here = lcode[(here.val + bit_reader.bits(op as usize) as u16) as usize];
2126 continue 'dolen;
2127 } else if op & 32 != 0 {
2128 state.mode = Mode::Type;
2130 break 'outer;
2131 } else {
2132 bad = Some("invalid literal/length code\0");
2133 state.mode = Mode::Bad;
2134 break 'outer;
2135 }
2136
2137 break 'dolen;
2138 }
2139
2140 let remaining = bit_reader.bytes_remaining_including_buffer();
2142 if remaining >= INFLATE_FAST_MIN_HAVE && writer.remaining() >= INFLATE_FAST_MIN_LEFT {
2143 continue;
2144 }
2145
2146 break 'outer;
2147 }
2148
2149 bit_reader.return_unused_bytes();
2151
2152 state.bit_reader = bit_reader;
2153 state.writer = writer;
2154
2155 if let Some(error_message) = bad {
2156 debug_assert!(matches!(state.mode, Mode::Bad));
2157 state.bad(error_message);
2158 }
2159}
2160
2161pub fn prime(stream: &mut InflateStream, bits: i32, value: i32) -> ReturnCode {
2162 if bits == 0 {
2163 } else if bits < 0 {
2165 stream.state.bit_reader.init_bits();
2166 } else if bits > 16 || stream.state.bit_reader.bits_in_buffer() + bits as u8 > 32 {
2167 return ReturnCode::StreamError;
2168 } else {
2169 stream.state.bit_reader.prime(bits as u8, value as u64);
2170 }
2171
2172 ReturnCode::Ok
2173}
2174
2175struct InflateAllocOffsets {
2176 total_size: usize,
2177 state_pos: usize,
2178 window_pos: usize,
2179}
2180
2181impl InflateAllocOffsets {
2182 fn new() -> Self {
2183 use core::mem::size_of;
2184
2185 const WINDOW_PAD_SIZE: usize = 64;
2188
2189 const ALIGN_SIZE: usize = 64;
2192 let mut curr_size = 0usize;
2193
2194 let state_size = size_of::<State>();
2196 let window_size = (1 << MAX_WBITS) + WINDOW_PAD_SIZE;
2197
2198 let state_pos = curr_size.next_multiple_of(ALIGN_SIZE);
2200 curr_size = state_pos + state_size;
2201
2202 let window_pos = curr_size.next_multiple_of(ALIGN_SIZE);
2203 curr_size = window_pos + window_size;
2204
2205 let total_size = (curr_size + (ALIGN_SIZE - 1)).next_multiple_of(ALIGN_SIZE);
2208
2209 Self {
2210 total_size,
2211 state_pos,
2212 window_pos,
2213 }
2214 }
2215}
2216
2217#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
2221pub struct InflateConfig {
2222 pub window_bits: i32,
2223}
2224
2225impl Default for InflateConfig {
2226 fn default() -> Self {
2227 Self {
2228 window_bits: DEF_WBITS,
2229 }
2230 }
2231}
2232
2233pub fn init(stream: &mut z_stream, config: InflateConfig) -> ReturnCode {
2235 stream.msg = core::ptr::null_mut();
2236
2237 #[cfg(feature = "rust-allocator")]
2241 if stream.zalloc.is_none() || stream.zfree.is_none() {
2242 stream.configure_default_rust_allocator()
2243 }
2244
2245 #[cfg(feature = "c-allocator")]
2246 if stream.zalloc.is_none() || stream.zfree.is_none() {
2247 stream.configure_default_c_allocator()
2248 }
2249
2250 if stream.zalloc.is_none() || stream.zfree.is_none() {
2251 return ReturnCode::StreamError;
2252 }
2253
2254 let mut state = State::new(&[], Writer::new(&mut []));
2255
2256 state.chunksize = 32;
2258
2259 let alloc = Allocator {
2260 zalloc: stream.zalloc.unwrap(),
2261 zfree: stream.zfree.unwrap(),
2262 opaque: stream.opaque,
2263 _marker: PhantomData,
2264 };
2265 let allocs = InflateAllocOffsets::new();
2266
2267 let Some(allocation_start) = alloc.allocate_slice_raw::<u8>(allocs.total_size) else {
2268 return ReturnCode::MemError;
2269 };
2270
2271 let address = allocation_start.as_ptr() as usize;
2272 let align_offset = address.next_multiple_of(64) - address;
2273 let buf = unsafe { allocation_start.as_ptr().add(align_offset) };
2274
2275 let window_allocation = unsafe { buf.add(allocs.window_pos) };
2276 let window = unsafe { Window::from_raw_parts(window_allocation, (1 << MAX_WBITS) + 64) };
2277 state.window = window;
2278
2279 let state_allocation = unsafe { buf.add(allocs.state_pos).cast::<State>() };
2280 unsafe { state_allocation.write(state) };
2281 stream.state = state_allocation.cast::<internal_state>();
2282
2283 if let Some(stream) = unsafe { InflateStream::from_stream_mut(stream) } {
2285 stream.state.allocation_start = allocation_start.as_ptr();
2286 stream.state.total_allocation_size = allocs.total_size;
2287 let ret = reset_with_config(stream, config);
2288
2289 if ret != ReturnCode::Ok {
2290 end(stream);
2291 }
2292
2293 ret
2294 } else {
2295 ReturnCode::StreamError
2296 }
2297}
2298
2299pub fn reset_with_config(stream: &mut InflateStream, config: InflateConfig) -> ReturnCode {
2300 let mut window_bits = config.window_bits;
2301 let wrap;
2302
2303 if window_bits < 0 {
2304 wrap = 0;
2305
2306 if window_bits < -MAX_WBITS {
2307 return ReturnCode::StreamError;
2308 }
2309
2310 window_bits = -window_bits;
2311 } else {
2312 wrap = (window_bits >> 4) + 5; if window_bits < 48 {
2315 window_bits &= MAX_WBITS;
2316 }
2317 }
2318
2319 if window_bits != 0 && !(MIN_WBITS..=MAX_WBITS).contains(&window_bits) {
2320 traceln!("invalid windowBits");
2321 return ReturnCode::StreamError;
2322 }
2323
2324 stream.state.wrap = wrap as u8;
2325 stream.state.wbits = window_bits as _;
2326
2327 reset(stream)
2328}
2329
2330pub fn reset(stream: &mut InflateStream) -> ReturnCode {
2331 stream.state.window.clear();
2333
2334 stream.state.error_message = None;
2335
2336 reset_keep(stream)
2337}
2338
2339pub fn reset_keep(stream: &mut InflateStream) -> ReturnCode {
2340 stream.total_in = 0;
2341 stream.total_out = 0;
2342 stream.state.total = 0;
2343
2344 stream.msg = core::ptr::null_mut();
2345
2346 let state = &mut stream.state;
2347
2348 if state.wrap != 0 {
2349 stream.adler = (state.wrap & 1) as _;
2351 }
2352
2353 state.mode = Mode::Head;
2354 state.checksum = crate::ADLER32_INITIAL_VALUE as u32;
2355
2356 state.flags.update(Flags::IS_LAST_BLOCK, false);
2357 state.flags.update(Flags::HAVE_DICT, false);
2358 state.flags.update(Flags::SANE, true);
2359 state.gzip_flags = -1;
2360 state.dmax = 32768;
2361 state.head = None;
2362 state.bit_reader = BitReader::new(&[]);
2363
2364 state.next = 0;
2365 state.len_table = Table::default();
2366 state.dist_table = Table::default();
2367
2368 state.back = usize::MAX;
2369
2370 ReturnCode::Ok
2371}
2372
2373pub fn codes_used(stream: &InflateStream) -> usize {
2374 stream.state.next
2375}
2376
2377pub unsafe fn inflate(stream: &mut InflateStream, flush: InflateFlush) -> ReturnCode {
2378 if stream.next_out.is_null() || (stream.next_in.is_null() && stream.avail_in != 0) {
2379 return ReturnCode::StreamError;
2380 }
2381
2382 let state = &mut stream.state;
2383
2384 if let Mode::Type = state.mode {
2386 state.mode = Mode::TypeDo;
2387 }
2388
2389 state.flush = flush;
2390
2391 unsafe {
2392 state
2393 .bit_reader
2394 .update_slice(stream.next_in, stream.avail_in as usize)
2395 };
2396 state.writer = unsafe { Writer::new_uninit(stream.next_out.cast(), stream.avail_out as usize) };
2398
2399 state.in_available = stream.avail_in as _;
2400 state.out_available = stream.avail_out as _;
2401
2402 let err = state.dispatch();
2403
2404 let in_read = state.bit_reader.as_ptr() as usize - stream.next_in as usize;
2405 let out_written = state.out_available - (state.writer.capacity() - state.writer.len());
2406
2407 stream.total_in += in_read as z_size;
2408 state.total = state.total.wrapping_add(out_written);
2409 stream.total_out = state.total as _;
2410
2411 stream.avail_in = state.bit_reader.bytes_remaining() as u32;
2412 stream.next_in = state.bit_reader.as_ptr() as *mut u8;
2413
2414 stream.avail_out = (state.writer.capacity() - state.writer.len()) as u32;
2415 stream.next_out = state.writer.next_out() as *mut u8;
2416
2417 stream.adler = state.checksum as z_checksum;
2418
2419 let valid_mode = |mode| !matches!(mode, Mode::Bad | Mode::Mem | Mode::Sync);
2420 let not_done = |mode| {
2421 !matches!(
2422 mode,
2423 Mode::Check | Mode::Length | Mode::Bad | Mode::Mem | Mode::Sync
2424 )
2425 };
2426
2427 let must_update_window = state.window.size() != 0
2428 || (out_written != 0
2429 && valid_mode(state.mode)
2430 && (not_done(state.mode) || !matches!(state.flush, InflateFlush::Finish)));
2431
2432 let update_checksum = state.wrap & 4 != 0;
2433
2434 if must_update_window {
2435 state.window.extend(
2436 &state.writer.filled()[..out_written],
2437 state.gzip_flags,
2438 update_checksum,
2439 &mut state.checksum,
2440 &mut state.crc_fold,
2441 );
2442 }
2443
2444 if let Some(msg) = state.error_message {
2445 assert!(msg.ends_with('\0'));
2446 stream.msg = msg.as_ptr() as *mut u8 as *mut core::ffi::c_char;
2447 }
2448
2449 stream.data_type = state.decoding_state();
2450
2451 if ((in_read == 0 && out_written == 0) || flush == InflateFlush::Finish)
2452 && err == ReturnCode::Ok
2453 {
2454 ReturnCode::BufError
2455 } else {
2456 err
2457 }
2458}
2459
2460fn syncsearch(mut got: usize, buf: &[u8]) -> (usize, usize) {
2461 let len = buf.len();
2462 let mut next = 0;
2463
2464 while next < len && got < 4 {
2465 if buf[next] == if got < 2 { 0 } else { 0xff } {
2466 got += 1;
2467 } else if buf[next] != 0 {
2468 got = 0;
2469 } else {
2470 got = 4 - got;
2471 }
2472 next += 1;
2473 }
2474
2475 (got, next)
2476}
2477
2478pub fn sync(stream: &mut InflateStream) -> ReturnCode {
2479 let state = &mut stream.state;
2480
2481 if stream.avail_in == 0 && state.bit_reader.bits_in_buffer() < 8 {
2482 return ReturnCode::BufError;
2483 }
2484 if !matches!(state.mode, Mode::Sync) {
2486 state.mode = Mode::Sync;
2487
2488 let (buf, len) = state.bit_reader.start_sync_search();
2489
2490 (state.have, _) = syncsearch(0, &buf[..len]);
2491 }
2492
2493 let slice = unsafe { core::slice::from_raw_parts(stream.next_in, stream.avail_in as usize) };
2496
2497 let len;
2498 (state.have, len) = syncsearch(state.have, slice);
2499 stream.next_in = unsafe { stream.next_in.add(len) };
2501 stream.avail_in -= len as u32;
2502 stream.total_in += len as z_size;
2503
2504 if state.have != 4 {
2506 return ReturnCode::DataError;
2507 }
2508
2509 if state.gzip_flags == -1 {
2510 state.wrap = 0; } else {
2512 state.wrap &= !4; }
2514
2515 let flags = state.gzip_flags;
2516 let total_in = stream.total_in;
2517 let total_out = stream.total_out;
2518
2519 reset(stream);
2520
2521 stream.total_in = total_in;
2522 stream.total_out = total_out;
2523
2524 stream.state.gzip_flags = flags;
2525 stream.state.mode = Mode::Type;
2526
2527 ReturnCode::Ok
2528}
2529
2530pub fn sync_point(stream: &mut InflateStream) -> bool {
2539 matches!(stream.state.mode, Mode::Stored) && stream.state.bit_reader.bits_in_buffer() == 0
2540}
2541
2542pub unsafe fn copy<'a>(
2543 dest: &mut MaybeUninit<InflateStream<'a>>,
2544 source: &InflateStream<'a>,
2545) -> ReturnCode {
2546 if source.next_out.is_null() || (source.next_in.is_null() && source.avail_in != 0) {
2547 return ReturnCode::StreamError;
2548 }
2549
2550 unsafe { core::ptr::copy_nonoverlapping(source, dest.as_mut_ptr(), 1) };
2553
2554 let allocs = InflateAllocOffsets::new();
2556 debug_assert_eq!(allocs.total_size, source.state.total_allocation_size);
2557
2558 let Some(allocation_start) = source.alloc.allocate_slice_raw::<u8>(allocs.total_size) else {
2559 return ReturnCode::MemError;
2560 };
2561
2562 let address = allocation_start.as_ptr() as usize;
2563 let align_offset = address.next_multiple_of(64) - address;
2564 let buf = unsafe { allocation_start.as_ptr().add(align_offset) };
2565
2566 let window_allocation = unsafe { buf.add(allocs.window_pos) };
2567 let window = unsafe {
2568 source
2569 .state
2570 .window
2571 .clone_to(window_allocation, (1 << MAX_WBITS) + 64)
2572 };
2573
2574 let copy = unsafe { buf.add(allocs.state_pos).cast::<State>() };
2575 unsafe { core::ptr::copy_nonoverlapping(source.state, copy, 1) };
2576
2577 let field_ptr = unsafe { core::ptr::addr_of_mut!((*copy).window) };
2578 unsafe { core::ptr::write(field_ptr, window) };
2579
2580 let field_ptr = unsafe { core::ptr::addr_of_mut!((*copy).allocation_start) };
2581 unsafe { core::ptr::write(field_ptr, allocation_start.as_ptr()) };
2582
2583 let field_ptr = unsafe { core::ptr::addr_of_mut!((*dest.as_mut_ptr()).state) };
2584 unsafe { core::ptr::write(field_ptr as *mut *mut State, copy) };
2585
2586 ReturnCode::Ok
2587}
2588
2589pub fn undermine(stream: &mut InflateStream, subvert: i32) -> ReturnCode {
2590 stream.state.flags.update(Flags::SANE, (!subvert) != 0);
2591
2592 ReturnCode::Ok
2593}
2594
2595pub fn validate(stream: &mut InflateStream, check: bool) -> ReturnCode {
2597 if check && stream.state.wrap != 0 {
2598 stream.state.wrap |= 0b100;
2599 } else {
2600 stream.state.wrap &= !0b100;
2601 }
2602
2603 ReturnCode::Ok
2604}
2605
2606pub fn mark(stream: &InflateStream) -> c_long {
2607 if stream.next_out.is_null() || (stream.next_in.is_null() && stream.avail_in != 0) {
2608 return c_long::MIN;
2609 }
2610
2611 let state = &stream.state;
2612
2613 let length = match state.mode {
2614 Mode::CopyBlock => state.length,
2615 Mode::Match => state.was - state.length,
2616 _ => 0,
2617 };
2618
2619 (((state.back as c_long) as c_ulong) << 16) as c_long + length as c_long
2620}
2621
2622pub fn set_dictionary(stream: &mut InflateStream, dictionary: &[u8]) -> ReturnCode {
2623 if stream.state.wrap != 0 && !matches!(stream.state.mode, Mode::Dict) {
2624 return ReturnCode::StreamError;
2625 }
2626
2627 if matches!(stream.state.mode, Mode::Dict) {
2629 let dictid = adler32(1, dictionary);
2630
2631 if dictid != stream.state.checksum {
2632 return ReturnCode::DataError;
2633 }
2634 }
2635
2636 stream.state.window.extend(
2637 dictionary,
2638 stream.state.gzip_flags,
2639 false,
2640 &mut stream.state.checksum,
2641 &mut stream.state.crc_fold,
2642 );
2643
2644 stream.state.flags.update(Flags::HAVE_DICT, true);
2645
2646 ReturnCode::Ok
2647}
2648
2649pub fn end<'a>(stream: &'a mut InflateStream<'_>) -> &'a mut z_stream {
2650 let alloc = stream.alloc;
2651 let allocation_start = stream.state.allocation_start;
2652 let total_allocation_size = stream.state.total_allocation_size;
2653
2654 let mut window = Window::empty();
2655 core::mem::swap(&mut window, &mut stream.state.window);
2656
2657 let stream = stream.as_z_stream_mut();
2658 let _ = core::mem::replace(&mut stream.state, core::ptr::null_mut());
2659
2660 unsafe { alloc.deallocate(allocation_start, total_allocation_size) };
2661
2662 stream
2663}
2664
2665pub unsafe fn get_header<'a>(
2674 stream: &mut InflateStream<'a>,
2675 head: Option<&'a mut gz_header>,
2676) -> ReturnCode {
2677 if (stream.state.wrap & 2) == 0 {
2678 return ReturnCode::StreamError;
2679 }
2680
2681 stream.state.head = head.map(|head| {
2682 head.done = 0;
2683 head
2684 });
2685 ReturnCode::Ok
2686}
2687
2688pub unsafe fn get_dictionary(stream: &InflateStream<'_>, dictionary: *mut u8) -> usize {
2692 let whave = stream.state.window.have();
2693 let wnext = stream.state.window.next();
2694
2695 if !dictionary.is_null() {
2696 unsafe {
2697 core::ptr::copy_nonoverlapping(
2698 stream.state.window.as_ptr().add(wnext),
2699 dictionary,
2700 whave - wnext,
2701 );
2702
2703 core::ptr::copy_nonoverlapping(
2704 stream.state.window.as_ptr(),
2705 dictionary.add(whave).sub(wnext).cast(),
2706 wnext,
2707 );
2708 }
2709 }
2710
2711 stream.state.window.have()
2712}
2713
2714#[cfg(test)]
2715mod tests {
2716 use super::*;
2717
2718 #[test]
2719 fn uncompress_buffer_overflow() {
2720 let mut output = [0; 1 << 13];
2721 let input = [
2722 72, 137, 58, 0, 3, 39, 255, 255, 255, 255, 255, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2723 14, 14, 184, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 184, 14, 14,
2724 14, 14, 14, 14, 14, 63, 14, 14, 14, 14, 14, 14, 14, 14, 184, 14, 14, 255, 14, 103, 14,
2725 14, 14, 14, 14, 14, 61, 14, 255, 255, 63, 14, 14, 14, 14, 14, 14, 14, 14, 184, 14, 14,
2726 255, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 6, 14, 14, 14, 14, 14, 14, 14, 14, 71,
2727 4, 137, 106,
2728 ];
2729
2730 let config = InflateConfig { window_bits: 15 };
2731
2732 let (_decompressed, err) = decompress_slice(&mut output, &input, config);
2733 assert_eq!(err, ReturnCode::DataError);
2734 }
2735}