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;
}