From: Yann Collet Date: Sun, 29 Dec 2024 20:26:04 +0000 (-0800) Subject: improve ZSTD_getFrameHeader on skippable frames X-Git-Tag: v1.5.7^2~46^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2ff6ea7846c598812be580026dfc63fd7229db3;p=thirdparty%2Fzstd.git improve ZSTD_getFrameHeader on skippable frames now reports: - the header size - the magic variant (within @dictID field) --- diff --git a/lib/common/zstd_trace.h b/lib/common/zstd_trace.h index 3ae779fa6..d33edf35d 100644 --- a/lib/common/zstd_trace.h +++ b/lib/common/zstd_trace.h @@ -74,7 +74,7 @@ typedef struct { * Is the dictionary cold? * Only set on decompression. */ - unsigned dictionaryIsCold; + int dictionaryIsCold; /** * The dictionary size or zero if no dictionary. */ diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 6aac5dd3f..b2eb39c51 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -484,8 +484,10 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s if (srcSize < ZSTD_SKIPPABLEHEADERSIZE) return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); - zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE); zfhPtr->frameType = ZSTD_skippableFrame; + zfhPtr->dictID = MEM_readLE32(src) - ZSTD_MAGIC_SKIPPABLE_START; + zfhPtr->headerSize = ZSTD_SKIPPABLEHEADERSIZE; + zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE); return 0; } RETURN_ERROR(prefix_unknown, ""); @@ -917,7 +919,7 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, return regenSize; } -static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming) +static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, int streaming) { #if ZSTD_TRACE if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) { diff --git a/lib/zstd.h b/lib/zstd.h index acbcd0f99..bbddacee7 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1491,7 +1491,7 @@ ZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize); /*! ZSTD_frameHeaderSize() : - * srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX. + * srcSize must be large enough, aka >= ZSTD_FRAMEHEADERSIZE_PREFIX. * @return : size of the Frame Header, * or an error code (if srcSize is too small) */ ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); @@ -1503,18 +1503,18 @@ typedef struct { unsigned blockSizeMax; ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */ unsigned headerSize; - unsigned dictID; + unsigned dictID; /* for ZSTD_skippableFrame, contains the skippable magic variant [0-15] */ unsigned checksumFlag; unsigned _reserved1; unsigned _reserved2; } ZSTD_frameHeader; /*! ZSTD_getFrameHeader() : - * decode Frame Header, or requires larger `srcSize`. - * @return : 0, `zfhPtr` is correctly filled, - * >0, `srcSize` is too small, @return value is the wanted `srcSize` amount, + * decode Frame Header into `zfhPtr`, or requires larger `srcSize`. + * @return : 0 => header is complete, `zfhPtr` is correctly filled, + * >0 => `srcSize` is too small, @return value is the wanted `srcSize` amount, `zfhPtr` is not filled, * or an error code, which can be tested using ZSTD_isError() */ -ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */ +ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /*! ZSTD_getFrameHeader_advanced() : * same as ZSTD_getFrameHeader(), * with added capability to select a format (like ZSTD_f_zstd1_magicless) */ diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 706dd9b95..4ef0db2d0 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -4111,15 +4111,28 @@ static int basicUnitTests(U32 const seed, double compressibility) /* frame operations on skippable frames */ - { const char skippableFrame[] = "\x50\x2a\x4d\x18\x05\x0\x0\0abcde"; - size_t const skippableFrameSize = sizeof(skippableFrame) - 1 /* remove final /0 */; + { const char skippableFrame[] = "\x52\x2a\x4d\x18\x05\x0\x0\0abcde"; + size_t const skippableFrameSize = sizeof(skippableFrame) - 1 /* remove the terminating /0 */; DISPLAYLEVEL(3, "test%3i : ZSTD_findFrameCompressedSize on skippable frame : ", testNb++); - if (ZSTD_findFrameCompressedSize(skippableFrame, skippableFrameSize) != skippableFrameSize) goto _output_error; + CHECK(ZSTD_findFrameCompressedSize(skippableFrame, skippableFrameSize) == skippableFrameSize); DISPLAYLEVEL(3, "OK \n"); DISPLAYLEVEL(3, "test%3i : ZSTD_getFrameContentSize on skippable frame : ", testNb++); - if (ZSTD_getFrameContentSize(skippableFrame, skippableFrameSize) != 0) goto _output_error; + CHECK(ZSTD_getFrameContentSize(skippableFrame, skippableFrameSize) == 0); + DISPLAYLEVEL(3, "OK \n"); + + DISPLAYLEVEL(3, "test%3i : ZSTD_getFrameHeader on skippable frame : ", testNb++); + { ZSTD_frameHeader zfh; + size_t const s = ZSTD_getFrameHeader(&zfh, skippableFrame, skippableFrameSize); + CHECK_Z(s); + CHECK(s == 0); /* success */ + CHECK(zfh.frameType == ZSTD_skippableFrame); + CHECK(zfh.headerSize == ZSTD_SKIPPABLEHEADERSIZE); + CHECK(zfh.dictID == 2); /* magic variant */ + assert(skippableFrameSize >= ZSTD_SKIPPABLEHEADERSIZE); + CHECK(zfh.frameContentSize == skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE); + } DISPLAYLEVEL(3, "OK \n"); }