]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
Add a fallback in case the total blocksize of split blocks exceeds raw block size
authorSen Huang <senhuang96@fb.com>
Mon, 22 Mar 2021 21:38:21 +0000 (14:38 -0700)
committerSen Huang <senhuang96@fb.com>
Wed, 24 Mar 2021 15:21:29 +0000 (08:21 -0700)
lib/compress/zstd_compress.c

index d29825c4659190aefa333bbda9273a57d26d0ff8..fe1516b79341cfc5b5c64f4be134dae7597391e1 100644 (file)
@@ -3327,6 +3327,7 @@ static size_t ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, s
     seqStore_t nextSeqStore;
     seqStore_t currSeqStore;
     U32 canEmitRLEorNoCompress = 1;
+    const size_t dstCapacityInitial = dstCapacity;
 
     DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
                 (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,
@@ -3370,6 +3371,14 @@ static size_t ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, s
         cSize += cSizeChunk;
         currSeqStore = nextSeqStore;
     }
+
+    if (cSize > ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize) {
+        /* If too large, recompress the original block to avoid any chance of a single block exceeding ZSTD_BLOCKSIZE_MAX */
+        cSize = ZSTD_compressSequences_singleBlock(zc, &zc->seqStore, (BYTE*)dst, dstCapacityInitial, (const BYTE*)src, blockSize, lastBlock, 1);
+        FORWARD_IF_ERROR(cSize, "Compressing single block from splitBlock_internal() fallback failed!");
+        DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal: Compressed split block too large, recompressed");
+    }
+    assert(cSize <= ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize);
     return cSize;
 }