]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
Fix compression segfault
authorNick Terrell <terrelln@fb.com>
Sat, 10 Dec 2016 01:15:33 +0000 (17:15 -0800)
committerNick Terrell <terrelln@fb.com>
Sat, 10 Dec 2016 01:15:33 +0000 (17:15 -0800)
When the overflow protection kicks in, it makes sure that ip - ctx->base
isn't too large.  However, it didn't ensure that saved offsets are
still valid.  This change ensures that any valid offsets (<= windowLog)
are still representable after the update.

The bug would shop up on line 1056, when `offset_1 > current + 1`, which
causes an underflow.  This in turn, would cause a segfault on line 1063.

The input must necessarily be longer than 1 GB for this issue to occur.
Even then, it only occurs if one of the last 3 matches is larger than
the chain size and block size.

lib/compress/zstd_compress.c

index 665d09c0febc7f37146bce1478d611c94a3ace90..a575534c3da987d83b2fd61002bb44cbe9f5efde 100644 (file)
@@ -2277,7 +2277,7 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
         if (cctx->lowLimit > (1<<30)) {
             U32 const btplus = (cctx->params.cParams.strategy == ZSTD_btlazy2) | (cctx->params.cParams.strategy == ZSTD_btopt) | (cctx->params.cParams.strategy == ZSTD_btopt2);
             U32 const chainMask = (1 << (cctx->params.cParams.chainLog - btplus)) - 1;
-            U32 const supLog = MAX(cctx->params.cParams.chainLog, 17 /* blockSize */);
+            U32 const supLog = MAX(MAX(cctx->params.cParams.chainLog, 17 /* blockSize */), cctx->params.cParams.windowLog);
             U32 const newLowLimit = (cctx->lowLimit & chainMask) + (1 << supLog);   /* preserve position % chainSize, ensure current-repcode doesn't underflow */
             U32 const correction = cctx->lowLimit - newLowLimit;
             ZSTD_reduceIndex(cctx, correction);