deflate: fix zlib stream magic detection
[nihav.git] / nihav-core / src / compr / deflate.rs
index 89e8b6874ea4ae71005f8130fd92818697bb76eb..638e110b8e4d4bb709712a169c925d7b15366e56 100644 (file)
@@ -227,6 +227,7 @@ pub struct Inflate {
     buf:            [u8; 65536],
     bpos:           usize,
     output_idx:     usize,
+    full_pos:       usize,
 
     state:          InflateState,
     final_block:    bool,
@@ -305,6 +306,7 @@ impl Inflate {
             buf:            [0; 65536],
             bpos:           0,
             output_idx:     0,
+            full_pos:       0,
 
             state:          InflateState::Start,
             final_block:    false,
@@ -320,19 +322,21 @@ impl Inflate {
     }
     fn put_literal(&mut self, val: u8) {
         self.buf[self.bpos] = val;
-        self.bpos += 1;
+        self.bpos = (self.bpos + 1) & (self.buf.len() - 1);
+        self.full_pos += 1;
     }
     fn lz_copy(&mut self, offset: usize, len: usize, dst: &mut [u8]) -> DecompressResult<()> {
         let mask = self.buf.len() - 1;
-        if self.bpos < offset {
+        if offset > self.full_pos {
             return Err(DecompressError::InvalidData);
         }
-        let cstart = (self.bpos - offset) & mask;
+        let cstart = (self.bpos.wrapping_sub(offset)) & mask;
         for i in 0..len {
             self.buf[(self.bpos + i) & mask] = self.buf[(cstart + i) & mask];
             dst[i] = self.buf[(cstart + i) & mask];
         }
-        self.bpos += len;
+        self.bpos = (self.bpos + len) & mask;
+        self.full_pos += len;
         Ok(())
     }
     ///! Reports whether decoder has finished decoding the input.
@@ -355,6 +359,7 @@ impl Inflate {
     ///!
     ///! [`DecompressError::ShortData`]: ../enum.DecompressError.html#variant.ShortData
     ///! [`DecompressError::OutputFull`]: ../enum.DecompressError.html#variant.OutputFull
+    #[allow(clippy::comparison_chain)]
     pub fn decompress_data(&mut self, src: &[u8], dst: &mut [u8], continue_block: bool) -> DecompressResult<usize> {
         if src.is_empty() || dst.is_empty() {
             return Err(DecompressError::InvalidArgument);
@@ -716,7 +721,8 @@ impl Inflate {
     ///! Decompresses input data into output returning the uncompressed data length.
     pub fn uncompress(src: &[u8], dst: &mut [u8]) -> DecompressResult<usize> {
         let mut inflate = Self::new();
-        inflate.decompress_data(src, dst, false)
+        let off = if src.len() > 2 && src[0] == 0x78 && (src[1] != 0 && ((src[1] - 1) % 31) == 0) { 2 } else { 0 };
+        inflate.decompress_data(&src[off..], dst, false)
     }
 }