]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
[legacy] Fix bug in zstd-0.5 decoder 1696/head
authorNick Terrell <terrelln@fb.com>
Mon, 22 Jul 2019 20:05:09 +0000 (13:05 -0700)
committerNick Terrell <terrelln@fb.com>
Mon, 22 Jul 2019 20:05:09 +0000 (13:05 -0700)
The match length and literal length extra bytes could either
by 2 bytes or 3 bytes in version 0.5. All earlier verions were
always 3 bytes, and later version didn't have dumps.

The bug, introduced by commit 0fd322f812211e653a83492c0c114b933f8b6bc5,
was triggered when the last dump was a 2-byte dump, because we didn't
separate that case from a 3-byte dump, and thought we were over-reading.

I've tested this fix with every zstd version < 1.0.0 on the buggy file,
and we are now always successfully decompressing with the right
checksum.

Fixes #1693.

lib/legacy/zstd_v05.c

index a7ea6066fb0837c56fe229fa6d4510ee26dedf9a..e347b00dcf2e611229898476a4bd3d2ff933b078 100644 (file)
@@ -218,11 +218,6 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
     }
 }
 
-MEM_STATIC U32 MEM_readLE24(const void* memPtr)
-{
-    return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
-}
-
 MEM_STATIC U32 MEM_readLE32(const void* memPtr)
 {
     if (MEM_isLittleEndian())
@@ -3158,10 +3153,14 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)
     if (litLength == MaxLL) {
         const U32 add = *dumps++;
         if (add < 255) litLength += add;
-        else if (dumps + 3 <= de) {
-            litLength = MEM_readLE24(dumps);
-            if (litLength&1) litLength>>=1, dumps += 3;
-            else litLength = (U16)(litLength)>>1, dumps += 2;
+        else if (dumps + 2 <= de) {
+            litLength = MEM_readLE16(dumps);
+            dumps += 2;
+            if ((litLength & 1) && dumps < de) {
+                litLength += *dumps << 16;
+                dumps += 1;
+            }
+            litLength>>=1;
         }
         if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */
     }
@@ -3191,10 +3190,14 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)
     if (matchLength == MaxML) {
         const U32 add = dumps<de ? *dumps++ : 0;
         if (add < 255) matchLength += add;
-        else if (dumps + 3 <= de) {
-            matchLength = MEM_readLE24(dumps);
-            if (matchLength&1) matchLength>>=1, dumps += 3;
-            else matchLength = (U16)(matchLength)>>1, dumps += 2;
+        else if (dumps + 2 <= de) {
+            matchLength = MEM_readLE16(dumps);
+            dumps += 2;
+            if ((matchLength & 1) && dumps < de) {
+                matchLength += *dumps << 16;
+                dumps += 1;
+            }
+            matchLength >>= 1;
         }
         if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */
     }