Fix : decoder issue in exceptionnal circumstances (dst buffer too small)

This commit is contained in:
Yann Collet
2015-08-20 15:55:50 +01:00
parent 602834f794
commit 7d20acd340
+14 -12
View File
@@ -1405,7 +1405,7 @@ static size_t ZSTD_execSequence(BYTE* op, seq_t sequence, const BYTE** litPtr, B
static const int dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4}; /* added */ static const int dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4}; /* added */
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */ static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* substracted */
const BYTE* const ostart = op; const BYTE* const ostart = op;
size_t litLength = sequence.litLength; const size_t litLength = sequence.litLength;
BYTE* const endMatch = op + litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */ BYTE* const endMatch = op + litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
const BYTE* const litEnd = *litPtr + litLength; const BYTE* const litEnd = *litPtr + litLength;
@@ -1418,14 +1418,17 @@ static size_t ZSTD_execSequence(BYTE* op, seq_t sequence, const BYTE** litPtr, B
else else
ZSTD_wildcopy(op, *litPtr, litLength); ZSTD_wildcopy(op, *litPtr, litLength);
op += litLength; op += litLength;
*litPtr = litEnd; *litPtr = litEnd; /* update for next sequence */
/* copy Match */ /* check : last match must be at a minimum distance of 8 from end of dest buffer */
if (oend-op < 8) return (size_t)-ZSTD_ERROR_maxDstSize_tooSmall;
/* copy Match */
{ {
const BYTE* match = op - sequence.offset; /* possible underflow at op - offset ? */
size_t qutt=12;
U64 saved[2];
const U32 overlapRisk = (((size_t)(litEnd - endMatch)) < 12); const U32 overlapRisk = (((size_t)(litEnd - endMatch)) < 12);
const BYTE* match = op - sequence.offset; /* possible underflow at op - offset ? */
size_t qutt = 12;
U64 saved[2];
/* save beginning of literal sequence, in case of write overlap */ /* save beginning of literal sequence, in case of write overlap */
if (overlapRisk) if (overlapRisk)
@@ -1445,27 +1448,26 @@ static size_t ZSTD_execSequence(BYTE* op, seq_t sequence, const BYTE** litPtr, B
ZSTD_copy4(op+4, match); ZSTD_copy4(op+4, match);
match -= dec64; match -= dec64;
} else { ZSTD_copy8(op, match); } } else { ZSTD_copy8(op, match); }
op += 8; match += 8;
if (endMatch > oend-12) if (endMatch > oend-12)
{ {
if (op < oend-16) if (op < oend-8)
{ {
ZSTD_wildcopy(op+8, match+8, (oend-8) - (op+8)); ZSTD_wildcopy(op, match, (oend-8) - op);
match += (oend-8) - op; match += (oend-8) - op;
op = oend-8; op = oend-8;
} }
while (op<endMatch) *op++ = *match++; while (op<endMatch) *op++ = *match++;
} }
else else
ZSTD_wildcopy(op+8, match+8, sequence.matchLength-8); /* works even if matchLength < 8 */ ZSTD_wildcopy(op, match, sequence.matchLength-8); /* works even if matchLength < 8 */
op = endMatch;
/* restore, in case of overlap */ /* restore, in case of overlap */
if (overlapRisk) memcpy(endMatch, saved, qutt); if (overlapRisk) memcpy(endMatch, saved, qutt);
} }
return op-ostart; return endMatch-ostart;
} }