in csharp/src/ZStdDecompress.cs [1355:1441]
static size_t ExecSequenceLong(BYTE* op,
BYTE* oend, seq_t sequence,
BYTE** litPtr, BYTE* litLimit,
BYTE* prefixStart, BYTE* dictStart, BYTE* dictEnd)
{
BYTE* oLitEnd = op + sequence.litLength;
size_t sequenceLength = sequence.litLength + sequence.matchLength;
BYTE* oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
BYTE* oend_w = oend - WILDCOPY_OVERLENGTH;
BYTE* iLitEnd = *litPtr + sequence.litLength;
BYTE* match = sequence.match;
/* check */
if (oMatchEnd > oend) return ERROR(Error.dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
if (iLitEnd > litLimit) return ERROR(Error.corruption_detected); /* over-read beyond lit buffer */
if (oLitEnd > oend_w) return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, prefixStart, dictStart, dictEnd);
/* copy Literals */
ZSTD_copy8(op, *litPtr); /* note : op <= oLitEnd <= oend_w == oend - 8 */
if (sequence.litLength > 8)
Wildcopy(op + 8, (*litPtr) + 8, (int)(sequence.litLength - 8)); /* note : since oLitEnd <= oend- WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
op = oLitEnd;
*litPtr = iLitEnd; /* update for next sequence */
/* copy Match */
if (sequence.offset > (size_t)(oLitEnd - prefixStart))
{
/* offset beyond prefix */
if (sequence.offset > (size_t)(oLitEnd - dictStart)) return ERROR(Error.corruption_detected);
if (match + sequence.matchLength <= dictEnd)
{
memmove(oLitEnd, match, sequence.matchLength);
return sequenceLength;
}
/* span extDict & currentPrefixSegment */
{
size_t length1 = (size_t)(dictEnd - match);
memmove(oLitEnd, match, length1);
op = oLitEnd + length1;
sequence.matchLength -= length1;
match = prefixStart;
if (op > oend_w || sequence.matchLength < MINMATCH)
{
U32 i;
for (i = 0; i < sequence.matchLength; ++i) op[i] = match[i];
return sequenceLength;
}
}
}
Debug.Assert(op <= oend_w);
Debug.Assert(sequence.matchLength >= MINMATCH);
/* match within prefix */
if (sequence.offset < 8)
{
/* close range match, overlap */
int sub2 = dec64table[sequence.offset];
op[0] = match[0];
op[1] = match[1];
op[2] = match[2];
op[3] = match[3];
match += dec32table[sequence.offset];
ZSTD_copy4(op + 4, match);
match -= sub2;
}
else
{
ZSTD_copy8(op, match);
}
op += 8; match += 8;
if (oMatchEnd > oend - (16 - MINMATCH))
{
if (op < oend_w)
{
Wildcopy(op, match, (int)(oend_w - op));
match += oend_w - op;
op = oend_w;
}
while (op < oMatchEnd) *op++ = *match++;
}
else
{
Wildcopy(op, match, (int)(sequence.matchLength - 8)); /* works even if matchLength < 8 */
}
return sequenceLength;
}