aboutsummaryrefslogtreecommitdiff
path: root/lib/lz4frame.c
diff options
context:
space:
mode:
authorYann Collet <yann.collet.73@gmail.com>2015-04-19 15:23:53 +0100
committerYann Collet <yann.collet.73@gmail.com>2015-04-19 15:23:53 +0100
commit409f816267b00e2307fabc59cc6ddffcc605a1ec (patch)
treeabc9b214e91ed4809f90ccfbf2872273d4b9921f /lib/lz4frame.c
parent47c304039954d73cea018fbd6b4eebc05877d3fc (diff)
downloadlz4-409f816267b00e2307fabc59cc6ddffcc605a1ec.tar.gz
Updated LZ4F_getFrameInfo() behavior, related to uncomplete frame header decoding attempts
Diffstat (limited to 'lib/lz4frame.c')
-rw-r--r--lib/lz4frame.c82
1 files changed, 45 insertions, 37 deletions
diff --git a/lib/lz4frame.c b/lib/lz4frame.c
index 6f53897e..7fc1314e 100644
--- a/lib/lz4frame.c
+++ b/lib/lz4frame.c
@@ -100,10 +100,11 @@ typedef unsigned long long U64;
#define LZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U
#define LZ4F_MAGICNUMBER 0x184D2204U
#define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U
-#define LZ4F_MAXHEADERFRAME_SIZE 15
#define LZ4F_BLOCKSIZEID_DEFAULT LZ4F_max64KB
-static const size_t minFHSize = 5;
+static const size_t minFHSize = 7;
+static const size_t maxFHSize = 15;
+static const size_t BHSize = 4;
static const U32 minHClevel = 3;
/**************************************
@@ -263,7 +264,7 @@ size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* prefere
prefs.frameInfo.blockSizeID = LZ4F_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);
prefs.autoFlush = 1;
- headerSize = 15; /* header size, including magic number and frame content size*/
+ headerSize = maxFHSize; /* header size, including magic number and frame content size*/
streamSize = LZ4F_compressBound(srcSize, &prefs);
return headerSize + streamSize;
@@ -398,7 +399,7 @@ size_t LZ4F_compressBegin(LZ4F_compressionContext_t compressionContext, void* ds
BYTE* headerStart;
size_t requiredBuffSize;
- if (dstMaxSize < LZ4F_MAXHEADERFRAME_SIZE) return (size_t)-LZ4F_ERROR_dstMaxSize_tooSmall;
+ if (dstMaxSize < maxFHSize) return (size_t)-LZ4F_ERROR_dstMaxSize_tooSmall;
if (cctxPtr->cStage != 0) return (size_t)-LZ4F_ERROR_GENERIC;
memset(&prefNull, 0, sizeof(prefNull));
if (preferencesPtr == NULL) preferencesPtr = &prefNull;
@@ -789,8 +790,9 @@ LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_decompressionContext_t LZ4F_
typedef enum { dstage_getHeader=0, dstage_storeHeader,
dstage_getCBlockSize, dstage_storeCBlockSize,
dstage_copyDirect,
- dstage_getCBlock, dstage_storeCBlock, dstage_decodeCBlock,
- dstage_decodeCBlock_intoDst, dstage_decodeCBlock_intoTmp, dstage_flushOut,
+ dstage_getCBlock, dstage_storeCBlock,
+ dstage_decodeCBlock, dstage_decodeCBlock_intoDst,
+ dstage_decodeCBlock_intoTmp, dstage_flushOut,
dstage_getSuffix, dstage_storeSuffix,
dstage_getSFrameSize, dstage_storeSFrameSize,
dstage_skipSkippable
@@ -802,6 +804,7 @@ typedef enum { dstage_getHeader=0, dstage_storeHeader,
or an error code (testable with LZ4F_isError())
output : set internal values of dctx, such as
dctxPtr->frameInfo and dctxPtr->dStage.
+ input : srcVoidPtr points at the **beginning of the frame**
*/
static size_t LZ4F_decodeHeader(LZ4F_dctx_internal_t* dctxPtr, const void* srcVoidPtr, size_t srcSize)
{
@@ -812,10 +815,10 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx_internal_t* dctxPtr, const void* srcVo
const BYTE* srcPtr = (const BYTE*)srcVoidPtr;
/* need to decode header to get frameInfo */
- if (srcSize < minFHSize) return (size_t)-LZ4F_ERROR_GENERIC; /* minimal header size */
+ if (srcSize < minFHSize) return (size_t)-LZ4F_ERROR_frameHeader_incomplete; /* minimal frame header size */
memset(&(dctxPtr->frameInfo), 0, sizeof(dctxPtr->frameInfo));
- /* skippable frames */
+ /* special case : skippable frames */
if ((LZ4F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START)
{
dctxPtr->frameInfo.frameType = LZ4F_skippableFrame;
@@ -846,10 +849,11 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx_internal_t* dctxPtr, const void* srcVo
contentChecksumFlag = (FLG>>2) & _1BIT;
/* Frame Header Size */
- frameHeaderSize = contentSizeFlag ? 15 : 7;
+ frameHeaderSize = contentSizeFlag ? maxFHSize : minFHSize;
if (srcSize < frameHeaderSize)
{
+ /* not enough input to fully decode frame header */
if (srcPtr != dctxPtr->header)
memcpy(dctxPtr->header, srcPtr, srcSize);
dctxPtr->tmpInSize = srcSize;
@@ -920,28 +924,32 @@ static size_t LZ4F_decodeHeader(LZ4F_dctx_internal_t* dctxPtr, const void* srcVo
* The function result is an hint of the better srcSize to use for next call to LZ4F_decompress,
* or an error code which can be tested using LZ4F_isError().
*/
-LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t decompressionContext, LZ4F_frameInfo_t* frameInfoPtr, const void* srcBuffer, size_t* srcSizePtr)
+LZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_decompressionContext_t dCtx, LZ4F_frameInfo_t* frameInfoPtr,
+ const void* srcBuffer, size_t* srcSizePtr)
{
- LZ4F_dctx_internal_t* dctxPtr = (LZ4F_dctx_internal_t*)decompressionContext;
+ LZ4F_dctx_internal_t* dctxPtr = (LZ4F_dctx_internal_t*)dCtx;
- if (dctxPtr->dStage == dstage_getHeader)
+ if (dctxPtr->dStage > dstage_storeHeader) /* note : requires dstage_* header related to be at beginning of enum */
{
- size_t frameHeaderSize = LZ4F_decodeHeader(dctxPtr, srcBuffer, *srcSizePtr);
- if (LZ4F_isError(frameHeaderSize)) return frameHeaderSize;
- *srcSizePtr = frameHeaderSize; /* nb Bytes consumed */
- *frameInfoPtr = dctxPtr->frameInfo; /* copy into */
- dctxPtr->srcExpect = NULL;
- return 4; /* nextSrcSizeHint : 4 == block header size */
+ size_t o=0, i=0;
+ /* frameInfo already decoded */
+ *srcSizePtr = 0;
+ *frameInfoPtr = dctxPtr->frameInfo;
+ return LZ4F_decompress(dCtx, NULL, &o, NULL, &i, NULL);
+ }
+ else
+ {
+ size_t o=0;
+ size_t nextSrcSize = LZ4F_decompress(dCtx, NULL, &o, srcBuffer, srcSizePtr, NULL);
+ if (dctxPtr->dStage <= dstage_storeHeader) /* note : requires dstage_* header related to be at beginning of enum */
+ return (size_t)-LZ4F_ERROR_frameHeader_incomplete;
+ *frameInfoPtr = dctxPtr->frameInfo;
+ return nextSrcSize;
}
-
- /* frameInfo already decoded */
- *srcSizePtr = 0;
- *frameInfoPtr = dctxPtr->frameInfo;
- return 0;
}
-/* redirector, with common prototype */
+/* trivial redirector, for common prototype */
static int LZ4F_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize)
{
(void)dictStart; (void)dictSize;
@@ -1071,7 +1079,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
case dstage_getHeader:
{
- if (srcEnd-srcPtr >= 7)
+ if ((size_t)(srcEnd-srcPtr) >= maxFHSize) /* enough to decode - shortcut */
{
LZ4F_errorCode_t errorCode = LZ4F_decodeHeader(dctxPtr, srcPtr, srcEnd-srcPtr);
if (LZ4F_isError(errorCode)) return errorCode;
@@ -1079,7 +1087,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
break;
}
dctxPtr->tmpInSize = 0;
- dctxPtr->tmpInTarget = 7;
+ dctxPtr->tmpInTarget = minFHSize; /* minimum to attempt decode */
dctxPtr->dStage = dstage_storeHeader;
}
@@ -1092,7 +1100,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
srcPtr += sizeToCopy;
if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget)
{
- nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + 4;
+ nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + BHSize; /* rest of header + nextBlockHeader */
doAnotherStage = 0; /* not enough src data, ask for some more */
break;
}
@@ -1105,10 +1113,10 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
case dstage_getCBlockSize:
{
- if ((srcEnd - srcPtr) >= 4)
+ if ((size_t)(srcEnd - srcPtr) >= BHSize)
{
selectedIn = srcPtr;
- srcPtr += 4;
+ srcPtr += BHSize;
}
else
{
@@ -1121,15 +1129,15 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
if (dctxPtr->dStage == dstage_storeCBlockSize)
case dstage_storeCBlockSize:
{
- size_t sizeToCopy = 4 - dctxPtr->tmpInSize;
+ size_t sizeToCopy = BHSize - dctxPtr->tmpInSize;
if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;
memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);
srcPtr += sizeToCopy;
dctxPtr->tmpInSize += sizeToCopy;
- if (dctxPtr->tmpInSize < 4) /* not enough input to get full cBlockSize; wait for more */
+ if (dctxPtr->tmpInSize < BHSize) /* not enough input to get full cBlockSize; wait for more */
{
- nextSrcSizeHint = 4 - dctxPtr->tmpInSize;
- doAnotherStage=0;
+ nextSrcSizeHint = BHSize - dctxPtr->tmpInSize;
+ doAnotherStage = 0;
break;
}
selectedIn = dctxPtr->tmpIn;
@@ -1153,7 +1161,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
dctxPtr->dStage = dstage_getCBlock;
if (dstPtr==dstEnd)
{
- nextSrcSizeHint = nextCBlockSize + 4;
+ nextSrcSizeHint = nextCBlockSize + BHSize;
doAnotherStage = 0;
}
break;
@@ -1180,7 +1188,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
break;
}
dctxPtr->tmpInTarget -= sizeToCopy; /* still need to copy more */
- nextSrcSizeHint = dctxPtr->tmpInTarget + 4;
+ nextSrcSizeHint = dctxPtr->tmpInTarget + BHSize;
doAnotherStage = 0;
break;
}
@@ -1208,7 +1216,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
srcPtr += sizeToCopy;
if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget) /* need more input */
{
- nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + 4;
+ nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + BHSize;
doAnotherStage=0;
break;
}
@@ -1311,7 +1319,7 @@ size_t LZ4F_decompress(LZ4F_decompressionContext_t decompressionContext,
dctxPtr->dStage = dstage_getCBlockSize;
break;
}
- nextSrcSizeHint = 4;
+ nextSrcSizeHint = BHSize;
doAnotherStage = 0; /* still some data to flush */
break;
}