diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 9974dbe3b..a981af0a1 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -433,17 +433,6 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he return 0; } -/** - * Contains the compressed frame size and an upper-bound for the decompressed frame size. - * Note: before using `compressedSize` you must check for errors using ZSTD_isError(). - * similarly, before using `decompressedBound`, you must check for errors using: - * `decompressedBound` != ZSTD_CONTENTSIZE_ERROR - */ -typedef struct { - size_t compressedSize; - unsigned long long decompressedBound; -} ZSTD_frameSizeInfo; - static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret) { ZSTD_frameSizeInfo frameSizeInfo; @@ -458,8 +447,9 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo)); #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) - if (ZSTD_isLegacy(src, srcSize)) - return ZSTD_errorFrameSizeInfo(ZSTD_findFrameCompressedSizeLegacy(src, srcSize)); + if (ZSTD_isLegacy(src, srcSize)) { + return ZSTD_findFrameSizeInfoLegacy(src, srcSize); + } #endif if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE) diff --git a/lib/legacy/zstd_legacy.h b/lib/legacy/zstd_legacy.h index 5893cb965..306a87399 100644 --- a/lib/legacy/zstd_legacy.h +++ b/lib/legacy/zstd_legacy.h @@ -178,43 +178,73 @@ MEM_STATIC size_t ZSTD_decompressLegacy( } } -MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, - size_t compressedSize) +MEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret) { - U32 const version = ZSTD_isLegacy(src, compressedSize); + *cSize = ret; + *dBound = ZSTD_CONTENTSIZE_ERROR; +} + +MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size_t srcSize) +{ + ZSTD_frameSizeInfo frameSizeInfo; + memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo)); + U32 const version = ZSTD_isLegacy(src, srcSize); switch(version) { #if (ZSTD_LEGACY_SUPPORT <= 1) case 1 : - return ZSTDv01_findFrameCompressedSize(src, compressedSize); + ZSTDv01_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, &frameSizeInfo.decompressedBound); + break; #endif #if (ZSTD_LEGACY_SUPPORT <= 2) case 2 : - return ZSTDv02_findFrameCompressedSize(src, compressedSize); + ZSTDv02_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, &frameSizeInfo.decompressedBound); + break; #endif #if (ZSTD_LEGACY_SUPPORT <= 3) case 3 : - return ZSTDv03_findFrameCompressedSize(src, compressedSize); + ZSTDv03_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, &frameSizeInfo.decompressedBound); + break; #endif #if (ZSTD_LEGACY_SUPPORT <= 4) case 4 : - return ZSTDv04_findFrameCompressedSize(src, compressedSize); + ZSTDv04_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, &frameSizeInfo.decompressedBound); + break; #endif #if (ZSTD_LEGACY_SUPPORT <= 5) case 5 : - return ZSTDv05_findFrameCompressedSize(src, compressedSize); + ZSTDv05_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, &frameSizeInfo.decompressedBound); + break; #endif #if (ZSTD_LEGACY_SUPPORT <= 6) case 6 : - return ZSTDv06_findFrameCompressedSize(src, compressedSize); + ZSTDv06_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, &frameSizeInfo.decompressedBound); + break; #endif #if (ZSTD_LEGACY_SUPPORT <= 7) case 7 : - return ZSTDv07_findFrameCompressedSize(src, compressedSize); + ZSTDv07_findFrameSizeInfoLegacy(src, srcSize, + &frameSizeInfo.compressedSize, &frameSizeInfo.decompressedBound); + break; #endif default : - return ERROR(prefix_unknown); + ZSTD_errorFrameSizeInfoLegacy(&frameSizeInfo.compressedSize, + &frameSizeInfo.decompressedBound, ERROR(prefix_unknown)); + break; } + return frameSizeInfo; +} + +MEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, size_t srcSize) +{ + ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize); + return frameSizeInfo.compressedSize; } MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version) diff --git a/lib/legacy/zstd_v01.c b/lib/legacy/zstd_v01.c index c007e7ceb..1d2d34f18 100644 --- a/lib/legacy/zstd_v01.c +++ b/lib/legacy/zstd_v01.c @@ -1336,6 +1336,9 @@ static const U32 ZSTD_magicNumber = 0xFD2FB51E; /* 3rd version : seqNb header #define LITERAL_NOENTROPY 63 #define COMMAND_NOENTROPY 7 /* to remove */ +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) + static const size_t ZSTD_blockHeaderSize = 3; static const size_t ZSTD_frameHeaderSize = 4; @@ -1999,36 +2002,58 @@ size_t ZSTDv01_decompress(void* dst, size_t maxDstSize, const void* src, size_t return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize); } -size_t ZSTDv01_findFrameCompressedSize(const void* src, size_t srcSize) +static void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret) +{ + *cSize = ret; + *dBound = ZSTD_CONTENTSIZE_ERROR; +} + +void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound) { const BYTE* ip = (const BYTE*)src; size_t remainingSize = srcSize; + size_t nbBlocks = 0; U32 magicNumber; blockProperties_t blockProperties; /* Frame Header */ - if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); + if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } magicNumber = ZSTD_readBE32(src); - if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown); + if (magicNumber != ZSTD_magicNumber) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown)); + return; + } ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize; /* Loop on each block */ while (1) { size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties); - if (ZSTDv01_isError(blockSize)) return blockSize; + if (ZSTDv01_isError(blockSize)) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, blockSize); + return; + } ip += ZSTD_blockHeaderSize; remainingSize -= ZSTD_blockHeaderSize; - if (blockSize > remainingSize) return ERROR(srcSize_wrong); + if (blockSize > remainingSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } if (blockSize == 0) break; /* bt_end */ ip += blockSize; remainingSize -= blockSize; + nbBlocks++; } - return ip - (const BYTE*)src; + *cSize = ip - (const BYTE*)src; + *dBound = nbBlocks * BLOCKSIZE; } /******************************* diff --git a/lib/legacy/zstd_v01.h b/lib/legacy/zstd_v01.h index 42f0897c7..c56a2f0c7 100644 --- a/lib/legacy/zstd_v01.h +++ b/lib/legacy/zstd_v01.h @@ -35,13 +35,14 @@ ZSTDv01_decompress() : decompress ZSTD frames compliant with v0.1.x format size_t ZSTDv01_decompress( void* dst, size_t maxOriginalSize, const void* src, size_t compressedSize); -/** -ZSTDv01_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.1.x format - compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' - return : the number of bytes that would be read to decompress this frame - or an errorCode if it fails (which can be tested using ZSTDv01_isError()) -*/ -size_t ZSTDv01_findFrameCompressedSize(const void* src, size_t compressedSize); + /** + ZSTDv01_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.1.x format + compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + return : the number of bytes that would be read to decompress this frame + or an errorCode if it fails (which can be tested using ZSTDv01_isError()) + */ +void ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); /** ZSTDv01_isError() : tells if the result of ZSTDv01_decompress() is an error diff --git a/lib/legacy/zstd_v02.c b/lib/legacy/zstd_v02.c index c09ef8cff..06496101c 100644 --- a/lib/legacy/zstd_v02.c +++ b/lib/legacy/zstd_v02.c @@ -2728,6 +2728,9 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_ #define LITERAL_NOENTROPY 63 #define COMMAND_NOENTROPY 7 /* to remove */ +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) + static const size_t ZSTD_blockHeaderSize = 3; static const size_t ZSTD_frameHeaderSize = 4; @@ -3312,37 +3315,58 @@ static size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, siz return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize); } -static size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) +MEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret) { + *cSize = ret; + *dBound = ZSTD_CONTENTSIZE_ERROR; +} +void ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound) +{ const BYTE* ip = (const BYTE*)src; size_t remainingSize = srcSize; + size_t nbBlocks = 0; U32 magicNumber; blockProperties_t blockProperties; /* Frame Header */ - if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); + if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } magicNumber = MEM_readLE32(src); - if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown); + if (magicNumber != ZSTD_magicNumber) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown)); + return; + } ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize; /* Loop on each block */ while (1) { size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); - if (ZSTD_isError(cBlockSize)) return cBlockSize; + if (ZSTD_isError(cBlockSize)) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize); + return; + } ip += ZSTD_blockHeaderSize; remainingSize -= ZSTD_blockHeaderSize; - if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); + if (cBlockSize > remainingSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } if (cBlockSize == 0) break; /* bt_end */ ip += cBlockSize; remainingSize -= cBlockSize; + nbBlocks++; } - return ip - (const BYTE*)src; + *cSize = ip - (const BYTE*)src; + *dBound = nbBlocks * BLOCKSIZE; } /******************************* @@ -3458,11 +3482,6 @@ size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize, return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize); } -size_t ZSTDv02_findFrameCompressedSize(const void *src, size_t compressedSize) -{ - return ZSTD_findFrameCompressedSize(src, compressedSize); -} - ZSTDv02_Dctx* ZSTDv02_createDCtx(void) { return (ZSTDv02_Dctx*)ZSTD_createDCtx(); diff --git a/lib/legacy/zstd_v02.h b/lib/legacy/zstd_v02.h index 0dde7a637..5f7cba524 100644 --- a/lib/legacy/zstd_v02.h +++ b/lib/legacy/zstd_v02.h @@ -35,13 +35,14 @@ ZSTDv02_decompress() : decompress ZSTD frames compliant with v0.2.x format size_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize, const void* src, size_t compressedSize); -/** -ZSTDv02_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.2.x format - compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' - return : the number of bytes that would be read to decompress this frame - or an errorCode if it fails (which can be tested using ZSTDv02_isError()) -*/ -size_t ZSTDv02_findFrameCompressedSize(const void* src, size_t compressedSize); + /** + ZSTDv02_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.2.x format + compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + return : the number of bytes that would be read to decompress this frame + or an errorCode if it fails (which can be tested using ZSTDv02_isError()) + */ +void ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); /** ZSTDv02_isError() : tells if the result of ZSTDv02_decompress() is an error diff --git a/lib/legacy/zstd_v03.c b/lib/legacy/zstd_v03.c index 0c4cdf688..27c1b67bb 100644 --- a/lib/legacy/zstd_v03.c +++ b/lib/legacy/zstd_v03.c @@ -2369,6 +2369,9 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_ #define LITERAL_NOENTROPY 63 #define COMMAND_NOENTROPY 7 /* to remove */ +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) + static const size_t ZSTD_blockHeaderSize = 3; static const size_t ZSTD_frameHeaderSize = 4; @@ -2953,36 +2956,58 @@ static size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, siz return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize); } -static size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize) +MEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret) +{ + *cSize = ret; + *dBound = ZSTD_CONTENTSIZE_ERROR; +} + +void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound) { const BYTE* ip = (const BYTE*)src; size_t remainingSize = srcSize; + size_t nbBlocks = 0; U32 magicNumber; blockProperties_t blockProperties; /* Frame Header */ - if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); + if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } magicNumber = MEM_readLE32(src); - if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown); + if (magicNumber != ZSTD_magicNumber) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown)); + return; + } ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize; /* Loop on each block */ while (1) { size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); - if (ZSTD_isError(cBlockSize)) return cBlockSize; + if (ZSTD_isError(cBlockSize)) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize); + return; + } ip += ZSTD_blockHeaderSize; remainingSize -= ZSTD_blockHeaderSize; - if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); + if (cBlockSize > remainingSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } if (cBlockSize == 0) break; /* bt_end */ ip += cBlockSize; remainingSize -= cBlockSize; + nbBlocks++; } - return ip - (const BYTE*)src; + *cSize = ip - (const BYTE*)src; + *dBound = nbBlocks * BLOCKSIZE; } @@ -3099,11 +3124,6 @@ size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize, return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize); } -size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t srcSize) -{ - return ZSTD_findFrameCompressedSize(src, srcSize); -} - ZSTDv03_Dctx* ZSTDv03_createDCtx(void) { return (ZSTDv03_Dctx*)ZSTD_createDCtx(); diff --git a/lib/legacy/zstd_v03.h b/lib/legacy/zstd_v03.h index b4449e299..36fc61190 100644 --- a/lib/legacy/zstd_v03.h +++ b/lib/legacy/zstd_v03.h @@ -35,13 +35,14 @@ ZSTDv03_decompress() : decompress ZSTD frames compliant with v0.3.x format size_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize, const void* src, size_t compressedSize); -/** -ZSTDv03_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.3.x format - compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' - return : the number of bytes that would be read to decompress this frame - or an errorCode if it fails (which can be tested using ZSTDv03_isError()) -*/ -size_t ZSTDv03_findFrameCompressedSize(const void* src, size_t compressedSize); + /** + ZSTDv03_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.3.x format + compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + return : the number of bytes that would be read to decompress this frame + or an errorCode if it fails (which can be tested using ZSTDv03_isError()) + */ + void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); /** ZSTDv03_isError() : tells if the result of ZSTDv03_decompress() is an error diff --git a/lib/legacy/zstd_v04.c b/lib/legacy/zstd_v04.c index d7522025e..81994d1f3 100644 --- a/lib/legacy/zstd_v04.c +++ b/lib/legacy/zstd_v04.c @@ -373,6 +373,9 @@ static const size_t ZSTD_frameHeaderSize_min = 5; #define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/) #define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE) +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) + typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t; @@ -3119,34 +3122,56 @@ static size_t ZSTD_decompress_usingDict(ZSTD_DCtx* ctx, return op-ostart; } -static size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize) +MEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret) +{ + *cSize = ret; + *dBound = ZSTD_CONTENTSIZE_ERROR; +} + +void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound) { const BYTE* ip = (const BYTE*)src; size_t remainingSize = srcSize; + size_t nbBlocks = 0; blockProperties_t blockProperties; /* Frame Header */ - if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); - if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown); + if (srcSize < ZSTD_frameHeaderSize_min) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } + if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown)); + return; + } ip += ZSTD_frameHeaderSize_min; remainingSize -= ZSTD_frameHeaderSize_min; /* Loop on each block */ while (1) { size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties); - if (ZSTD_isError(cBlockSize)) return cBlockSize; + if (ZSTD_isError(cBlockSize)) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize); + return; + } ip += ZSTD_blockHeaderSize; remainingSize -= ZSTD_blockHeaderSize; - if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); + if (cBlockSize > remainingSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } if (cBlockSize == 0) break; /* bt_end */ ip += cBlockSize; remainingSize -= cBlockSize; + nbBlocks++; } - return ip - (const BYTE*)src; + *cSize = ip - (const BYTE*)src; + *dBound = nbBlocks * BLOCKSIZE; } /* ****************************** @@ -3578,11 +3603,6 @@ size_t ZSTDv04_decompress(void* dst, size_t maxDstSize, const void* src, size_t #endif } -size_t ZSTDv04_findFrameCompressedSize(const void* src, size_t srcSize) -{ - return ZSTD_findFrameCompressedSize(src, srcSize); -} - size_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx) { return ZSTD_resetDCtx(dctx); } size_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx) diff --git a/lib/legacy/zstd_v04.h b/lib/legacy/zstd_v04.h index 6391631fc..1da32c6c9 100644 --- a/lib/legacy/zstd_v04.h +++ b/lib/legacy/zstd_v04.h @@ -35,13 +35,14 @@ ZSTDv04_decompress() : decompress ZSTD frames compliant with v0.4.x format size_t ZSTDv04_decompress( void* dst, size_t maxOriginalSize, const void* src, size_t compressedSize); -/** -ZSTDv04_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.4.x format - compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' - return : the number of bytes that would be read to decompress this frame - or an errorCode if it fails (which can be tested using ZSTDv04_isError()) -*/ -size_t ZSTDv04_findFrameCompressedSize(const void* src, size_t compressedSize); + /** + ZSTDv04_getFrameSrcSize() : get the source length of a ZSTD frame compliant with v0.4.x format + compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + return : the number of bytes that would be read to decompress this frame + or an errorCode if it fails (which can be tested using ZSTDv04_isError()) + */ + void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); /** ZSTDv04_isError() : tells if the result of ZSTDv04_decompress() is an error diff --git a/lib/legacy/zstd_v05.c b/lib/legacy/zstd_v05.c index 96bffc44a..ff1095ca9 100644 --- a/lib/legacy/zstd_v05.c +++ b/lib/legacy/zstd_v05.c @@ -491,6 +491,9 @@ static const size_t ZSTDv05_frameHeaderSize_min = 5; #define WILDCOPY_OVERLENGTH 8 +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) + typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t; @@ -3508,34 +3511,56 @@ size_t ZSTDv05_decompress(void* dst, size_t maxDstSize, const void* src, size_t #endif } -size_t ZSTDv05_findFrameCompressedSize(const void *src, size_t srcSize) +MEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret) +{ + *cSize = ret; + *dBound = ZSTD_CONTENTSIZE_ERROR; +} + +void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound) { const BYTE* ip = (const BYTE*)src; size_t remainingSize = srcSize; + size_t nbBlocks = 0; blockProperties_t blockProperties; /* Frame Header */ - if (srcSize < ZSTDv05_frameHeaderSize_min) return ERROR(srcSize_wrong); - if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown); + if (srcSize < ZSTDv05_frameHeaderSize_min) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } + if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown)); + return; + } ip += ZSTDv05_frameHeaderSize_min; remainingSize -= ZSTDv05_frameHeaderSize_min; /* Loop on each block */ while (1) { size_t cBlockSize = ZSTDv05_getcBlockSize(ip, remainingSize, &blockProperties); - if (ZSTDv05_isError(cBlockSize)) return cBlockSize; + if (ZSTDv05_isError(cBlockSize)) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize); + return; + } ip += ZSTDv05_blockHeaderSize; remainingSize -= ZSTDv05_blockHeaderSize; - if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); + if (cBlockSize > remainingSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } if (cBlockSize == 0) break; /* bt_end */ ip += cBlockSize; remainingSize -= cBlockSize; + nbBlocks++; } - return ip - (const BYTE*)src; + *cSize = ip - (const BYTE*)src; + *dBound = nbBlocks * BLOCKSIZE; } /* ****************************** diff --git a/lib/legacy/zstd_v05.h b/lib/legacy/zstd_v05.h index b68fd578e..3798c5092 100644 --- a/lib/legacy/zstd_v05.h +++ b/lib/legacy/zstd_v05.h @@ -33,13 +33,14 @@ extern "C" { size_t ZSTDv05_decompress( void* dst, size_t dstCapacity, const void* src, size_t compressedSize); -/** -ZSTDv05_getFrameSrcSize() : get the source length of a ZSTD frame - compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' - return : the number of bytes that would be read to decompress this frame - or an errorCode if it fails (which can be tested using ZSTDv05_isError()) -*/ -size_t ZSTDv05_findFrameCompressedSize(const void* src, size_t compressedSize); + /** + ZSTDv05_getFrameSrcSize() : get the source length of a ZSTD frame + compressedSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src' + return : the number of bytes that would be read to decompress this frame + or an errorCode if it fails (which can be tested using ZSTDv05_isError()) + */ +void ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); /* ************************************* * Helper functions diff --git a/lib/legacy/zstd_v06.c b/lib/legacy/zstd_v06.c index 60d8d6fd9..33a2b7daf 100644 --- a/lib/legacy/zstd_v06.c +++ b/lib/legacy/zstd_v06.c @@ -506,6 +506,9 @@ typedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t; #define FSEv06_ENCODING_STATIC 2 #define FSEv06_ENCODING_DYNAMIC 3 +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) + static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12, 13,14,15,16 }; @@ -3654,36 +3657,61 @@ size_t ZSTDv06_decompress(void* dst, size_t dstCapacity, const void* src, size_t #endif } -size_t ZSTDv06_findFrameCompressedSize(const void* src, size_t srcSize) +MEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret) +{ + *cSize = ret; + *dBound = ZSTD_CONTENTSIZE_ERROR; +} + +void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound) { const BYTE* ip = (const BYTE*)src; size_t remainingSize = srcSize; + size_t nbBlocks = 0; blockProperties_t blockProperties = { bt_compressed, 0 }; /* Frame Header */ { size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min); - if (ZSTDv06_isError(frameHeaderSize)) return frameHeaderSize; - if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) return ERROR(prefix_unknown); - if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong); + if (ZSTDv06_isError(frameHeaderSize)) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize); + return; + } + if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown)); + return; + } + if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } ip += frameHeaderSize; remainingSize -= frameHeaderSize; } /* Loop on each block */ while (1) { size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, remainingSize, &blockProperties); - if (ZSTDv06_isError(cBlockSize)) return cBlockSize; + if (ZSTDv06_isError(cBlockSize)) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize); + return; + } ip += ZSTDv06_blockHeaderSize; remainingSize -= ZSTDv06_blockHeaderSize; - if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); + if (cBlockSize > remainingSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } if (cBlockSize == 0) break; /* bt_end */ ip += cBlockSize; remainingSize -= cBlockSize; + nbBlocks++; } - return ip - (const BYTE*)src; + *cSize = ip - (const BYTE*)src; + *dBound = nbBlocks * ZSTDv06_BLOCKSIZE_MAX; } /*_****************************** diff --git a/lib/legacy/zstd_v06.h b/lib/legacy/zstd_v06.h index fb4eb37c8..d3305e02b 100644 --- a/lib/legacy/zstd_v06.h +++ b/lib/legacy/zstd_v06.h @@ -48,7 +48,8 @@ ZSTDv06_getFrameSrcSize() : get the source length of a ZSTD frame return : the number of bytes that would be read to decompress this frame or an errorCode if it fails (which can be tested using ZSTDv06_isError()) */ -size_t ZSTDv06_findFrameCompressedSize(const void* src, size_t compressedSize); +void ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); /* ************************************* * Helper functions diff --git a/lib/legacy/zstd_v07.c b/lib/legacy/zstd_v07.c index c7bb7a529..9ad8b07d3 100644 --- a/lib/legacy/zstd_v07.c +++ b/lib/legacy/zstd_v07.c @@ -2740,6 +2740,9 @@ typedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t; #define FSEv07_ENCODING_STATIC 2 #define FSEv07_ENCODING_DYNAMIC 3 +#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1) +#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) + static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12, 13,14,15,16 }; @@ -3895,19 +3898,39 @@ size_t ZSTDv07_decompress(void* dst, size_t dstCapacity, const void* src, size_t #endif } -size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t srcSize) +MEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret) +{ + *cSize = ret; + *dBound = ZSTD_CONTENTSIZE_ERROR; +} + +void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound) { const BYTE* ip = (const BYTE*)src; size_t remainingSize = srcSize; + size_t nbBlocks = 0; /* check */ - if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong); + if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } /* Frame Header */ { size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min); - if (ZSTDv07_isError(frameHeaderSize)) return frameHeaderSize; - if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) return ERROR(prefix_unknown); - if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong); + if (ZSTDv07_isError(frameHeaderSize)) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize); + return; + } + if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown)); + return; + } + if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } ip += frameHeaderSize; remainingSize -= frameHeaderSize; } @@ -3915,20 +3938,28 @@ size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t srcSize) while (1) { blockProperties_t blockProperties; size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties); - if (ZSTDv07_isError(cBlockSize)) return cBlockSize; + if (ZSTDv07_isError(cBlockSize)) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize); + return; + } ip += ZSTDv07_blockHeaderSize; remainingSize -= ZSTDv07_blockHeaderSize; if (blockProperties.blockType == bt_end) break; - if (cBlockSize > remainingSize) return ERROR(srcSize_wrong); + if (cBlockSize > remainingSize) { + ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong)); + return; + } ip += cBlockSize; remainingSize -= cBlockSize; + nbBlocks++; } - return ip - (const BYTE*)src; + *cSize = ip - (const BYTE*)src; + *dBound = nbBlocks * ZSTDv07_BLOCKSIZE_ABSOLUTEMAX; } /*_****************************** diff --git a/lib/legacy/zstd_v07.h b/lib/legacy/zstd_v07.h index 6591cd301..8543e0b6a 100644 --- a/lib/legacy/zstd_v07.h +++ b/lib/legacy/zstd_v07.h @@ -55,7 +55,8 @@ ZSTDv07_getFrameSrcSize() : get the source length of a ZSTD frame return : the number of bytes that would be read to decompress this frame or an errorCode if it fails (which can be tested using ZSTDv07_isError()) */ -size_t ZSTDv07_findFrameCompressedSize(const void* src, size_t compressedSize); +void ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, + size_t* cSize, unsigned long long* dBound); /*====== Helper functions ======*/ ZSTDLIBv07_API unsigned ZSTDv07_isError(size_t code); /*!< tells if a `size_t` function result is an error code */ diff --git a/lib/zstd.h b/lib/zstd.h index 4373d6dfd..e9e5eec0f 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1085,6 +1085,17 @@ typedef enum { * Frame size functions ***************************************/ +/** + * Contains the compressed frame size and an upper-bound for the decompressed frame size. + * Note: before using `compressedSize` you must check for errors using ZSTD_isError(). + * similarly, before using `decompressedBound`, you must check for errors using: + * `decompressedBound` != ZSTD_CONTENTSIZE_ERROR + */ +typedef struct { + size_t compressedSize; + unsigned long long decompressedBound; +} ZSTD_frameSizeInfo; + /*! ZSTD_findDecompressedSize() : * `src` should point to the start of a series of ZSTD encoded and/or skippable frames * `srcSize` must be the _exact_ size of this series diff --git a/tests/legacy.c b/tests/legacy.c index e660b9cc6..20f6e2830 100644 --- a/tests/legacy.c +++ b/tests/legacy.c @@ -133,8 +133,8 @@ static int testStreamingAPI(void) static int testFrameDecoding(void) { - if (ZSTD_decompressBound(COMPRESSED, COMPRESSED_SIZE) != ZSTD_CONTENTSIZE_ERROR) { - DISPLAY("ERROR: ZSTD_decompressBound: Expected to receive ZSTD_CONTENTSIZE_ERROR\n"); + if (strlen(EXPECTED) > ZSTD_decompressBound(COMPRESSED, COMPRESSED_SIZE)) { + DISPLAY("ERROR: ZSTD_decompressBound: decompressed bound too small\n"); return 1; } DISPLAY("Frame Decoding OK\n");