diff --git a/lib/zstd_decompress.c b/lib/zstd_decompress.c index 2625f547..bfa398d8 100644 --- a/lib/zstd_decompress.c +++ b/lib/zstd_decompress.c @@ -94,13 +94,13 @@ typedef struct } blockProperties_t; -/* ******************************************************* +/*_******************************************************* * Memory operations **********************************************************/ static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); } -/* ************************************* +/*-************************************* * Error Management ***************************************/ unsigned ZSTD_versionNumber (void) { return ZSTD_VERSION_NUMBER; } @@ -118,7 +118,7 @@ ZSTD_ErrorCode ZSTD_getError(size_t code) { return ERR_getError(code); } const char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); } -/* ************************************************************* +/*-************************************************************* * Context management ***************************************************************/ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader, @@ -185,15 +185,15 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) } -/* ************************************************************* +/*-************************************************************* * Decompression section ***************************************************************/ /* Frame format description Frame Header - [ Block Header - Block ] - Frame End 1) Frame Header - - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_internal.h) - - 1 byte - Window Descriptor + - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_static.h) + - 1 byte - Frame Descriptor 2) Block Header - 3 bytes, starting with a 2-bits descriptor Uncompressed, Compressed, Frame End, unused @@ -203,7 +203,18 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) - 3 bytes, compatible with Block Header */ -/* Block format description + +/* Frame descriptor + + 1 byte, using : + bit 0-3 : windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN (see zstd_internal.h) + bit 4 : minmatch 4(0) or 3(1) + bit 5 : reserved (must be zero) + bit 6-7 : Frame content size : unknown, 1 byte, 2 bytes, 8 bytes +*/ + + +/* Compressed Block, format description Block = Literal Section - Sequences Section Prerequisite : size of (compressed) block, maximum size of regenerated data @@ -269,46 +280,63 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) TO DO */ +static const size_t ZSTD_fcs_fieldSize[4] = { 0, 1, 2, 8 }; -/** ZSTD_decodeFrameHeader_Part1() : -* decode the 1st part of the Frame Header, which tells Frame Header size. -* srcSize must be == ZSTD_frameHeaderSize_min. -* @return : the full size of the Frame Header */ -static size_t ZSTD_decodeFrameHeader_Part1(ZSTD_DCtx* zc, const void* src, size_t srcSize) +/** ZSTD_frameHeaderSize() : +* srcSize must be >= ZSTD_frameHeaderSize_min. +* @return : size of the Frame Header */ +static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize) { - U32 magicNumber; - if (srcSize != ZSTD_frameHeaderSize_min) - return ERROR(srcSize_wrong); - magicNumber = MEM_readLE32(src); - if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown); - zc->headerSize = ZSTD_frameHeaderSize_min; - return zc->headerSize; + U32 fcsId; + if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); + fcsId = (((const BYTE*)src)[4]) >> 6; + return ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId]; } +/** ZSTD_getFrameParams() : +* decode Frame Header, or provide expected `srcSize`. +* @return : 0, `fparamsPtr` is correctly filled, +* >0, not enough srcSize, provide expected `srcSize`, +* or an error code, which can be tested using ZSTD_isError() */ size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize) { - U32 magicNumber; - if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_max; + U32 magicNumber, fcsId; + const BYTE* ip = (const BYTE*)src; + BYTE frameDesc; + + if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_min; magicNumber = MEM_readLE32(src); if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown); + + { size_t fhsize = ZSTD_frameHeaderSize(src, srcSize); + if (srcSize < fhsize) return fhsize; } + memset(fparamsPtr, 0, sizeof(*fparamsPtr)); - fparamsPtr->windowLog = (((const BYTE*)src)[4] & 15) + ZSTD_WINDOWLOG_ABSOLUTEMIN; - fparamsPtr->mml = (((const BYTE*)src)[4] & 16) ? MINMATCH-1 : MINMATCH; - if ((((const BYTE*)src)[4] >> 5) != 0) return ERROR(frameParameter_unsupported); /* reserved 3 bits */ + frameDesc = ip[4]; + fparamsPtr->windowLog = (frameDesc & 0xF) + ZSTD_WINDOWLOG_ABSOLUTEMIN; + fparamsPtr->mml = (frameDesc & 0x10) ? MINMATCH-1 : MINMATCH; + if ((frameDesc & 0x20) != 0) return ERROR(frameParameter_unsupported); /* reserved 1 bit */ + fcsId = frameDesc >> 6; + switch(fcsId) + { + default: /* impossible */ + case 0 : fparamsPtr->frameContentSize = 0; break; + case 1 : fparamsPtr->frameContentSize = ip[5]; break; + case 2 : fparamsPtr->frameContentSize = MEM_readLE16(ip+5); break; + case 3 : fparamsPtr->frameContentSize = MEM_readLE64(ip+5); break; + } return 0; } -/** ZSTD_decodeFrameHeader_Part2() : -* decode the full Frame Header. + +/** ZSTD_decodeFrameHeader() : +* decode Frame Header. * srcSize must be the size provided by ZSTD_decodeFrameHeader_Part1(). * @return : 0, or an error code, which can be tested using ZSTD_isError() */ -static size_t ZSTD_decodeFrameHeader_Part2(ZSTD_DCtx* zc, const void* src, size_t srcSize) +static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* zc, const void* src, size_t srcSize) { - size_t result; - if (srcSize != zc->headerSize) - return ERROR(srcSize_wrong); - result = ZSTD_getFrameParams(&(zc->fParams), src, srcSize); + size_t result = ZSTD_getFrameParams(&(zc->fParams), src, srcSize); if ((MEM_32bits()) && (zc->fParams.windowLog > 25)) return ERROR(frameParameter_unsupportedBy32bits); return result; } @@ -901,7 +929,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, /* Frame Header */ { - size_t frameHeaderSize; + size_t frameHeaderSize, errorCode; if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1) { @@ -910,12 +938,12 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, return ZSTD_decompressLegacy(dst, maxDstSize, src, srcSize, magicNumber); } #endif - frameHeaderSize = ZSTD_decodeFrameHeader_Part1(dctx, src, ZSTD_frameHeaderSize_min); + frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min); if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize; if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); + errorCode = ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize); + if (ZSTD_isError(errorCode)) return errorCode; ip += frameHeaderSize; remainingSize -= frameHeaderSize; - frameHeaderSize = ZSTD_decodeFrameHeader_Part2(dctx, src, frameHeaderSize); - if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize; } /* Loop on each block */ @@ -1024,7 +1052,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, co { /* get frame header size */ if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */ - dctx->headerSize = ZSTD_decodeFrameHeader_Part1(dctx, src, ZSTD_frameHeaderSize_min); + dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min); if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize; memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_min); if (dctx->headerSize > ZSTD_frameHeaderSize_min) { @@ -1039,7 +1067,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, co /* get frame header */ size_t result; memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected); - result = ZSTD_decodeFrameHeader_Part2(dctx, dctx->headerBuffer, dctx->headerSize); + result = ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize); if (ZSTD_isError(result)) return result; dctx->expected = ZSTD_blockHeaderSize; dctx->stage = ZSTDds_decodeBlockHeader; diff --git a/lib/zstd_static.h b/lib/zstd_static.h index e3c0dfc4..f6eb8aa3 100644 --- a/lib/zstd_static.h +++ b/lib/zstd_static.h @@ -165,7 +165,7 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci You can then reuse ZSTD_CCtx to compress some new frame. */ -typedef struct { U64 frameSize; U32 windowLog; U32 mml; } ZSTD_frameParams; +typedef struct { U64 frameContentSize; U32 windowLog; U32 mml; } ZSTD_frameParams; #define ZSTD_FRAMEHEADERSIZE_MAX 13 /* for static allocation */ static const size_t ZSTD_frameHeaderSize_min = 5;