contrib/lz4/lib/lz4frame.c in extlz4-0.2.4.3 vs contrib/lz4/lib/lz4frame.c in extlz4-0.2.5

- old
+ new

@@ -320,11 +320,11 @@ const void* srcBuffer, size_t srcSize, const LZ4F_CDict* cdict, const LZ4F_preferences_t* preferencesPtr) { LZ4F_cctx_t cctxI; - LZ4_stream_t lz4ctx; + LZ4_stream_t lz4ctx; /* pretty large on stack */ LZ4F_preferences_t prefs; LZ4F_compressOptions_t options; BYTE* const dstStart = (BYTE*) dstBuffer; BYTE* dstPtr = dstStart; BYTE* const dstEnd = dstStart + dstCapacity; @@ -502,19 +502,19 @@ memset(&prefNull, 0, sizeof(prefNull)); if (preferencesPtr == NULL) preferencesPtr = &prefNull; cctxPtr->prefs = *preferencesPtr; /* Ctx Management */ - { U32 const tableID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2; /* 0:nothing ; 1:LZ4 table ; 2:HC tables */ - if (cctxPtr->lz4CtxLevel < tableID) { + { U32 const ctxTypeID = (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2; /* 0:nothing ; 1:LZ4 table ; 2:HC tables */ + if (cctxPtr->lz4CtxLevel < ctxTypeID) { FREEMEM(cctxPtr->lz4CtxPtr); if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) cctxPtr->lz4CtxPtr = (void*)LZ4_createStream(); else cctxPtr->lz4CtxPtr = (void*)LZ4_createStreamHC(); if (cctxPtr->lz4CtxPtr == NULL) return err0r(LZ4F_ERROR_allocation_failed); - cctxPtr->lz4CtxLevel = tableID; + cctxPtr->lz4CtxLevel = ctxTypeID; } } /* Buffer Management */ if (cctxPtr->prefs.frameInfo.blockSizeID == 0) cctxPtr->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT; @@ -1251,33 +1251,36 @@ case dstage_storeFrameHeader: { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd - srcPtr)); memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy); dctx->tmpInSize += sizeToCopy; srcPtr += sizeToCopy; - if (dctx->tmpInSize < dctx->tmpInTarget) { - nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */ - doAnotherStage = 0; /* not enough src data, ask for some more */ - break; - } - { size_t const hSize = LZ4F_decodeHeader(dctx, dctx->header, dctx->tmpInTarget); /* will update dStage appropriately */ - if (LZ4F_isError(hSize)) return hSize; - } + } + if (dctx->tmpInSize < dctx->tmpInTarget) { + nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */ + doAnotherStage = 0; /* not enough src data, ask for some more */ break; } + { size_t const hSize = LZ4F_decodeHeader(dctx, dctx->header, dctx->tmpInTarget); /* will update dStage appropriately */ + if (LZ4F_isError(hSize)) return hSize; + } + break; case dstage_init: if (dctx->frameInfo.contentChecksumFlag) XXH32_reset(&(dctx->xxh), 0); /* internal buffers allocation */ - { size_t const bufferNeeded = dctx->maxBlockSize + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) * 128 KB) + 4 /* block checksum */; + { size_t const bufferNeeded = dctx->maxBlockSize + + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) * 128 KB); if (bufferNeeded > dctx->maxBufferSize) { /* tmp buffers too small */ dctx->maxBufferSize = 0; /* ensure allocation will be re-attempted on next entry*/ FREEMEM(dctx->tmpIn); - dctx->tmpIn = (BYTE*)ALLOCATOR(dctx->maxBlockSize); - if (dctx->tmpIn == NULL) return err0r(LZ4F_ERROR_allocation_failed); + dctx->tmpIn = (BYTE*)ALLOCATOR(dctx->maxBlockSize + 4 /* block checksum */); + if (dctx->tmpIn == NULL) + return err0r(LZ4F_ERROR_allocation_failed); FREEMEM(dctx->tmpOutBuffer); dctx->tmpOutBuffer= (BYTE*)ALLOCATOR(bufferNeeded); - if (dctx->tmpOutBuffer== NULL) return err0r(LZ4F_ERROR_allocation_failed); + if (dctx->tmpOutBuffer== NULL) + return err0r(LZ4F_ERROR_allocation_failed); dctx->maxBufferSize = bufferNeeded; } } dctx->tmpInSize = 0; dctx->tmpInTarget = 0; dctx->tmpOut = dctx->tmpOutBuffer; @@ -1297,22 +1300,24 @@ dctx->dStage = dstage_storeBlockHeader; } if (dctx->dStage == dstage_storeBlockHeader) /* can be skipped */ case dstage_storeBlockHeader: - { size_t sizeToCopy = BHSize - dctx->tmpInSize; - if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr; + { size_t const remainingInput = (size_t)(srcEnd - srcPtr); + size_t const wantedData = BHSize - dctx->tmpInSize; + size_t const sizeToCopy = MIN(wantedData, remainingInput); memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy); srcPtr += sizeToCopy; dctx->tmpInSize += sizeToCopy; + if (dctx->tmpInSize < BHSize) { /* not enough input for cBlockSize */ nextSrcSizeHint = BHSize - dctx->tmpInSize; doAnotherStage = 0; break; } selectedIn = dctx->tmpIn; - } + } /* if (dctx->dStage == dstage_storeBlockHeader) */ /* decode block header */ { size_t const nextCBlockSize = LZ4F_readLE32(selectedIn) & 0x7FFFFFFFU; size_t const crcSize = dctx->frameInfo.blockChecksumFlag * 4; if (nextCBlockSize==0) { /* frameEnd signal, no more block */ @@ -1399,11 +1404,11 @@ } } dctx->dStage = dstage_getBlockHeader; /* new block */ break; - case dstage_getCBlock: /* entry from dstage_decodeCBlockSize */ + case dstage_getCBlock: if ((size_t)(srcEnd-srcPtr) < dctx->tmpInTarget) { dctx->tmpInSize = 0; dctx->dStage = dstage_storeCBlock; break; } @@ -1412,11 +1417,13 @@ srcPtr += dctx->tmpInTarget; dctx->dStage = dstage_decodeCBlock; break; case dstage_storeCBlock: - { size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd-srcPtr)); + { size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize; + size_t const inputLeft = (size_t)(srcEnd-srcPtr); + size_t const sizeToCopy = MIN(wantedData, inputLeft); memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy); dctx->tmpInSize += sizeToCopy; srcPtr += sizeToCopy; if (dctx->tmpInSize < dctx->tmpInTarget) { /* need more input */ nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize; @@ -1463,11 +1470,10 @@ break; } case dstage_decodeCBlock_intoTmp: /* not enough place into dst : decode into tmpOut */ - /* ensure enough place for tmpOut */ if (dctx->frameInfo.blockMode == LZ4F_blockLinked) { if (dctx->dict == dctx->tmpOutBuffer) { if (dctx->dictSize > 128 KB) { memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - 64 KB, 64 KB); @@ -1516,43 +1522,41 @@ doAnotherStage = 0; /* still some data to flush */ break; } case dstage_getSuffix: - { size_t const suffixSize = dctx->frameInfo.contentChecksumFlag * 4; - if (dctx->frameRemainingSize) - return err0r(LZ4F_ERROR_frameSize_wrong); /* incorrect frame size decoded */ - if (suffixSize == 0) { /* frame completed */ - nextSrcSizeHint = 0; - LZ4F_resetDecompressionContext(dctx); - doAnotherStage = 0; - break; - } - if ((srcEnd - srcPtr) < 4) { /* not enough size for entire CRC */ - dctx->tmpInSize = 0; - dctx->dStage = dstage_storeSuffix; - } else { - selectedIn = srcPtr; - srcPtr += 4; - } + if (dctx->frameRemainingSize) + return err0r(LZ4F_ERROR_frameSize_wrong); /* incorrect frame size decoded */ + if (!dctx->frameInfo.contentChecksumFlag) { /* no checksum, frame is completed */ + nextSrcSizeHint = 0; + LZ4F_resetDecompressionContext(dctx); + doAnotherStage = 0; + break; } + if ((srcEnd - srcPtr) < 4) { /* not enough size for entire CRC */ + dctx->tmpInSize = 0; + dctx->dStage = dstage_storeSuffix; + } else { + selectedIn = srcPtr; + srcPtr += 4; + } if (dctx->dStage == dstage_storeSuffix) /* can be skipped */ case dstage_storeSuffix: - { - size_t sizeToCopy = 4 - dctx->tmpInSize; - if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr; + { size_t const remainingInput = (size_t)(srcEnd - srcPtr); + size_t const wantedData = 4 - dctx->tmpInSize; + size_t const sizeToCopy = MIN(wantedData, remainingInput); memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy); srcPtr += sizeToCopy; dctx->tmpInSize += sizeToCopy; if (dctx->tmpInSize < 4) { /* not enough input to read complete suffix */ nextSrcSizeHint = 4 - dctx->tmpInSize; doAnotherStage=0; break; } selectedIn = dctx->tmpIn; - } + } /* if (dctx->dStage == dstage_storeSuffix) */ /* case dstage_checkSuffix: */ /* no direct call, avoid scan-build warning */ { U32 const readCRC = LZ4F_readLE32(selectedIn); U32 const resultCRC = XXH32_digest(&(dctx->xxh)); if (readCRC != resultCRC) @@ -1587,11 +1591,11 @@ nextSrcSizeHint = dctx->tmpInTarget - dctx->tmpInSize; doAnotherStage = 0; break; } selectedIn = dctx->header + 4; - } + } /* if (dctx->dStage == dstage_storeSFrameSize) */ /* case dstage_decodeSFrameSize: */ /* no direct access */ { size_t const SFrameSize = LZ4F_readLE32(selectedIn); dctx->frameInfo.contentSize = SFrameSize; dctx->tmpInTarget = SFrameSize; @@ -1604,39 +1608,41 @@ srcPtr += skipSize; dctx->tmpInTarget -= skipSize; doAnotherStage = 0; nextSrcSizeHint = dctx->tmpInTarget; if (nextSrcSizeHint) break; /* still more to skip */ + /* frame fully skipped : prepare context for a new frame */ LZ4F_resetDecompressionContext(dctx); break; } } - } + } /* while (doAnotherStage) */ - /* preserve history within tmp if necessary */ - if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked) - && (dctx->dict != dctx->tmpOutBuffer) - && (dctx->dStage != dstage_getFrameHeader) - && (!decompressOptionsPtr->stableDst) - && ((unsigned)(dctx->dStage-1) < (unsigned)(dstage_getSuffix-1)) ) + /* preserve history within tmp whenever necessary */ + LZ4F_STATIC_ASSERT((unsigned)dstage_init == 2); + if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked) /* next block will use up to 64KB from previous ones */ + && (dctx->dict != dctx->tmpOutBuffer) /* dictionary is not already within tmp */ + && (!decompressOptionsPtr->stableDst) /* cannot rely on dst data to remain there for next call */ + && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) ) /* valid stages : [init ... getSuffix[ */ { if (dctx->dStage == dstage_flushOut) { - size_t preserveSize = dctx->tmpOut - dctx->tmpOutBuffer; + size_t const preserveSize = dctx->tmpOut - dctx->tmpOutBuffer; size_t copySize = 64 KB - dctx->tmpOutSize; const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart; if (dctx->tmpOutSize > 64 KB) copySize = 0; if (copySize > preserveSize) copySize = preserveSize; - memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize); + if (copySize > 0) + memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize); dctx->dict = dctx->tmpOutBuffer; dctx->dictSize = preserveSize + dctx->tmpOutStart; } else { - size_t newDictSize = dctx->dictSize; - const BYTE* oldDictEnd = dctx->dict + dctx->dictSize; - if ((newDictSize) > 64 KB) newDictSize = 64 KB; + const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize; + size_t const newDictSize = MIN(dctx->dictSize, 64 KB); - memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize); + if (newDictSize > 0) + memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize); dctx->dict = dctx->tmpOutBuffer; dctx->dictSize = newDictSize; dctx->tmpOut = dctx->tmpOutBuffer + newDictSize; }