From abe12b339994a15cd176df65ceb3a5345e2d47aa Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 28 Jul 2017 11:54:28 -0700 Subject: [PATCH] [libzstd] Fix bug in Huffman decompresser The zstd format specification doesn't enforce that Huffman compressed literals (including the table) have to be smaller than the uncompressed literals. The compressor will never Huffman compress literals if the compressed size is larger than the uncompressed size. The decompresser doesn't accept Huffman compressed literals with 4 streams whose compressed size is at least as large as the uncompressed size. * Make the decompresser accept Huffman compressed literals whose size increases. * Add a test case that exposes the bug. The compressed file has to be statically generated, since the compressor won't normally produce files that expose the bug. --- lib/decompress/huf_decompress.c | 6 +++--- tests/files/huffman-compressed-larger | Bin 0 -> 143 bytes tests/playTests.sh | 7 +++++++ 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 tests/files/huffman-compressed-larger diff --git a/lib/decompress/huf_decompress.c b/lib/decompress/huf_decompress.c index 2a1b70ea5..0a47a3d74 100644 --- a/lib/decompress/huf_decompress.c +++ b/lib/decompress/huf_decompress.c @@ -917,11 +917,11 @@ static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, qu * Tells which decoder is likely to decode faster, * based on a set of pre-determined metrics. * @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 . -* Assumption : 0 < cSrcSize < dstSize <= 128 KB */ +* Assumption : 0 < cSrcSize, dstSize <= 128 KB */ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize) { /* decoder timing evaluation */ - U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */ + U32 const Q = cSrcSize >= dstSize ? 15 : (U32)(cSrcSize * 16 / dstSize); /* Q < 16 */ U32 const D256 = (U32)(dstSize >> 8); U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256); U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256); @@ -977,7 +977,7 @@ size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, { /* validation checks */ if (dstSize == 0) return ERROR(dstSize_tooSmall); - if ((cSrcSize >= dstSize) || (cSrcSize <= 1)) return ERROR(corruption_detected); /* invalid */ + if (cSrcSize == 0) return ERROR(corruption_detected); { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); return algoNb ? HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize): diff --git a/tests/files/huffman-compressed-larger b/tests/files/huffman-compressed-larger new file mode 100644 index 0000000000000000000000000000000000000000..f594f1ae9816a52054935aab96eec94c4ffe14b7 GIT binary patch literal 143 zc-jGv0C4{(wJ-eyP!$9KW`-Ueka7hx0Dvr|0RR9101)1^uIswqo=F4%0Du4hfEEB3 z02Tl|2JCX%cWtRD`Y@9(#KBM?3Vi8VgP*Qj(lfvmE1c0RaG879=~%<1Ug5Gim?; literal 0 Hc-jL100001 diff --git a/tests/playTests.sh b/tests/playTests.sh index 77853b1a4..bc8584e7a 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -386,6 +386,13 @@ $ZSTD -t tmpSplit.* && die "bad file not detected !" ./datagen | $ZSTD -c | $ZSTD -t + +$ECHO "\n**** golden files tests **** " + +$ZSTD -t -r files +$ZSTD -c -r files | $ZSTD -t + + $ECHO "\n**** benchmark mode tests **** " $ECHO "bench one file" -- 2.47.2