summaryrefslogtreecommitdiff
path: root/lib/lz4frame.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lz4frame.c')
-rw-r--r--lib/lz4frame.c52
1 files changed, 31 insertions, 21 deletions
diff --git a/lib/lz4frame.c b/lib/lz4frame.c
index 890fc96..bfdef5d 100644
--- a/lib/lz4frame.c
+++ b/lib/lz4frame.c
@@ -533,7 +533,7 @@ void LZ4F_freeCDict(LZ4F_CDict* cdict)
* If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation.
* Object can release its memory using LZ4F_freeCompressionContext();
*/
-LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, unsigned version)
+LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** LZ4F_compressionContextPtr, unsigned version)
{
LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)ALLOC_AND_ZERO(sizeof(LZ4F_cctx_t));
if (cctxPtr==NULL) return err0r(LZ4F_ERROR_allocation_failed);
@@ -541,20 +541,18 @@ LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_c
cctxPtr->version = version;
cctxPtr->cStage = 0; /* Next stage : init stream */
- *LZ4F_compressionContextPtr = (LZ4F_compressionContext_t)cctxPtr;
+ *LZ4F_compressionContextPtr = cctxPtr;
return LZ4F_OK_NoError;
}
-LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_compressionContext)
+LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctxPtr)
{
- LZ4F_cctx_t* const cctxPtr = (LZ4F_cctx_t*)LZ4F_compressionContext;
-
if (cctxPtr != NULL) { /* support free on NULL */
- FREEMEM(cctxPtr->lz4CtxPtr); /* works because LZ4_streamHC_t and LZ4_stream_t are simple POD types */
+ FREEMEM(cctxPtr->lz4CtxPtr); /* note: LZ4_streamHC_t and LZ4_stream_t are simple POD types */
FREEMEM(cctxPtr->tmpBuff);
- FREEMEM(LZ4F_compressionContext);
+ FREEMEM(cctxPtr);
}
return LZ4F_OK_NoError;
@@ -1286,15 +1284,20 @@ LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx,
/* LZ4F_updateDict() :
- * only used for LZ4F_blockLinked mode */
+ * only used for LZ4F_blockLinked mode
+ * Condition : dstPtr != NULL
+ */
static void LZ4F_updateDict(LZ4F_dctx* dctx,
const BYTE* dstPtr, size_t dstSize, const BYTE* dstBufferStart,
unsigned withinTmp)
{
- if (dctx->dictSize==0)
- dctx->dict = (const BYTE*)dstPtr; /* priority to dictionary continuity */
+ assert(dstPtr != NULL);
+ if (dctx->dictSize==0) {
+ dctx->dict = (const BYTE*)dstPtr; /* priority to prefix mode */
+ }
+ assert(dctx->dict != NULL);
- if (dctx->dict + dctx->dictSize == dstPtr) { /* dictionary continuity, directly within dstBuffer */
+ if (dctx->dict + dctx->dictSize == dstPtr) { /* prefix mode, everything within dstBuffer */
dctx->dictSize += dstSize;
return;
}
@@ -1308,9 +1311,10 @@ static void LZ4F_updateDict(LZ4F_dctx* dctx,
assert(dstSize < 64 KB); /* if dstSize >= 64 KB, dictionary would be set into dstBuffer directly */
- /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOut */
+ /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOutBuffer */
+ assert(dctx->tmpOutBuffer != NULL);
- if ((withinTmp) && (dctx->dict == dctx->tmpOutBuffer)) { /* continue history within tmpOutBuffer */
+ if (withinTmp && (dctx->dict == dctx->tmpOutBuffer)) { /* continue history within tmpOutBuffer */
/* withinTmp expectation : content of [dstPtr,dstSize] is same as [dict+dictSize,dstSize], so we just extend it */
assert(dctx->dict + dctx->dictSize == dctx->tmpOut + dctx->tmpOutStart);
dctx->dictSize += dstSize;
@@ -1382,13 +1386,14 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
const BYTE* const srcEnd = srcStart + *srcSizePtr;
const BYTE* srcPtr = srcStart;
BYTE* const dstStart = (BYTE*)dstBuffer;
- BYTE* const dstEnd = dstStart + *dstSizePtr;
+ BYTE* const dstEnd = dstStart ? dstStart + *dstSizePtr : NULL;
BYTE* dstPtr = dstStart;
const BYTE* selectedIn = NULL;
unsigned doAnotherStage = 1;
size_t nextSrcSizeHint = 1;
+ if (dstBuffer == NULL) assert(*dstSizePtr == 0);
MEM_INIT(&optionsNull, 0, sizeof(optionsNull));
if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;
*srcSizePtr = 0;
@@ -1516,6 +1521,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
}
case dstage_copyDirect: /* uncompressed block */
+ if (dstPtr==NULL) { doAnotherStage = 0; break; }
{ size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr));
size_t const sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);
memcpy(dstPtr, srcPtr, sizeToCopy);
@@ -1528,8 +1534,9 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
dctx->frameRemainingSize -= sizeToCopy;
/* history management (linked blocks only)*/
- if (dctx->frameInfo.blockMode == LZ4F_blockLinked)
+ if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {
LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0);
+ }
srcPtr += sizeToCopy;
dstPtr += sizeToCopy;
@@ -1590,7 +1597,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
selectedIn = srcPtr;
srcPtr += dctx->tmpInTarget;
- if (0) /* jump over next block */
+ if (0) /* always jump over next block */
case dstage_storeCBlock:
{ size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize;
size_t const inputLeft = (size_t)(srcEnd-srcPtr);
@@ -1627,6 +1634,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
const char* dict = (const char*)dctx->dict;
size_t dictSize = dctx->dictSize;
int decodedSize;
+ assert(dstPtr != NULL);
if (dict && dictSize > 1 GB) {
/* the dictSize param is an int, avoid truncation / sign issues */
dict += dictSize - 64 KB;
@@ -1644,8 +1652,9 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
dctx->frameRemainingSize -= (size_t)decodedSize;
/* dictionary management */
- if (dctx->frameInfo.blockMode==LZ4F_blockLinked)
+ if (dctx->frameInfo.blockMode==LZ4F_blockLinked) {
LZ4F_updateDict(dctx, dstPtr, (size_t)decodedSize, dstStart, 0);
+ }
dstPtr += decodedSize;
dctx->dStage = dstage_getBlockHeader;
@@ -1692,6 +1701,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
/* fall-through */
case dstage_flushOut: /* flush decoded data from tmpOut to dstBuffer */
+ if (dstPtr == NULL) { doAnotherStage = 0; nextSrcSizeHint = BHSize; break; }
{ size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr));
memcpy(dstPtr, dctx->tmpOut + dctx->tmpOutStart, sizeToCopy);
@@ -1814,6 +1824,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
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 */
+ && (dctx->dict != NULL) /* dictionary exists */
&& (!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[ */
{
@@ -1823,9 +1834,9 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;
if (dctx->tmpOutSize > 64 KB) copySize = 0;
if (copySize > preserveSize) copySize = preserveSize;
+ assert(dctx->tmpOutBuffer != NULL);
- if (copySize > 0)
- memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
+ memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);
dctx->dict = dctx->tmpOutBuffer;
dctx->dictSize = preserveSize + dctx->tmpOutStart;
@@ -1833,8 +1844,7 @@ size_t LZ4F_decompress(LZ4F_dctx* dctx,
const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize;
size_t const newDictSize = MIN(dctx->dictSize, 64 KB);
- if (newDictSize > 0)
- memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
+ memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);
dctx->dict = dctx->tmpOutBuffer;
dctx->dictSize = newDictSize;