From f5002981fd3e1b7db69181497e16a6c714a5abf7 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Fri, 12 Apr 2024 10:40:16 +0200 Subject: [PATCH] zstd: BuildDict fails with RLE table We cannot build a useable table if RLE. Add a fake entry to generate valid tables. --- zstd/dict.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/zstd/dict.go b/zstd/dict.go index 8d5567fe64..171b814a63 100644 --- a/zstd/dict.go +++ b/zstd/dict.go @@ -273,6 +273,9 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { enc.Encode(&block, b) addValues(&remain, block.literals) litTotal += len(block.literals) + if len(block.sequences) == 0 { + continue + } seqs += len(block.sequences) block.genCodes() addHist(&ll, block.coders.llEnc.Histogram()) @@ -336,6 +339,9 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { if seqs/nUsed < 512 { // Use 512 as minimum. nUsed = seqs / 512 + if nUsed == 0 { + nUsed = 1 + } } copyHist := func(dst *fseEncoder, src *[256]int) ([]byte, error) { hist := dst.Histogram() @@ -358,6 +364,28 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { fakeLength += v hist[i] = uint32(v) } + + // Ensure we aren't trying to represent RLE. + if maxCount == fakeLength { + for i := range hist { + if uint8(i) == maxSym { + fakeLength++ + maxSym++ + hist[i+1] = 1 + if maxSym > 1 { + break + } + } + if hist[0] == 0 { + fakeLength++ + hist[i] = 1 + if maxSym > 1 { + break + } + } + } + } + dst.HistogramFinished(maxSym, maxCount) dst.reUsed = false dst.useRLE = false