]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
improve ZSTD_getFrameHeader on skippable frames
authorYann Collet <yann.collet.73@gmail.com>
Sun, 29 Dec 2024 20:26:04 +0000 (12:26 -0800)
committerYann Collet <yann.collet.73@gmail.com>
Sun, 29 Dec 2024 20:26:04 +0000 (12:26 -0800)
now reports:
- the header size
- the magic variant (within @dictID field)

lib/common/zstd_trace.h
lib/decompress/zstd_decompress.c
lib/zstd.h
tests/fuzzer.c

index 3ae779fa62add2261834a4a2a7a749df6ea127f6..d33edf35db6f8d9d30e4afb001cb73ca5b3db59c 100644 (file)
@@ -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.
      */
index 6aac5dd3f59f63898fbb64d2cc5402088e2daee3..b2eb39c51b96dace0fd2e1df165d98ffc67ba547 100644 (file)
@@ -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) {
index acbcd0f99ff9ba7990c59d1fbc3c41d55641ed08..bbddacee754745d8e12a9f94c9810e9216f15054 100644 (file)
@@ -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) */
index 706dd9b9579a00a4ff0416b9e80536626acff419..4ef0db2d05152694c258db330a64eecc1bd3a9d0 100644 (file)
@@ -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");
     }