]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
Assert no divison by 0, correct superblocks 0 sequences case (#2592)
authorsen <senhuang96@fb.com>
Fri, 7 May 2021 17:26:56 +0000 (13:26 -0400)
committerGitHub <noreply@github.com>
Fri, 7 May 2021 17:26:56 +0000 (13:26 -0400)
lib/compress/zstd_compress.c
lib/compress/zstd_compress_sequences.c
lib/compress/zstd_compress_superblock.c

index 15a5c7c8d339a2245f798bc71cd115324bd1e0c4..b7ee2980a776d1d3c57d3eb2c9f1538559d63359 100644 (file)
@@ -2418,8 +2418,9 @@ typedef struct {
 } ZSTD_symbolEncodingTypeStats_t;
 
 /* ZSTD_buildSequencesStatistics():
- * Returns the size of the statistics for a given set of sequences, or a ZSTD error code,
- * Also modifies LLtype, Offtype, MLtype, and lastNCount to the appropriate values.
+ * Returns a ZSTD_symbolEncodingTypeStats_t, or a zstd error code in the `size` field.
+ * Modifies `nextEntropy` to have the appropriate values as a side effect.
+ * nbSeq must be greater than 0.
  *
  * entropyWkspSize must be of size at least ENTROPY_WORKSPACE_SIZE - (MaxSeq + 1)*sizeof(U32)
  */
@@ -2444,6 +2445,7 @@ ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq,
     /* convert length/distances into codes */
     ZSTD_seqToCodes(seqStorePtr);
     assert(op <= oend);
+    assert(nbSeq != 0); /* ZSTD_selectEncodingType() divides by nbSeq */
     /* build CTable for Literal Lengths */
     {   unsigned max = MaxLL;
         size_t const mostFrequent = HIST_countFast_wksp(countWorkspace, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);   /* can't fail */
@@ -3121,6 +3123,20 @@ static size_t ZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSi
     }
 }
 
+
+/* ZSTD_buildDummySequencesStatistics():
+ * Returns a ZSTD_symbolEncodingTypeStats_t with all encoding types as set_basic,
+ * and updates nextEntropy to the appropriate repeatMode.
+ */
+static ZSTD_symbolEncodingTypeStats_t
+ZSTD_buildDummySequencesStatistics(ZSTD_fseCTables_t* nextEntropy) {
+    ZSTD_symbolEncodingTypeStats_t stats = {set_basic, set_basic, set_basic, 0, 0};
+    nextEntropy->litlength_repeatMode = FSE_repeat_none;
+    nextEntropy->offcode_repeatMode = FSE_repeat_none;
+    nextEntropy->matchlength_repeatMode = FSE_repeat_none;
+    return stats;
+}
+
 /** ZSTD_buildBlockEntropyStats_sequences() :
  *  Builds entropy for the sequences.
  *  Stores symbol compression modes and fse table to fseMetadata.
@@ -3144,10 +3160,11 @@ static size_t ZSTD_buildBlockEntropyStats_sequences(seqStore_t* seqStorePtr,
     ZSTD_symbolEncodingTypeStats_t stats;
 
     DEBUGLOG(5, "ZSTD_buildBlockEntropyStats_sequences (nbSeq=%zu)", nbSeq);
-    stats = ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq,
-                                        prevEntropy, nextEntropy, op, oend,
-                                        strategy, countWorkspace,
-                                        entropyWorkspace, entropyWorkspaceSize);
+    stats = nbSeq != 0 ? ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq,
+                                          prevEntropy, nextEntropy, op, oend,
+                                          strategy, countWorkspace,
+                                          entropyWorkspace, entropyWorkspaceSize)
+                       : ZSTD_buildDummySequencesStatistics(nextEntropy);
     FORWARD_IF_ERROR(stats.size, "ZSTD_buildSequencesStatistics failed!");
     fseMetadata->llType = (symbolEncodingType_e) stats.LLtype;
     fseMetadata->ofType = (symbolEncodingType_e) stats.Offtype;
index 08a5b89019dd2e3c83a2cdfab80c838dc5694ba0..611eabdcbbbfa7845e69c46af589c097e68c1bfb 100644 (file)
@@ -85,6 +85,8 @@ static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t
 {
     unsigned cost = 0;
     unsigned s;
+
+    assert(total > 0);
     for (s = 0; s <= max; ++s) {
         unsigned norm = (unsigned)((256 * count[s]) / total);
         if (count[s] != 0 && norm == 0)
index e6376edf5b59a42061312af4f145815d69c734c7..e4e45069bc1b390a0a1e75dfc0f8132c892361cb 100644 (file)
@@ -365,8 +365,9 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
                                                   void* workspace, size_t wkspSize,
                                                   int writeEntropy)
 {
-    size_t sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
+    size_t const sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
     size_t cSeqSizeEstimate = 0;
+    if (nbSeq == 0) return sequencesSectionHeaderSize;
     cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
                                          nbSeq, fseTables->offcodeCTable, NULL,
                                          OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,