From: Yann Collet Date: Wed, 23 Mar 2016 21:31:57 +0000 (+0100) Subject: fixed write overflow found by fuzzer X-Git-Tag: v0.6.0^2~17^2~28^2~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7cbe79ab25cb3381fb2e249de8d6422d8b62565f;p=thirdparty%2Fzstd.git fixed write overflow found by fuzzer --- diff --git a/lib/zstd_compress.c b/lib/zstd_compress.c index 121a9fcd1..8d2eff0b3 100644 --- a/lib/zstd_compress.c +++ b/lib/zstd_compress.c @@ -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 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 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); } diff --git a/programs/fuzzer.c b/programs/fuzzer.c index d53586c17..29bf4861d 100644 --- a/programs/fuzzer.c +++ b/programs/fuzzer.c @@ -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 */