ZSTD_execSequence() accepts match in last 7 bytes
The zstd reference compressor will not emit a match in the last 7 bytes of a block. The decompressor will also not accept a match in the last 7 bytes. This patch makes the decompressor accept a match in the last 7 bytes.
This commit is contained in:
@@ -31,6 +31,16 @@
|
|||||||
# endif /* __STDC_VERSION__ */
|
# endif /* __STDC_VERSION__ */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# define FORCE_NOINLINE static __declspec(noinline)
|
||||||
|
#else
|
||||||
|
# ifdef __GNUC__
|
||||||
|
# define FORCE_NOINLINE static __attribute__((__noinline__))
|
||||||
|
# else
|
||||||
|
# define FORCE_NOINLINE static
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*-*************************************
|
/*-*************************************
|
||||||
* Dependencies
|
* Dependencies
|
||||||
|
|||||||
@@ -840,6 +840,53 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FORCE_NOINLINE
|
||||||
|
size_t ZSTD_execSequenceLast7(BYTE* op,
|
||||||
|
BYTE* const oend, seq_t sequence,
|
||||||
|
const BYTE** litPtr, const BYTE* const litLimit_w,
|
||||||
|
const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
|
||||||
|
{
|
||||||
|
BYTE* const oLitEnd = op + sequence.litLength;
|
||||||
|
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
|
||||||
|
BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
|
||||||
|
BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
|
||||||
|
const BYTE* const iLitEnd = *litPtr + sequence.litLength;
|
||||||
|
const BYTE* match = oLitEnd - sequence.offset;
|
||||||
|
|
||||||
|
/* check */
|
||||||
|
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
||||||
|
if (iLitEnd > litLimit_w) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
||||||
|
if (oLitEnd <= oend_w) return ERROR(GENERIC); /* Precondition */
|
||||||
|
|
||||||
|
/* copy literals */
|
||||||
|
if (op < oend_w) {
|
||||||
|
ZSTD_wildcopy(op, *litPtr, oend_w - op);
|
||||||
|
*litPtr += oend_w - op;
|
||||||
|
op = oend_w;
|
||||||
|
}
|
||||||
|
while (op < oLitEnd) *op++ = *(*litPtr)++;
|
||||||
|
|
||||||
|
/* copy Match */
|
||||||
|
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
||||||
|
/* offset beyond prefix */
|
||||||
|
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
||||||
|
match = dictEnd - (base-match);
|
||||||
|
if (match + sequence.matchLength <= dictEnd) {
|
||||||
|
memmove(oLitEnd, match, sequence.matchLength);
|
||||||
|
return sequenceLength;
|
||||||
|
}
|
||||||
|
/* span extDict & currentPrefixSegment */
|
||||||
|
{ size_t const length1 = dictEnd - match;
|
||||||
|
memmove(oLitEnd, match, length1);
|
||||||
|
op = oLitEnd + length1;
|
||||||
|
sequence.matchLength -= length1;
|
||||||
|
match = base;
|
||||||
|
} }
|
||||||
|
while (op < oMatchEnd) *op++ = *match++;
|
||||||
|
return sequenceLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FORCE_INLINE
|
FORCE_INLINE
|
||||||
size_t ZSTD_execSequence(BYTE* op,
|
size_t ZSTD_execSequence(BYTE* op,
|
||||||
BYTE* const oend, seq_t sequence,
|
BYTE* const oend, seq_t sequence,
|
||||||
@@ -854,8 +901,9 @@ size_t ZSTD_execSequence(BYTE* op,
|
|||||||
const BYTE* match = oLitEnd - sequence.offset;
|
const BYTE* match = oLitEnd - sequence.offset;
|
||||||
|
|
||||||
/* check */
|
/* check */
|
||||||
if ((oLitEnd>oend_w) | (oMatchEnd>oend)) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
if (oMatchEnd>oend) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
||||||
if (iLitEnd > litLimit_w) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
if (iLitEnd > litLimit_w) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
||||||
|
if (oLitEnd>oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit_w, base, vBase, dictEnd);
|
||||||
|
|
||||||
/* copy Literals */
|
/* copy Literals */
|
||||||
ZSTD_copy8(op, *litPtr);
|
ZSTD_copy8(op, *litPtr);
|
||||||
|
|||||||
Reference in New Issue
Block a user