]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
Fix #4553 fix4553 4555/head
authorYann Collet <cyan@fb.com>
Thu, 18 Dec 2025 23:52:11 +0000 (15:52 -0800)
committerYann Collet <cyan@fb.com>
Thu, 18 Dec 2025 23:52:11 +0000 (15:52 -0800)
This is a bug in the streaming implementation of the v0.5 decoder.
The bug has always been there.
It requires an uncommon block configuration, which wasn't tested at the time.

v0.5 is deprecated now,
latest version to produce such format is v0.5.1 from February 2016.
It was superceded in April 2016.
So it's both short lived and very old.

Another PR will remove support of this format,
but it will still be possible to explicitely request this support on demand,
so better fix the issue.

lib/legacy/zstd_v05.c

index e1efca597ce71b71b2af6cadb670677f9c864d94..ee180487e942af2dafa84c2d7718f2037088017b 100644 (file)
@@ -3972,8 +3972,15 @@ size_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* zbc, void* dst, size_t* maxDst
                 zbc->outStart += flushedSize;
                 if (flushedSize == toFlushSize) {
                     zbc->stage = ZBUFFv05ds_read;
-                    if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize)
-                        zbc->outStart = zbc->outEnd = 0;
+                    if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize) {
+                        /* Not enough room for next block - need to wrap buffer.
+                         * Preserve history: copy the last windowSize bytes to the
+                         * beginning so that back-references can still find valid data. */
+                        size_t const windowSize = (size_t)1 << zbc->params.windowLog;
+                        size_t const preserveSize = MIN(zbc->outEnd, windowSize);
+                        memmove(zbc->outBuff, zbc->outBuff + zbc->outEnd - preserveSize, preserveSize);
+                        zbc->outStart = zbc->outEnd = preserveSize;
+                    }
                     break;
                 }
                 /* cannot flush everything */