]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
Fix small bug in ZSTD_execSequence() 423/head
authorNick Terrell <terrelln@fb.com>
Thu, 20 Oct 2016 23:45:10 +0000 (16:45 -0700)
committerNick Terrell <terrelln@fb.com>
Fri, 21 Oct 2016 19:13:44 +0000 (12:13 -0700)
`memmove(op, match, sequence.matchLength)` is not the desired behavior.
Overlap is allowed, and handled as if we did `*op++ = *match++`, which
is not how `memmove()` handles overlap.

Only triggered if both of the following conditions are met:
* The match spans extDict & currentPrefixSegment
* `oLitEnd <= oend_w < oLitEnd + length1 < oMatchEnd <= oend`.

These two conditions imply that the block is less than 15 bytes long.
This bug isn't triggered by the streaming API, because it allocates
enough space for the window size + the block size, so there cannot be
a match that is within 8 bytes of the end and overlaps with itself.
It cannot be triggered by the block decompression API because all of
the decompressed data is in the currentPrefixSegment.

Introduced by commit 71585843998459e636f639165ff8a1ca9d161b62

lib/decompress/zstd_decompress.c
lib/legacy/zstd_v04.c
lib/legacy/zstd_v05.c
lib/legacy/zstd_v06.c
lib/legacy/zstd_v07.c

index 00b069e9fdd8a7f8cef22fd52ec36e216ce750c7..90c76faeb26b28d4f07ce6a059c60f0a5d22fe95 100644 (file)
@@ -880,7 +880,7 @@ size_t ZSTD_execSequence(BYTE* op,
             sequence.matchLength -= length1;
             match = base;
             if (op > oend_w) {
-              memmove(op, match, sequence.matchLength);
+              while (op < oMatchEnd) *op++ = *match++;
               return sequenceLength;
             }
     }   }
index 05e40aac51aea7a2a40cae74b7ec7d1ee4bcb7c5..a2332d93325b82e2f12d0b72b112a664ce323d2f 100644 (file)
@@ -3108,7 +3108,7 @@ static size_t ZSTD_execSequence(BYTE* op,
             sequence.matchLength -= length1;
             match = base;
             if (op > oend_8) {
-              memmove(op, match, sequence.matchLength);
+              while (op < oMatchEnd) *op++ = *match++;
               return sequenceLength;
             }
         }
index 3cb5bb4afedd447183f79ebfc3555a2f674216e6..0de28c9833a2d5deb3b221a904c351177e030fca 100644 (file)
@@ -2036,7 +2036,7 @@ size_t HUFv05_decompress1X2_usingDTable(
     const void* dtPtr = DTable;
     const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr)+1;
     BITv05_DStream_t bitD;
-    
+
     if (dstSize <= cSrcSize) return ERROR(dstSize_tooSmall);
     { size_t const errorCode = BITv05_initDStream(&bitD, cSrc, cSrcSize);
       if (HUFv05_isError(errorCode)) return errorCode; }
@@ -3317,7 +3317,7 @@ static size_t ZSTDv05_execSequence(BYTE* op,
             sequence.matchLength -= length1;
             match = base;
             if (op > oend_8) {
-              memmove(op, match, sequence.matchLength);
+              while (op < oMatchEnd) *op++ = *match++;
               return sequenceLength;
             }
     }   }
index 96a84d3e82851bc22e3e37521cf2d17db843b618..b1ff4be4a937fe6bb1bfbf8bf8e47387811e4a30 100644 (file)
@@ -3467,7 +3467,7 @@ size_t ZSTDv06_execSequence(BYTE* op,
             sequence.matchLength -= length1;
             match = base;
             if (op > oend_8) {
-              memmove(op, match, sequence.matchLength);
+              while (op < oMatchEnd) *op++ = *match++;
               return sequenceLength;
             }
     }   }
index 62285238aa637c7d67e75bbb2ffb75bec147d534..c679b97f23c0d961c47ea6de43f6d6386bdad383 100644 (file)
@@ -3691,7 +3691,7 @@ size_t ZSTDv07_execSequence(BYTE* op,
             sequence.matchLength -= length1;
             match = base;
             if (op > oend_w) {
-              memmove(op, match, sequence.matchLength);
+              while (op < oMatchEnd) *op++ = *match++;
               return sequenceLength;
             }
     }   }