1mod huffman;
2
3use super::adler::Adler32;
4use crate::{Error, Result};
5use huffman::{Bits, Huffman, Symbol};
6
7macro_rules! ready {
9 ($value:expr, $pending:expr) => {
10 match $value? {
11 Some(value) => value,
12 None => return Ok($pending),
13 }
14 };
15}
16
17pub const WINDOW_SIZE: usize = 32_768;
19
20const CODE_LENGTH_ORDER: [usize; 19] = [
21 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
22];
23
24const LENGTH_CODES: [(u16, u8); 29] = [
27 (3, 0),
28 (4, 0),
29 (5, 0),
30 (6, 0),
31 (7, 0),
32 (8, 0),
33 (9, 0),
34 (10, 0),
35 (11, 1),
36 (13, 1),
37 (15, 1),
38 (17, 1),
39 (19, 2),
40 (23, 2),
41 (27, 2),
42 (31, 2),
43 (35, 3),
44 (43, 3),
45 (51, 3),
46 (59, 3),
47 (67, 4),
48 (83, 4),
49 (99, 4),
50 (115, 4),
51 (131, 5),
52 (163, 5),
53 (195, 5),
54 (227, 5),
55 (258, 0),
56];
57const DISTANCE_CODES: [(u16, u8); 30] = [
58 (1, 0),
59 (2, 0),
60 (3, 0),
61 (4, 0),
62 (5, 1),
63 (7, 1),
64 (9, 2),
65 (13, 2),
66 (17, 3),
67 (25, 3),
68 (33, 4),
69 (49, 4),
70 (65, 5),
71 (97, 5),
72 (129, 6),
73 (193, 6),
74 (257, 7),
75 (385, 7),
76 (513, 8),
77 (769, 8),
78 (1025, 9),
79 (1537, 9),
80 (2049, 10),
81 (3073, 10),
82 (4097, 11),
83 (6145, 11),
84 (8193, 12),
85 (12289, 12),
86 (16385, 13),
87 (24577, 13),
88];
89
90#[derive(Clone, Copy, Debug, Eq, PartialEq)]
92pub struct InflateLimits {
93 pub max_output: u64,
94 pub max_ratio: u32,
98 pub ratio_slack: u64,
100}
101
102#[derive(Clone, Copy, Debug, Eq, PartialEq)]
103pub enum InflateStatus {
104 NeedInput,
106 NeedOutput,
108 Finished,
110}
111
112#[derive(Clone, Copy, Debug, Eq, PartialEq)]
113pub struct InflateProgress {
114 pub consumed: usize,
115 pub written: usize,
116 pub status: InflateStatus,
117}
118
119pub struct Inflater<'a> {
127 window: &'a mut [u8; WINDOW_SIZE],
128 position: usize,
129 window_limit: usize,
130 limits: InflateLimits,
131 bits: Bits,
132 symbol: Symbol,
133 literal: Huffman<288, 256>,
134 distance: Huffman<32, 32>,
135 code: Huffman<19, 16>,
136 lengths: [u8; 320],
137 dynamic: Dynamic,
138 state: State,
139 final_block: bool,
140 total_output: u64,
141 adler: Adler32,
142 failure: Option<Error>,
143 raw: bool,
144}
145
146impl<'a> Inflater<'a> {
147 pub fn new(window: &'a mut [u8; WINDOW_SIZE], limits: InflateLimits) -> Self {
148 Self {
149 window,
150 position: 0,
151 window_limit: WINDOW_SIZE,
152 limits,
153 bits: Bits::default(),
154 symbol: Symbol::default(),
155 literal: Huffman::new(),
156 distance: Huffman::new(),
157 code: Huffman::new(),
158 lengths: [0; 320],
159 dynamic: Dynamic::default(),
160 state: State::Header,
161 final_block: false,
162 total_output: 0,
163 adler: Adler32::new(),
164 failure: None,
165 raw: false,
166 }
167 }
168
169 pub fn new_raw(window: &'a mut [u8; WINDOW_SIZE], limits: InflateLimits) -> Self {
172 let mut decoder = Self::new(window, limits);
173 decoder.state = State::Block;
174 decoder.raw = true;
175 decoder
176 }
177
178 pub fn reset(&mut self, limits: InflateLimits) {
181 self.position = 0;
182 self.window_limit = WINDOW_SIZE;
183 self.limits = limits;
184 self.bits = Bits::default();
185 self.symbol = Symbol::default();
186 self.dynamic = Dynamic::default();
187 self.state = State::Header;
188 self.final_block = false;
189 self.total_output = 0;
190 self.adler = Adler32::new();
191 self.failure = None;
192 self.raw = false;
193 }
194
195 pub fn total_input(&self) -> u64 {
196 self.bits.total
197 }
198
199 pub fn total_output(&self) -> u64 {
200 self.total_output
201 }
202
203 pub fn update(
212 &mut self,
213 input: &[u8],
214 output: &mut [u8],
215 end_of_input: bool,
216 ) -> Result<InflateProgress> {
217 if let Some(error) = self.failure {
218 return Err(error);
219 }
220 let mut remaining = input;
221 let result = self
222 .run(&mut remaining, output)
223 .and_then(|(written, status)| {
224 if end_of_input && status == InflateStatus::NeedInput {
225 return Err(Error::InvalidZlib);
226 }
227 Ok(InflateProgress {
228 consumed: input.len() - remaining.len(),
229 written,
230 status,
231 })
232 });
233 if let Err(error) = result {
234 self.failure = Some(error);
235 }
236 result
237 }
238
239 fn run(&mut self, input: &mut &[u8], output: &mut [u8]) -> Result<(usize, InflateStatus)> {
240 let mut written = 0;
241 macro_rules! bits {
243 ($count:expr) => {
244 ready!(
245 self.bits.read($count, input),
246 (written, InflateStatus::NeedInput)
247 )
248 };
249 }
250 macro_rules! symbol {
251 ($table:ident) => {
252 ready!(
253 self.symbol.read(&self.$table, &mut self.bits, input),
254 (written, InflateStatus::NeedInput)
255 )
256 };
257 }
258 loop {
259 match self.state {
260 State::Header => {
261 self.window_limit = zlib_window(bits!(16))?;
262 self.state = State::Block;
263 }
264 State::Block => {
265 let header = bits!(3);
266 self.begin_block(header)?;
267 }
268 State::StoredLength => self.state = State::StoredComplement(bits!(16) as u16),
269 State::StoredComplement(length) => {
270 if bits!(16) as u16 != !length {
271 return Err(Error::InvalidZlib);
272 }
273 self.state = State::Stored(length);
274 }
275 State::Stored(0) => self.end_block(),
276 State::Stored(remaining) => {
277 let count = self.copy_stored(input, &mut output[written..], remaining);
278 if count != 0 {
279 written += count;
280 continue;
281 }
282 let byte = bits!(8) as u8;
285 self.state = State::Literal {
286 byte,
287 stored_remaining: Some(remaining - 1),
288 };
289 }
290 State::Dynamic | State::CodeLengths { .. } | State::Lengths | State::Repeat(_) => {
291 if !self.read_dynamic_tables(input)? {
292 return Ok((written, InflateStatus::NeedInput));
293 }
294 }
295 State::Compressed => {
296 let value = symbol!(literal);
297 self.state = match value {
298 0..=255 => State::Literal {
299 byte: value as u8,
300 stored_remaining: None,
301 },
302 256 => {
303 self.end_block();
304 continue;
305 }
306 257..=285 => State::Length(value - 257),
307 _ => return Err(Error::InvalidZlib),
308 };
309 }
310 State::Literal {
311 byte,
312 stored_remaining,
313 } => {
314 if written == output.len() {
315 return Ok((written, InflateStatus::NeedOutput));
316 }
317 self.emit(byte, &mut output[written])?;
318 written += 1;
319 self.state = stored_remaining.map_or(State::Compressed, State::Stored);
320 }
321 State::Length(index) => {
322 let (base, extra) = LENGTH_CODES[usize::from(index)];
323 self.state = State::Distance(base + bits!(extra) as u16);
324 }
325 State::Distance(length) => {
326 let index = symbol!(distance);
327 if usize::from(index) >= DISTANCE_CODES.len() {
328 return Err(Error::InvalidZlib);
329 }
330 self.state = State::DistanceExtra { length, index };
331 }
332 State::DistanceExtra { length, index } => {
333 let (base, extra) = DISTANCE_CODES[usize::from(index)];
334 let distance = base + bits!(extra) as u16;
335 if usize::from(distance) > self.window_limit
336 || u64::from(distance) > self.total_output
337 {
338 return Err(Error::InvalidZlib);
339 }
340 self.state = State::Copy {
341 remaining: length,
342 distance,
343 };
344 }
345 State::Copy {
346 remaining,
347 distance,
348 } => {
349 if written == output.len() {
350 return Ok((written, InflateStatus::NeedOutput));
351 }
352 written +=
353 self.copy_back_reference(&mut output[written..], remaining, distance)?;
354 }
355 State::Trailer { read, value } => {
356 let value = (value << 8) | bits!(8);
357 if read == 3 {
358 let actual = self.adler.value();
359 if value != actual {
360 return Err(Error::InvalidZlib);
361 }
362 self.state = State::Done;
363 } else {
364 self.state = State::Trailer {
365 read: read + 1,
366 value,
367 };
368 }
369 }
370 State::Done => return Ok((written, InflateStatus::Finished)),
371 }
372 }
373 }
374
375 fn begin_block(&mut self, header: u32) -> Result<()> {
376 self.final_block = header & 1 != 0;
377 self.state = match header >> 1 {
378 0 => {
379 self.bits.align();
380 State::StoredLength
381 }
382 1 => {
383 self.fixed_tables()?;
384 State::Compressed
385 }
386 2 => State::Dynamic,
387 _ => return Err(Error::InvalidZlib),
388 };
389 Ok(())
390 }
391
392 fn read_dynamic_tables(&mut self, input: &mut &[u8]) -> Result<bool> {
396 macro_rules! bits {
397 ($count:expr) => {
398 ready!(self.bits.read($count, input), false)
399 };
400 }
401 macro_rules! symbol {
402 ($table:ident) => {
403 ready!(self.symbol.read(&self.$table, &mut self.bits, input), false)
404 };
405 }
406 match self.state {
407 State::Dynamic => {
408 let header = bits!(14);
409 let literal = (header & 31) as u16 + 257;
410 if literal > 286 {
411 return Err(Error::InvalidZlib);
412 }
413 let distance = ((header >> 5) & 31) as u16 + 1;
414 let count = ((header >> 10) & 15) as u8 + 4;
415 self.lengths.fill(0);
416 self.dynamic = Dynamic {
417 next: 0,
418 literal,
419 total: literal + distance,
420 };
421 self.state = State::CodeLengths { next: 0, count };
422 }
423 State::CodeLengths { next, count } => {
424 self.lengths[CODE_LENGTH_ORDER[usize::from(next)]] = bits!(3) as u8;
425 self.state = if next + 1 == count {
426 self.code.build(&self.lengths[..19], false, false)?;
427 State::Lengths
428 } else {
429 State::CodeLengths {
430 next: next + 1,
431 count,
432 }
433 };
434 }
435 State::Lengths => {
436 let next = self.dynamic.next;
437 let value = symbol!(code);
438 if value <= 15 {
439 self.lengths[usize::from(next)] = value as u8;
440 self.finish_lengths(1)?;
441 } else {
442 if value == 16 && next == 0 {
443 return Err(Error::InvalidZlib);
444 }
445 self.state = State::Repeat(value);
446 }
447 }
448 State::Repeat(value) => {
449 let next = self.dynamic.next;
450 let (extra, base, length) = match value {
451 16 => (2, 3, self.lengths[usize::from(next - 1)]),
452 17 => (3, 3, 0),
453 18 => (7, 11, 0),
454 _ => return Err(Error::InvalidZlib),
455 };
456 let count = bits!(extra) as u16 + base;
457 if count > self.dynamic.total - next {
458 return Err(Error::InvalidZlib);
459 }
460 self.lengths[usize::from(next)..usize::from(next + count)].fill(length);
461 self.finish_lengths(count)?;
462 }
463 _ => unreachable!("only dynamic-table phases enter this helper"),
464 }
465 Ok(true)
466 }
467
468 #[inline]
469 fn copy_stored(&mut self, input: &mut &[u8], output: &mut [u8], remaining: u16) -> usize {
470 let next_input = self.bits.total.saturating_add(1);
474 let ratio_limit = next_input
475 .saturating_mul(u64::from(self.limits.max_ratio))
476 .saturating_add(self.limits.ratio_slack);
477 if self.bits.count != 0 || self.total_output >= ratio_limit {
478 return 0;
479 }
480 let budget = if self.limits.max_ratio == 0 {
481 self.limits.max_output.min(self.limits.ratio_slack)
482 } else {
483 self.limits.max_output
484 };
485 let count = usize::from(remaining)
486 .min(input.len())
487 .min(output.len())
488 .min(WINDOW_SIZE)
489 .min(
490 budget
491 .saturating_sub(self.total_output)
492 .min(u16::MAX as u64) as usize,
493 )
494 .min((u64::MAX - self.bits.total).min(u16::MAX as u64) as usize);
495 if count == 0 {
496 return 0;
497 }
498 output[..count].copy_from_slice(&input[..count]);
499 self.bits.total += count as u64;
500 *input = &input[count..];
501 self.emit_slice(&output[..count]);
502 self.state = State::Stored(remaining - count as u16);
503 count
504 }
505
506 #[inline]
507 fn copy_back_reference(
508 &mut self,
509 output: &mut [u8],
510 remaining: u16,
511 distance: u16,
512 ) -> Result<usize> {
513 let count = usize::from(remaining)
514 .min(output.len())
515 .min(self.output_budget().min(u16::MAX as u64) as usize);
516 if count == 0 {
517 return Err(Error::LimitExceeded);
518 }
519 let target = &mut output[..count];
520 let distance = usize::from(distance);
521 let position = (self.position + WINDOW_SIZE - distance) & (WINDOW_SIZE - 1);
522 let seed = count.min(distance);
523 let first = seed.min(WINDOW_SIZE - position);
524 target[..first].copy_from_slice(&self.window[position..position + first]);
525 target[first..seed].copy_from_slice(&self.window[..seed - first]);
526 let mut initialized = seed;
529 while initialized < count {
530 let next = initialized.min(count - initialized);
531 target.copy_within(..next, initialized);
532 initialized += next;
533 }
534 self.emit_slice(target);
535 self.state = if remaining == count as u16 {
536 State::Compressed
537 } else {
538 State::Copy {
539 remaining: remaining - count as u16,
540 distance: distance as u16,
541 }
542 };
543 Ok(count)
544 }
545
546 fn output_budget(&self) -> u64 {
547 let ratio_limit = self
548 .bits
549 .total
550 .saturating_mul(u64::from(self.limits.max_ratio))
551 .saturating_add(self.limits.ratio_slack);
552 self.limits
553 .max_output
554 .min(ratio_limit)
555 .saturating_sub(self.total_output)
556 }
557
558 fn emit(&mut self, byte: u8, output: &mut u8) -> Result<()> {
559 if self.output_budget() == 0 {
560 return Err(Error::LimitExceeded);
561 }
562 *output = byte;
563 self.emit_slice(core::slice::from_ref(output));
564 Ok(())
565 }
566
567 #[inline]
569 fn emit_slice(&mut self, bytes: &[u8]) {
570 let first = bytes.len().min(WINDOW_SIZE - self.position);
571 self.window[self.position..self.position + first].copy_from_slice(&bytes[..first]);
572 self.window[..bytes.len() - first].copy_from_slice(&bytes[first..]);
573 self.position = (self.position + bytes.len()) & (WINDOW_SIZE - 1);
574 self.total_output += bytes.len() as u64;
575 self.adler.update(bytes);
576 }
577
578 fn end_block(&mut self) {
579 self.state = if self.final_block {
580 self.bits.align();
581 if self.raw {
582 State::Done
583 } else {
584 State::Trailer { read: 0, value: 0 }
585 }
586 } else {
587 State::Block
588 };
589 }
590
591 fn fixed_tables(&mut self) -> Result<()> {
592 self.lengths[..144].fill(8);
593 self.lengths[144..256].fill(9);
594 self.lengths[256..280].fill(7);
595 self.lengths[280..288].fill(8);
596 self.lengths[288..].fill(5);
597 self.literal.build(&self.lengths[..288], false, false)?;
598 self.distance.build(&self.lengths[288..], false, false)
599 }
600
601 fn finish_lengths(&mut self, count: u16) -> Result<()> {
602 self.dynamic.next += count;
603 let Dynamic {
604 next,
605 literal,
606 total,
607 } = self.dynamic;
608 self.state = if next == total {
609 if self.lengths[256] == 0 {
610 return Err(Error::InvalidZlib);
611 }
612 self.literal
613 .build(&self.lengths[..usize::from(literal)], false, true)?;
614 self.distance.build(
615 &self.lengths[usize::from(literal)..usize::from(total)],
616 true,
617 true,
618 )?;
619 State::Compressed
620 } else {
621 State::Lengths
622 };
623 Ok(())
624 }
625}
626
627fn zlib_window(header: u32) -> Result<usize> {
628 let cmf = header & 255;
629 let flg = header >> 8;
630 if cmf & 15 != 8 || cmf >> 4 > 7 || (cmf * 256 + flg) % 31 != 0 {
631 return Err(Error::InvalidZlib);
632 }
633 if flg & 32 != 0 {
634 return Err(Error::Unsupported);
635 }
636 Ok(1 << ((cmf >> 4) + 8))
637}
638
639#[derive(Clone, Copy, Default)]
641struct Dynamic {
642 next: u16,
643 literal: u16,
644 total: u16,
645}
646
647#[derive(Clone, Copy)]
648enum State {
649 Header,
650 Block,
651 StoredLength,
652 StoredComplement(u16),
653 Stored(u16),
654 Dynamic,
655 CodeLengths {
656 next: u8,
657 count: u8,
658 },
659 Lengths,
660 Repeat(u16),
661 Compressed,
662 Literal {
663 byte: u8,
664 stored_remaining: Option<u16>,
665 },
666 Length(u16),
667 Distance(u16),
668 DistanceExtra {
669 length: u16,
670 index: u16,
671 },
672 Copy {
673 remaining: u16,
674 distance: u16,
675 },
676 Trailer {
677 read: u8,
678 value: u32,
679 },
680 Done,
681}