fixed write overflow found by fuzzer
This commit is contained in:
+35
-32
@@ -589,7 +589,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
|
|||||||
U16* const mlTable = seqStorePtr->matchLengthStart;
|
U16* const mlTable = seqStorePtr->matchLengthStart;
|
||||||
const U32* const offsetTable = seqStorePtr->offsetStart;
|
const U32* const offsetTable = seqStorePtr->offsetStart;
|
||||||
const U32* const offsetTableEnd = seqStorePtr->offset;
|
const U32* const offsetTableEnd = seqStorePtr->offset;
|
||||||
BYTE* const offCodeTable = seqStorePtr->offCodeStart;
|
BYTE* const ofCodeTable = seqStorePtr->offCodeStart;
|
||||||
BYTE* const llCodeTable = seqStorePtr->llCodeStart;
|
BYTE* const llCodeTable = seqStorePtr->llCodeStart;
|
||||||
BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
|
BYTE* const mlCodeTable = seqStorePtr->mlCodeStart;
|
||||||
BYTE* const ostart = (BYTE*)dst;
|
BYTE* const ostart = (BYTE*)dst;
|
||||||
@@ -607,7 +607,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Sequences Header */
|
/* 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;
|
if (nbSeq < 0x7F) *op++ = (BYTE)nbSeq;
|
||||||
else if (nbSeq < LONGNBSEQ) op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;
|
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;
|
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 */
|
/* 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;
|
{ 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)) {
|
if ((mostFrequent == nbSeq) && (nbSeq > 2)) {
|
||||||
*op++ = offCodeTable[0];
|
*op++ = ofCodeTable[0];
|
||||||
FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
|
FSE_buildCTable_rle(CTable_OffsetBits, (BYTE)max);
|
||||||
Offtype = FSE_ENCODING_RLE;
|
Offtype = FSE_ENCODING_RLE;
|
||||||
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
|
} else if ((zc->flagStaticTables) && (nbSeq < MAX_SEQ_FOR_STATIC_FSE)) {
|
||||||
@@ -677,7 +677,7 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
|
|||||||
} else {
|
} else {
|
||||||
size_t nbSeq_1 = nbSeq;
|
size_t nbSeq_1 = nbSeq;
|
||||||
const U32 tableLog = FSE_optimalTableLog(OffFSELog, nbSeq, max);
|
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);
|
FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max);
|
||||||
{ size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
|
{ size_t const NCountSize = FSE_writeNCount(op, oend-op, norm, max, tableLog); /* overflow protected */
|
||||||
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
|
if (FSE_isError(NCountSize)) return ERROR(GENERIC);
|
||||||
@@ -741,27 +741,30 @@ size_t ZSTD_compressSequences(ZSTD_CCtx* zc,
|
|||||||
|
|
||||||
/* first symbols */
|
/* first symbols */
|
||||||
FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);
|
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]);
|
FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
|
||||||
BIT_addBits(&blockStream, llTable[nbSeq-1], LL_bits[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, 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);
|
BIT_flushBits(&blockStream);
|
||||||
|
|
||||||
{ size_t n;
|
{ size_t n;
|
||||||
for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
|
for (n=nbSeq-2 ; n<nbSeq ; n--) { /* intentional underflow */
|
||||||
const BYTE MLCode = mlCodeTable[n];
|
const BYTE ofCode = ofCodeTable[n]; /* 32b*/ /* 64b*/
|
||||||
const U32 offset = offsetTable[n];
|
const BYTE mlCode = mlCodeTable[n];
|
||||||
const BYTE offCode = offCodeTable[n]; /* 32b*/ /* 64b*/
|
const BYTE llCode = llCodeTable[n];
|
||||||
const U32 nbBits = (offCode-1) + (!offCode);
|
const U32 llBits = LL_bits[llCode];
|
||||||
const BYTE LLCode = llCodeTable[n];
|
const U32 mlBits = ML_bits[mlCode];
|
||||||
|
const U32 ofBits = (ofCode-1) + (!ofCode);
|
||||||
/* (7)*/ /* (7)*/
|
/* (7)*/ /* (7)*/
|
||||||
FSE_encodeSymbol(&blockStream, &stateOffsetBits, offCode); /* 25 */ /* 35 */
|
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 25 */ /* 35 */
|
||||||
FSE_encodeSymbol(&blockStream, &stateMatchLength, MLCode); /* 17 */ /* 17 */
|
FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode); /* 17 */ /* 17 */
|
||||||
FSE_encodeSymbol(&blockStream, &stateLitLength, LLCode); /* 16 */ /* 26 */
|
FSE_encodeSymbol(&blockStream, &stateLitLength, llCode); /* 16 */ /* 26 */
|
||||||
BIT_addBits(&blockStream, llTable[n], LL_bits[LLCode]);
|
if (ofBits + mlBits + llBits > 64 - 7 - 27)
|
||||||
BIT_addBits(&blockStream, mlTable[n], ML_bits[MLCode]);
|
BIT_flushBits(&blockStream);
|
||||||
BIT_addBits(&blockStream, offset, nbBits); /* 31 */ /* 61 */ /* 24 bits max in 32-bits mode */
|
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 */
|
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,
|
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,
|
const void* src, size_t srcSize,
|
||||||
U32 frame)
|
U32 frame)
|
||||||
{
|
{
|
||||||
@@ -2006,10 +2009,10 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
|
|||||||
|
|
||||||
if (frame && (zc->stage==0)) {
|
if (frame && (zc->stage==0)) {
|
||||||
hbSize = zc->hbSize;
|
hbSize = zc->hbSize;
|
||||||
if (dstSize <= hbSize) return ERROR(dstSize_tooSmall);
|
if (dstCapacity <= hbSize) return ERROR(dstSize_tooSmall);
|
||||||
zc->stage = 1;
|
zc->stage = 1;
|
||||||
memcpy(dst, zc->headerBuffer, hbSize);
|
memcpy(dst, zc->headerBuffer, hbSize);
|
||||||
dstSize -= hbSize;
|
dstCapacity -= hbSize;
|
||||||
dst = (char*)dst + hbSize;
|
dst = (char*)dst + hbSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2048,8 +2051,8 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
|
|||||||
|
|
||||||
zc->nextSrc = ip + srcSize;
|
zc->nextSrc = ip + srcSize;
|
||||||
{ size_t const cSize = frame ?
|
{ size_t const cSize = frame ?
|
||||||
ZSTD_compress_generic (zc, dst, dstSize, src, srcSize) :
|
ZSTD_compress_generic (zc, dst, dstCapacity, src, srcSize) :
|
||||||
ZSTD_compressBlock_internal (zc, dst, dstSize, src, srcSize);
|
ZSTD_compressBlock_internal (zc, dst, dstCapacity, src, srcSize);
|
||||||
if (ZSTD_isError(cSize)) return cSize;
|
if (ZSTD_isError(cSize)) return cSize;
|
||||||
return cSize + hbSize;
|
return cSize + hbSize;
|
||||||
}
|
}
|
||||||
@@ -2057,10 +2060,10 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
|
|||||||
|
|
||||||
|
|
||||||
size_t ZSTD_compressContinue (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)
|
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 */
|
/* Init */
|
||||||
{ size_t const errorCode = ZSTD_compressBegin_advanced(ctx, dict, dictSize, params);
|
{ 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) */
|
/* body (compression) */
|
||||||
{ size_t const oSize = ZSTD_compressContinue (ctx, op, dstCapacity, src, srcSize);
|
{ size_t const oSize = ZSTD_compressContinue (ctx, op, dstCapacity, src, srcSize);
|
||||||
if(ZSTD_isError(oSize)) return oSize;
|
if(ZSTD_isError(oSize)) return oSize;
|
||||||
op += oSize;
|
op += oSize;
|
||||||
dstCapacity -= oSize; }
|
dstCapacity -= oSize; }
|
||||||
|
|
||||||
/* Close frame */
|
/* Close frame */
|
||||||
{ size_t const oSize = ZSTD_compressEnd(ctx, op, dstCapacity);
|
{ size_t const oSize = ZSTD_compressEnd(ctx, op, dstCapacity);
|
||||||
if(ZSTD_isError(oSize)) return oSize;
|
if(ZSTD_isError(oSize)) return oSize;
|
||||||
op += oSize; }
|
op += oSize; }
|
||||||
|
|
||||||
return (op - ostart);
|
return (op - ostart);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -488,12 +488,12 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, U32 maxDuration, doub
|
|||||||
if (cSize > 3) {
|
if (cSize > 3) {
|
||||||
const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
|
const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */
|
||||||
const size_t tooSmallSize = cSize - missing;
|
const size_t tooSmallSize = cSize - missing;
|
||||||
static const U32 endMark = 0x4DC2B1A9;
|
const U32 endMark = 0x4DC2B1A9;
|
||||||
memcpy(dstBuffer+tooSmallSize, &endMark, 4);
|
memcpy(dstBuffer+tooSmallSize, &endMark, 4);
|
||||||
errorCode = ZSTD_compressCCtx(ctx, dstBuffer, tooSmallSize, sampleBuffer, sampleSize, cLevel);
|
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);
|
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);
|
{ 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 */
|
/* frame header decompression test */
|
||||||
|
|||||||
Reference in New Issue
Block a user