]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
[zstd] Fix decompression edge case
authorNick Terrell <terrelln@fb.com>
Wed, 23 May 2018 19:16:00 +0000 (12:16 -0700)
committerNick Terrell <terrelln@fb.com>
Wed, 23 May 2018 19:16:00 +0000 (12:16 -0700)
This edge case is only possible with the new optimal encoding selector,
since before zstd would always choose `set_basic` for small numbers of
sequences.

Fix `FSE_readNCount()` to support buffers < 4 bytes.

Credit to OSS-Fuzz

lib/common/entropy_common.c

index 344c323615f6da5528bee781bbc8b83754183eec..a8d0b146becf2df12dd2fcda2e65841054cc444c 100644 (file)
@@ -72,7 +72,14 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
     unsigned charnum = 0;
     int previous0 = 0;
 
-    if (hbSize < 4) return ERROR(srcSize_wrong);
+    if (hbSize < 4) {
+      /* This function only works when hbSize >= 4 */
+      char buffer[4];
+      memset(buffer, 0, sizeof(buffer));
+      memcpy(buffer, headerBuffer, hbSize);
+      return FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr, buffer, sizeof(buffer));
+    }
+
     bitStream = MEM_readLE32(ip);
     nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */
     if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
@@ -105,6 +112,7 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
             if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);
             while (charnum < n0) normalizedCounter[charnum++] = 0;
             if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
+                assert((bitCount >> 3) <= 3); /* For first condition to work */
                 ip += bitCount>>3;
                 bitCount &= 7;
                 bitStream = MEM_readLE32(ip) >> bitCount;