fixed write overflow found by fuzzer

This commit is contained in:
Yann Collet 2016-03-23 22:31:57 +01:00
parent 72d706a020
commit 7cbe79ab25
2 changed files with 37 additions and 34 deletions

View File

@ -589,7 +589,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
U16* const mlTable = seqStorePtr->matchLengthStart;
const U32* const offsetTable = seqStorePtr->offsetStart;
const U32* const offsetTableEnd = seqStorePtr->offset;
BYTE* const offCodeTable = seqStorePtr->offCodeStart;
BYTE* const ofCodeTable = seqStorePtr->offCodeStart;
BYTE* const llCodeTable = seqStorePtr->llCodeStart;
BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
BYTE* const ostart = (BYTE*)dst;
@ -607,7 +607,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
}
/* Sequences Header */
if ((oend-op) < MIN_SEQUENCES_SIZE) return ERROR(dstSize_tooSmall);
if ((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead */) return ERROR(dstSize_tooSmall);
if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
else op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;
@ -661,12 +661,12 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
} }
/* Offset codes */
{ size_t i; for (i=0; i<nbSeq; i++) offCodeTable[i] = offsetTable[i] ? (BYTE)ZSTD_highbit(offsetTable[i]) + 1 : 0; }
{ size_t i; for (i=0; i<nbSeq; i++) ofCodeTable[i] = offsetTable[i] ? (BYTE)ZSTD_highbit(offsetTable[i]) + 1 : 0; }
{ U32 max = MaxOff;
size_t const mostFrequent = FSE_countFast(count, &max, offCodeTable, nbSeq);
size_t const mostFrequent = FSE_countFast(count, &max, ofCodeTable, nbSeq);
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
*op++ = offCodeTable[0];
*op++ = ofCodeTable[0];
FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
Offtype = FSE_ENCODING_RLE;
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
@ -677,7 +677,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
} else {
size_t nbSeq_1 = nbSeq;
const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
if (count[offCodeTable[nbSeq-1]]>1) { count[offCodeTable[nbSeq-1]]--; nbSeq_1--; }
if (count[ofCodeTable[nbSeq-1]]>1) { count[ofCodeTable[nbSeq-1]]--; nbSeq_1--; }
FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
{ size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
@ -741,27 +741,30 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
/* first symbols */
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, offCodeTable[nbSeq-1]);
FSE_initCState2(&stateOffsetBits, CTable_OffsetBits, ofCodeTable[nbSeq-1]);
FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
BIT_addBits(&blockStream, llTable[nbSeq-1], LL_bits[llCodeTable[nbSeq-1]]);
BIT_addBits(&blockStream, mlTable[nbSeq-1], ML_bits[mlCodeTable[nbSeq-1]]);
BIT_addBits(&blockStream, offsetTable[nbSeq-1], offCodeTable[nbSeq-1] ? (offCodeTable[nbSeq-1]-1) : 0);
BIT_addBits(&blockStream, offsetTable[nbSeq-1], ofCodeTable[nbSeq-1] ? (ofCodeTable[nbSeq-1]-1) : 0);
BIT_flushBits(&blockStream);
{ size_t n;
for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
const BYTE MLCode = mlCodeTable[n];
const U32 offset = offsetTable[n];
const BYTE offCode = offCodeTable[n]; /* 32b*/ /* 64b*/
const U32 nbBits = (offCode-1) + (!offCode);
const BYTE LLCode = llCodeTable[n];
const BYTE ofCode = ofCodeTable[n]; /* 32b*/ /* 64b*/
const BYTE mlCode = mlCodeTable[n];
const BYTE llCode = llCodeTable[n];
const U32 llBits = LL_bits[llCode];
const U32 mlBits = ML_bits[mlCode];
const U32 ofBits = (ofCode-1) + (!ofCode);
/* (7)*/ /* (7)*/
FSE_encodeSymbol(&blockStream, &stateOffsetBits, offCode); /* 25 */ /* 35 */
FSE_encodeSymbol(&blockStream, &stateMatchLength, MLCode); /* 17 */ /* 17 */
FSE_encodeSymbol(&blockStream, &stateLitLength, LLCode); /* 16 */ /* 26 */
BIT_addBits(&blockStream, llTable[n], LL_bits[LLCode]);
BIT_addBits(&blockStream, mlTable[n], ML_bits[MLCode]);
BIT_addBits(&blockStream, offset, nbBits); /* 31 */ /* 61 */ /* 24 bits max in 32-bits mode */
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 25 */ /* 35 */
FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 17 */ /* 17 */
FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 26 */
if (ofBits + mlBits + llBits > 64 - 7 - 27)
BIT_flushBits(&blockStream);
BIT_addBits(&blockStream, llTable[n], llBits);
BIT_addBits(&blockStream, mlTable[n], mlBits);
BIT_addBits(&blockStream, offsetTable[n], ofBits); /* 31 */ /* 61 */ /* 24 bits max in 32-bits mode */
BIT_flushBits(&blockStream); /* 7 */ /* 7 */
} }
@ -1997,7 +2000,7 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* zc,
static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
void* dst, size_t dstSize,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
U32 frame)
{
@ -2006,10 +2009,10 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
if (frame && (zc->stage==0)) {
hbSize = zc->hbSize;
if (dstSize <= hbSize) return ERROR(dstSize_tooSmall);
if (dstCapacity <= hbSize) return ERROR(dstSize_tooSmall);
zc->stage = 1;
memcpy(dst, zc->headerBuffer, hbSize);
dstSize -= hbSize;
dstCapacity -= hbSize;
dst = (char*)dst + hbSize;
}
@ -2048,8 +2051,8 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
zc->nextSrc = ip + srcSize;
{ size_t const cSize = frame ?
ZSTD_compress_generic (zc, dst, dstSize, src, srcSize) :
ZSTD_compressBlock_internal (zc, dst, dstSize, src, srcSize);
ZSTD_compress_generic (zc, dst, dstCapacity, src, srcSize) :
ZSTD_compressBlock_internal (zc, dst, dstCapacity, src, srcSize);
if (ZSTD_isError(cSize)) return cSize;
return cSize + hbSize;
}
@ -2057,10 +2060,10 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
size_t ZSTD_compressContinue (ZSTD_CCtx* zc,
void* dst, size_t dstSize,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize)
{
return ZSTD_compressContinue_internal(zc, dst, dstSize, src, srcSize, 1);
return ZSTD_compressContinue_internal(zc, dst, dstCapacity, src, srcSize, 1);
}
@ -2283,18 +2286,18 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
/* Init */
{ size_t const errorCode = ZSTD_compressBegin_advanced(ctx, dict, dictSize, params);
if(ZSTD_isError(errorCode)) return errorCode; }
if(ZSTD_isError(errorCode)) return errorCode; }
/* body (compression) */
{ size_t const oSize = ZSTD_compressContinue (ctx, op, dstCapacity, src, srcSize);
if(ZSTD_isError(oSize)) return oSize;
op += oSize;
dstCapacity -= oSize; }
if(ZSTD_isError(oSize)) return oSize;
op += oSize;
dstCapacity -= oSize; }
/* Close frame */
{ size_t const oSize = ZSTD_compressEnd(ctx, op, dstCapacity);
if(ZSTD_isError(oSize)) return oSize;
op += oSize; }
if(ZSTD_isError(oSize)) return oSize;
op += oSize; }
return (op - ostart);
}

View File

@ -488,12 +488,12 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 maxDuration, doub
if (cSize > 3) {
const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
const size_t tooSmallSize = cSize - missing;
static const U32 endMark = 0x4DC2B1A9;
const U32 endMark = 0x4DC2B1A9;
memcpy(dstBuffer+tooSmallSize, &endMark, 4);
errorCode = ZSTD_compressCCtx(ctx, dstBuffer, tooSmallSize, sampleBuffer, sampleSize, cLevel);
CHECK(!ZSTD_isError(errorCode), "ZSTD_compressCCtx should have failed ! (buffer too small : %u < %u)", (U32)tooSmallSize, (U32)cSize);
{ U32 endCheck; memcpy(&endCheck, dstBuffer+tooSmallSize, 4);
CHECK(endCheck != endMark, "ZSTD_compressCCtx : dst buffer overflow"); }
CHECK(endCheck != endMark, "ZSTD_compressCCtx : dst buffer overflow"); }
}
/* frame header decompression test */