summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Collet <yann.collet.73@gmail.com>2015-03-29 12:28:32 (GMT)
committerYann Collet <yann.collet.73@gmail.com>2015-03-29 12:28:32 (GMT)
commit8cb06d5b9922b16854b05081ce829c223a8129fd (patch)
tree90ce83e8949d054b336aaffc72f7463b2dfab3f8
parentd5da787c1bd92a22c87b6428321668548155995f (diff)
downloadlz4-8cb06d5b9922b16854b05081ce829c223a8129fd.zip
lz4-8cb06d5b9922b16854b05081ce829c223a8129fd.tar.gz
lz4-8cb06d5b9922b16854b05081ce829c223a8129fd.tar.bz2
lz4frame validates contentSize during decompression
-rw-r--r--lib/lz4frame.c16
-rw-r--r--lib/lz4frame.h52
-rw-r--r--programs/frametest.c4
3 files changed, 39 insertions, 33 deletions
diff --git a/lib/lz4frame.c b/lib/lz4frame.c
index 521be86..5683eee 100644
--- a/lib/lz4frame.c
+++ b/lib/lz4frame.c
@@ -636,8 +636,8 @@ size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* d
if ((cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize) /* necessarily blockLinked && lastBlockCompressed==fromTmpBuffer */
&& !(cctxPtr->prefs.autoFlush))
{
- LZ4F_localSaveDict(cctxPtr);
- cctxPtr->tmpIn = cctxPtr->tmpBuff + 64 KB;
+ int realDictSize = LZ4F_localSaveDict(cctxPtr);
+ cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
}
/* some input data left, necessarily < blockSize */
@@ -675,7 +675,7 @@ size_t LZ4F_flush(LZ4F_compressionContext_t compressionContext, void* dstBuffer,
if (cctxPtr->tmpInSize == 0) return 0; /* nothing to flush */
if (cctxPtr->cStage != 1) return (size_t)-ERROR_GENERIC;
- if (dstMaxSize < (cctxPtr->tmpInSize + 16)) return (size_t)-ERROR_dstMaxSize_tooSmall;
+ if (dstMaxSize < (cctxPtr->tmpInSize + 8)) return (size_t)-ERROR_dstMaxSize_tooSmall; /* +8 : block header(4) + block checksum(4) */
(void)compressOptionsPtr; /* not yet useful */
/* select compression function */
@@ -689,8 +689,8 @@ size_t LZ4F_flush(LZ4F_compressionContext_t compressionContext, void* dstBuffer,
/* keep tmpIn within limits */
if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) /* necessarily blockLinked */
{
- LZ4F_localSaveDict(cctxPtr);
- cctxPtr->tmpIn = cctxPtr->tmpBuff + 64 KB;
+ int realDictSize = LZ4F_localSaveDict(cctxPtr);
+ cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;
}
return dstPtr - dstStart;
@@ -1155,7 +1155,8 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
if ((size_t)(srcEnd-srcPtr) < sizeToCopy) sizeToCopy = srcEnd - srcPtr; /* not enough input to read full block */
if ((size_t)(dstEnd-dstPtr) < sizeToCopy) sizeToCopy = dstEnd - dstPtr;
memcpy(dstPtr, srcPtr, sizeToCopy);
- if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), srcPtr, (U32)sizeToCopy);
+ if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), srcPtr, sizeToCopy);
+ if (dctxPtr->frameInfo.contentSize) dctxPtr->frameInfo.contentSize -= sizeToCopy;
/* dictionary management */
if (dctxPtr->frameInfo.blockMode==blockLinked)
@@ -1228,6 +1229,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
decodedSize = decoder((const char*)selectedIn, (char*)dstPtr, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);
if (decodedSize < 0) return (size_t)-ERROR_GENERIC; /* decompression failed */
if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dstPtr, decodedSize);
+ if (dctxPtr->frameInfo.contentSize) dctxPtr->frameInfo.contentSize -= decodedSize;
/* dictionary management */
if (dctxPtr->frameInfo.blockMode==blockLinked)
@@ -1273,6 +1275,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
decodedSize = decoder((const char*)selectedIn, (char*)dctxPtr->tmpOut, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);
if (decodedSize < 0) return (size_t)-ERROR_decompressionFailed; /* decompression failed */
if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dctxPtr->tmpOut, decodedSize);
+ if (dctxPtr->frameInfo.contentSize) dctxPtr->frameInfo.contentSize -= decodedSize;
dctxPtr->tmpOutSize = decodedSize;
dctxPtr->tmpOutStart = 0;
dctxPtr->dStage = dstage_flushOut;
@@ -1306,6 +1309,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
case dstage_getSuffix:
{
size_t suffixSize = dctxPtr->frameInfo.contentChecksumFlag * 4;
+ if (dctxPtr->frameInfo.contentSize) return (size_t)-ERROR_frameSize_wrong; /* incorrect frame size decoded */
if (suffixSize == 0) /* frame completed */
{
nextSrcSizeHint = 0;
diff --git a/lib/lz4frame.h b/lib/lz4frame.h
index e29f84a..01a756a 100644
--- a/lib/lz4frame.h
+++ b/lib/lz4frame.h
@@ -91,7 +91,7 @@ size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* prefere
size_t LZ4F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
/* LZ4F_compressFrame()
- * Compress an entire srcBuffer into a valid LZ4 frame, as defined by specification v1.4.1.
+ * Compress an entire srcBuffer into a valid LZ4 frame, as defined by specification v1.5
* The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
* You can get the minimum value of dstMaxSize by using LZ4F_compressFrameBound()
* If this condition is not respected, LZ4F_compressFrame() will fail (result is an errorCode)
@@ -115,8 +115,8 @@ typedef struct {
/* Resource Management */
#define LZ4F_VERSION 100
-LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* LZ4F_compressionContextPtr, unsigned version);
-LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_compressionContext);
+LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_compressionContext_t* cctxPtr, unsigned version);
+LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t cctx);
/* LZ4F_createCompressionContext() :
* The first thing to do is to create a compressionContext object, which will be used in all compression operations.
* This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure.
@@ -129,7 +129,7 @@ LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_compressionContext_t LZ4F_comp
/* Compression */
-size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_preferences_t* preferencesPtr);
+size_t LZ4F_compressBegin(LZ4F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ4F_preferences_t* prefsPtr);
/* LZ4F_compressBegin() :
* will write the frame header into dstBuffer.
* dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is 15 bytes.
@@ -138,14 +138,14 @@ size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* ds
* or an error code (can be tested using LZ4F_isError())
*/
-size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
+size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* prefsPtr);
/* LZ4F_compressBound() :
* Provides the minimum size of Dst buffer given srcSize to handle worst case situations.
- * preferencesPtr is optional : you can provide NULL as argument, all preferences will then be set to default.
+ * prefsPtr is optional : you can provide NULL as argument, all preferences will then be set to default.
* Note that different preferences will produce in different results.
*/
-size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* compressOptionsPtr);
+size_t LZ4F_compressUpdate(LZ4F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ4F_compressOptions_t* cOptPtr);
/* LZ4F_compressUpdate()
* LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.
* The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
@@ -156,17 +156,18 @@ size_t LZ4F_compressUpdate(LZ4F_compressionContext_t compressionContext, void* d
* The function outputs an error code if it fails (can be tested using LZ4F_isError())
*/
-size_t LZ4F_flush(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr);
+size_t LZ4F_flush(LZ4F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* cOptPtr);
/* LZ4F_flush()
- * Should you need to create compressed data immediately, without waiting for a block to be filled,
- * you can call LZ4_flush(), which will immediately compress any remaining data buffered within compressionContext.
- * The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
+ * Should you need to generate compressed data immediately, without waiting for the current block to be filled,
+ * you can call LZ4_flush(), which will immediately compress any remaining data buffered within cctx.
+ * Note that dstMaxSize must be large enough to ensure the operation will be successful.
+ * LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
* The result of the function is the number of bytes written into dstBuffer
- * (it can be zero, this means there was no data left within compressionContext)
+ * (it can be zero, this means there was no data left within cctx)
* The function outputs an error code if it fails (can be tested using LZ4F_isError())
*/
-size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* compressOptionsPtr);
+size_t LZ4F_compressEnd(LZ4F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ4F_compressOptions_t* cOptPtr);
/* LZ4F_compressEnd()
* When you want to properly finish the compressed frame, just call LZ4F_compressEnd().
* It will flush whatever data remained within compressionContext (like LZ4_flush())
@@ -174,7 +175,7 @@ size_t LZ4F_compressEnd(LZ4F_compressionContext_t compressionContext, void* dstB
* The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))
* The function outputs an error code if it fails (can be tested using LZ4F_isError())
* The LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.
- * compressionContext can then be used again, starting with LZ4F_compressBegin().
+ * A successful call to LZ4F_compressEnd() makes cctx available again for future compression work.
*/
@@ -192,21 +193,21 @@ typedef struct {
/* Resource management */
-LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_decompressionContext_t* ctxPtr, unsigned version);
-LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_decompressionContext_t ctx);
+LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_decompressionContext_t* dctxPtr, unsigned version);
+LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_decompressionContext_t dctx);
/* LZ4F_createDecompressionContext() :
- * The first thing to do is to create a decompressionContext object, which will be used in all decompression operations.
+ * The first thing to do is to create an LZ4F_decompressionContext_t object, which will be used in all decompression operations.
* This is achieved using LZ4F_createDecompressionContext().
- * The version provided MUST be LZ4F_VERSION. It is intended to track potential version differences between different binaries.
+ * The version provided MUST be LZ4F_VERSION. It is intended to track potential breaking differences between different versions.
* The function will provide a pointer to a fully allocated and initialized LZ4F_decompressionContext_t object.
- * If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation.
- * Object can release its memory using LZ4F_freeDecompressionContext();
+ * The result is an errorCode, which can be tested using LZ4F_isError().
+ * dctx memory can be released using LZ4F_freeDecompressionContext();
*/
/* Decompression */
-size_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t ctx,
+size_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t dctx,
LZ4F_frameInfo_t* frameInfoPtr,
const void* srcBuffer, size_t* srcSizePtr);
/* LZ4F_getFrameInfo()
@@ -220,10 +221,10 @@ size_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t ctx,
* or an error code which can be tested using LZ4F_isError().
*/
-size_t LZ4F_decompress(LZ4F_decompressionContext_t ctx,
+size_t LZ4F_decompress(LZ4F_decompressionContext_t dctx,
void* dstBuffer, size_t* dstSizePtr,
const void* srcBuffer, size_t* srcSizePtr,
- const LZ4F_decompressOptions_t* optionsPtr);
+ const LZ4F_decompressOptions_t* dOptPtr);
/* LZ4F_decompress()
* Call this function repetitively to regenerate data compressed within srcBuffer.
* The function will attempt to decode *srcSizePtr bytes from srcBuffer, into dstBuffer of maximum size *dstSizePtr.
@@ -243,12 +244,13 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t ctx,
* Schematically, it's the size of the current (or remaining) compressed block + header of next block.
* Respecting the hint provides some boost to performance, since it does skip intermediate buffers.
* This is just a hint, you can always provide any srcSize you want.
- * When a frame is fully decoded, the function result will be 0. (no more data expected)
+ * When a frame is fully decoded, the function result will be 0 (no more data expected).
* If decompression failed, function result is an error code, which can be tested using LZ4F_isError().
+ *
+ * After a frame is fully decoded, dctx can be used again to decompress another frame.
*/
-
#if defined (__cplusplus)
}
#endif
diff --git a/programs/frametest.c b/programs/frametest.c
index b73cc4e..96d5acb 100644
--- a/programs/frametest.c
+++ b/programs/frametest.c
@@ -740,7 +740,7 @@ int main(int argc, char** argv)
int proba = FUZ_COMPRESSIBILITY_DEFAULT;
int result=0;
- // Check command line
+ /* Check command line */
programName = argv[0];
for(argNb=1; argNb<argc; argNb++)
{
@@ -830,7 +830,7 @@ int main(int argc, char** argv)
}
}
- // Get Seed
+ /* Get Seed */
printf("Starting lz4frame tester (%i-bits, %s)\n", (int)(sizeof(size_t)*8), LZ4_VERSION);
if (!seedset) seed = FUZ_GetMilliStart() % 10000;