From: shakeelrao
Date: Fri, 1 Mar 2019 06:55:18 +0000 (-0800)
Subject: implement API-level changes
X-Git-Tag: v1.4.0^2~30^2~7
X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8930c3c79ba725311c72b7c7f33b630118f7f9cb;p=thirdparty%2Fzstd.git
implement API-level changes
---
diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html
index 426c6cf24..c7962e7de 100644
--- a/doc/zstd_manual.html
+++ b/doc/zstd_manual.html
@@ -127,11 +127,10 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
Helper functions
#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11)
/* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
-size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
-unsigned long long ZSTD_decompressBound(const void* src, size_t srcSice); /*!< maximum decompressed size of the compressed source */
-unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
-const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
-int ZSTD_maxCLevel(void); /*!< maximum compression level available */
+size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
+unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
+const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
+int ZSTD_maxCLevel(void); /*!< maximum compression level available */
Explicit context
diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c
index b7eccdfe8..4b9402d69 100644
--- a/lib/decompress/zstd_decompress.c
+++ b/lib/decompress/zstd_decompress.c
@@ -433,40 +433,73 @@ 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` or `decompressedBound`,
+ * you must check the field for errors using ZSTD_isError().
+ */
+typedef struct {
+ size_t compressedSize;
+ size_t decompressedBound;
+} ZSTD_frameSizeInfo;
-static size_t ZSTD_findFrameCompressedSize_internal(const void *src, size_t srcSize, size_t* bound)
+static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
{
+ ZSTD_frameSizeInfo frameSizeInfo;
+ memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
+
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
- if (ZSTD_isLegacy(src, srcSize))
- return ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
+ if (ZSTD_isLegacy(src, srcSize)) {
+ frameSizeInfo.compressedSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
+ frameSizeInfo.decompressedBound = ERROR(version_unsupported);
+ return frameSizeInfo;
+ }
#endif
- if ( (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
- && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START ) {
- return readSkippableFrameSize(src, srcSize);
+
+ if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
+ && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
+ frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
+ return frameSizeInfo;
} else {
const BYTE* ip = (const BYTE*)src;
const BYTE* const ipstart = ip;
size_t remainingSize = srcSize;
- ZSTD_frameHeader zfh;
unsigned nbBlocks = 0;
+ ZSTD_frameHeader zfh;
/* Extract Frame Header */
- { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
- if (ZSTD_isError(ret)) return ret;
- RETURN_ERROR_IF(ret > 0, srcSize_wrong);
+ {
+ size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
+ if (ZSTD_isError(ret)) {
+ frameSizeInfo.compressedSize = ret;
+ frameSizeInfo.decompressedBound = ret;
+ return frameSizeInfo;
+ }
+ if (ret > 0) {
+ frameSizeInfo.compressedSize = ERROR(srcSize_wrong);
+ frameSizeInfo.decompressedBound = ERROR(srcSize_wrong);
+ return frameSizeInfo;
+ }
}
ip += zfh.headerSize;
remainingSize -= zfh.headerSize;
- /* Loop on each block */
+ /* Iterate over each block */
while (1) {
blockProperties_t blockProperties;
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
- if (ZSTD_isError(cBlockSize)) return cBlockSize;
+ if (ZSTD_isError(cBlockSize)) {
+ frameSizeInfo.compressedSize = cBlockSize;
+ frameSizeInfo.decompressedBound = cBlockSize;
+ return frameSizeInfo;
+ }
- RETURN_ERROR_IF(ZSTD_blockHeaderSize + cBlockSize > remainingSize,
- srcSize_wrong);
+ if (ZSTD_blockHeaderSize + cBlockSize > remainingSize) {
+ frameSizeInfo.compressedSize = ERROR(srcSize_wrong);
+ frameSizeInfo.decompressedBound = ERROR(srcSize_wrong);
+ return frameSizeInfo;
+ }
ip += ZSTD_blockHeaderSize + cBlockSize;
remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
@@ -475,14 +508,21 @@ static size_t ZSTD_findFrameCompressedSize_internal(const void *src, size_t srcS
if (blockProperties.lastBlock) break;
}
- if (zfh.checksumFlag) { /* Final frame content checksum */
- RETURN_ERROR_IF(remainingSize < 4, srcSize_wrong);
+ /* Final frame content checksum */
+ if (zfh.checksumFlag) {
+ if (remainingSize < 4) {
+ frameSizeInfo.compressedSize = ERROR(srcSize_wrong);
+ frameSizeInfo.decompressedBound = ERROR(srcSize_wrong);
+ return frameSizeInfo;
+ }
ip += 4;
}
- if (bound != NULL) *bound = (nbBlocks * zfh.blockSizeMax); /* set to block-based bound */
-
- return ip - ipstart;
+ frameSizeInfo.compressedSize = ip - ipstart;
+ frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
+ ? zfh.frameContentSize
+ : nbBlocks * zfh.blockSizeMax;
+ return frameSizeInfo;
}
}
@@ -493,7 +533,8 @@ static size_t ZSTD_findFrameCompressedSize_internal(const void *src, size_t srcS
* @return : the compressed size of the frame starting at `src` */
size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
{
- return ZSTD_findFrameCompressedSize_internal(src, srcSize, NULL);
+ ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
+ return frameSizeInfo.compressedSize;
}
@@ -502,56 +543,23 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
* `src` must point to the start of a ZSTD frame or a skippeable frame
* `srcSize` must be at least as large as the frame contained
* @return : maximum decompressed size of the compressed source
+ * or an error code which can be tested with ZSTD_isError()
*/
-unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
-{
- unsigned long long totalDstSize = 0;
-#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
- if (ZSTD_isLegacy(src, srcSize))
- return ERROR(version_unsupported);
-#endif
-
- /* Loop over each frame */
- while (srcSize >= ZSTD_FRAMEHEADERSIZE_PREFIX) {
- U32 const magicNumber = MEM_readLE32(src);
-
- if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
- size_t const skippableSize = readSkippableFrameSize(src, srcSize);
- if (ZSTD_isError(skippableSize))
- return skippableSize;
- if (srcSize < skippableSize) {
- return ZSTD_CONTENTSIZE_ERROR;
- }
-
- src = (const BYTE *)src + skippableSize;
- srcSize -= skippableSize;
- continue;
- }
-
- { size_t bound = 0;
- unsigned long long frameBound = 0;
- size_t frameSrcSize = 0;
- unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
- if (ret == ZSTD_CONTENTSIZE_ERROR) return ret;
-
- frameSrcSize = ZSTD_findFrameCompressedSize_internal(src, srcSize, &bound);
- if (ZSTD_isError(frameSrcSize)) {
- return ZSTD_CONTENTSIZE_ERROR;
- }
-
- frameBound = (ret == ZSTD_CONTENTSIZE_UNKNOWN) ? bound : ret;
- /* check for overflow */
- if (totalDstSize + frameBound < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
- totalDstSize += frameBound;
-
- src = (const BYTE *)src + frameSrcSize;
- srcSize -= frameSrcSize;
- }
- } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
-
- if (srcSize) return ZSTD_CONTENTSIZE_ERROR;
-
- return totalDstSize;
+size_t ZSTD_decompressBound(const void* src, size_t srcSize)
+{
+ size_t bound = 0;
+ /* Iterate over each frame */
+ while (srcSize > 0) {
+ ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
+ size_t compressedSize = frameSizeInfo.compressedSize;
+ size_t decompressedBound = frameSizeInfo.decompressedBound;
+ FORWARD_IF_ERROR(compressedSize);
+ FORWARD_IF_ERROR(decompressedBound);
+ src = (const BYTE*)src + compressedSize;
+ srcSize -= compressedSize;
+ bound += decompressedBound;
+ }
+ return bound;
}
diff --git a/lib/zstd.h b/lib/zstd.h
index 4d764680e..6d457cfdc 100644
--- a/lib/zstd.h
+++ b/lib/zstd.h
@@ -148,11 +148,10 @@ ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t
/*====== Helper functions ======*/
#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
-ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
-ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSice); /*!< maximum decompressed size of the compressed source */
-ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
-ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
-ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
+ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
+ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
+ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
+ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
/***************************************
@@ -1104,6 +1103,21 @@ typedef enum {
* however it does mean that all frame data must be present and valid. */
ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
+/** ZSTD_decompressBound() :
+ * currently incompatible with legacy mode
+ * `src` must point to the start of a ZSTD frame or a skippeable frame
+ * `srcSize` must be at least as large as the frame contained
+ * @return : maximum decompressed size of the compressed source
+ * or an error code which can be tested with ZSTD_isError()
+ *
+ * note 1 : the bound is exact when Frame_Content_Size field is available in EVERY frame of `src`.
+ * note 2 : when Frame_Content_Size isn't provided, the upper-bound for that frame is calculated by:
+ * upper-bound = min(128 KB, Window_Size)
+ * note 3 : we always use Frame_Content_Size to bound the decompressed frame size if it's present.
+ ** the above formula is only used when Frame_Content_Size is missing.
+ */
+ZSTDLIB_API size_t ZSTD_decompressBound(const void* src, size_t srcSice);
+
/*! ZSTD_frameHeaderSize() :
* srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
* @return : size of the Frame Header,
diff --git a/tests/fuzzer.c b/tests/fuzzer.c
index c64fff883..2ac1f0f47 100644
--- a/tests/fuzzer.c
+++ b/tests/fuzzer.c
@@ -378,8 +378,8 @@ static int basicUnitTests(U32 seed, double compressibility)
DISPLAYLEVEL(3, "test%3i : tight ZSTD_decompressBound test : ", testNb++);
{
- unsigned long long bound = ZSTD_decompressBound(compressedBuffer, cSize);
- if (bound != CNBuffSize) goto _output_error;
+ size_t rSize = ZSTD_decompressBound(compressedBuffer, cSize);
+ if (rSize != CNBuffSize) goto _output_error;
}
DISPLAYLEVEL(3, "OK \n");
@@ -909,8 +909,8 @@ static int basicUnitTests(U32 seed, double compressibility)
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : get tight decompressed bound of multiple frames : ", testNb++);
- { unsigned long long const r = ZSTD_decompressBound(compressedBuffer, cSize);
- if (r != CNBuffSize / 2) goto _output_error; }
+ { size_t const rSize = ZSTD_decompressBound(compressedBuffer, cSize);
+ if (rSize != CNBuffSize / 2) goto _output_error; }
DISPLAYLEVEL(3, "OK \n");
DISPLAYLEVEL(3, "test%3i : decompress multiple frames : ", testNb++);