@@ -13,15 +13,12 @@ a list of known ports and bindings is provided on [Zstandard homepage](https://f
|
|||||||
**Development branch status:**
|
**Development branch status:**
|
||||||
|
|
||||||
[![Build Status][travisDevBadge]][travisLink]
|
[![Build Status][travisDevBadge]][travisLink]
|
||||||
[![Build status][AppveyorDevBadge]][AppveyorLink]
|
|
||||||
[![Build status][CircleDevBadge]][CircleLink]
|
[![Build status][CircleDevBadge]][CircleLink]
|
||||||
[![Build status][CirrusDevBadge]][CirrusLink]
|
[![Build status][CirrusDevBadge]][CirrusLink]
|
||||||
[![Fuzzing Status][OSSFuzzBadge]][OSSFuzzLink]
|
[![Fuzzing Status][OSSFuzzBadge]][OSSFuzzLink]
|
||||||
|
|
||||||
[travisDevBadge]: https://api.travis-ci.com/facebook/zstd.svg?branch=dev "Continuous Integration test suite"
|
[travisDevBadge]: https://api.travis-ci.com/facebook/zstd.svg?branch=dev "Continuous Integration test suite"
|
||||||
[travisLink]: https://travis-ci.com/facebook/zstd
|
[travisLink]: https://travis-ci.com/facebook/zstd
|
||||||
[AppveyorDevBadge]: https://ci.appveyor.com/api/projects/status/xt38wbdxjk5mrbem/branch/dev?svg=true "Windows test suite"
|
|
||||||
[AppveyorLink]: https://ci.appveyor.com/project/YannCollet/zstd-p0yf0
|
|
||||||
[CircleDevBadge]: https://circleci.com/gh/facebook/zstd/tree/dev.svg?style=shield "Short test suite"
|
[CircleDevBadge]: https://circleci.com/gh/facebook/zstd/tree/dev.svg?style=shield "Short test suite"
|
||||||
[CircleLink]: https://circleci.com/gh/facebook/zstd
|
[CircleLink]: https://circleci.com/gh/facebook/zstd
|
||||||
[CirrusDevBadge]: https://api.cirrus-ci.com/github/facebook/zstd.svg?branch=dev
|
[CirrusDevBadge]: https://api.cirrus-ci.com/github/facebook/zstd.svg?branch=dev
|
||||||
|
|||||||
@@ -589,49 +589,52 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
|
|||||||
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
|
||||||
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
|
||||||
frameParameter_unsupported, "");
|
frameParameter_unsupported, "");
|
||||||
{
|
{ size_t const skippableSize = skippableHeaderSize + sizeU32;
|
||||||
size_t const skippableSize = skippableHeaderSize + sizeU32;
|
|
||||||
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
|
RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
|
||||||
return skippableSize;
|
return skippableSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! ZSTD_readSkippableFrame() :
|
/*! ZSTD_readSkippableFrame() :
|
||||||
* Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
|
* Retrieves content of a skippable frame, and writes it to dst buffer.
|
||||||
*
|
*
|
||||||
* The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
|
* The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
|
||||||
* i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
|
* i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
|
||||||
* in the magicVariant.
|
* in the magicVariant.
|
||||||
*
|
*
|
||||||
* Returns an error if destination buffer is not large enough, or if the frame is not skippable.
|
* Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame.
|
||||||
*
|
*
|
||||||
* @return : number of bytes written or a ZSTD error.
|
* @return : number of bytes written or a ZSTD error.
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
|
size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,
|
||||||
const void* src, size_t srcSize)
|
unsigned* magicVariant, /* optional, can be NULL */
|
||||||
|
const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
U32 const magicNumber = MEM_readLE32(src);
|
RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
|
||||||
size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
|
|
||||||
size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
|
|
||||||
|
|
||||||
/* check input validity */
|
{ U32 const magicNumber = MEM_readLE32(src);
|
||||||
RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
|
size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
|
||||||
RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
|
size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
|
||||||
RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
|
|
||||||
|
|
||||||
/* deliver payload */
|
/* check input validity */
|
||||||
if (skippableContentSize > 0 && dst != NULL)
|
RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
|
||||||
ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
|
RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
|
||||||
if (magicVariant != NULL)
|
RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
|
||||||
*magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
|
|
||||||
return skippableContentSize;
|
/* deliver payload */
|
||||||
|
if (skippableContentSize > 0 && dst != NULL)
|
||||||
|
ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
|
||||||
|
if (magicVariant != NULL)
|
||||||
|
*magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
|
||||||
|
return skippableContentSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ZSTD_findDecompressedSize() :
|
/** ZSTD_findDecompressedSize() :
|
||||||
* compatible with legacy mode
|
|
||||||
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
|
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
|
||||||
* skippable frames
|
* skippable frames
|
||||||
* @return : decompressed size of the frames contained */
|
* note: compatible with legacy mode
|
||||||
|
* @return : decompressed size of the frames contained */
|
||||||
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
unsigned long long totalDstSize = 0;
|
unsigned long long totalDstSize = 0;
|
||||||
@@ -641,9 +644,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|||||||
|
|
||||||
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||||
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
||||||
if (ZSTD_isError(skippableSize)) {
|
if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;
|
||||||
return ZSTD_CONTENTSIZE_ERROR;
|
|
||||||
}
|
|
||||||
assert(skippableSize <= srcSize);
|
assert(skippableSize <= srcSize);
|
||||||
|
|
||||||
src = (const BYTE *)src + skippableSize;
|
src = (const BYTE *)src + skippableSize;
|
||||||
@@ -651,17 +652,17 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
|
{ unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);
|
||||||
if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
|
if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;
|
||||||
|
|
||||||
/* check for overflow */
|
if (totalDstSize + fcs < totalDstSize)
|
||||||
if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
|
return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */
|
||||||
totalDstSize += ret;
|
totalDstSize += fcs;
|
||||||
}
|
}
|
||||||
|
/* skip to next frame */
|
||||||
{ size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
|
{ size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
|
||||||
if (ZSTD_isError(frameSrcSize)) {
|
if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;
|
||||||
return ZSTD_CONTENTSIZE_ERROR;
|
assert(frameSrcSize <= srcSize);
|
||||||
}
|
|
||||||
|
|
||||||
src = (const BYTE *)src + frameSrcSize;
|
src = (const BYTE *)src + frameSrcSize;
|
||||||
srcSize -= frameSrcSize;
|
srcSize -= frameSrcSize;
|
||||||
@@ -1091,17 +1092,18 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ U32 const magicNumber = MEM_readLE32(src);
|
if (srcSize >= 4) {
|
||||||
DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
|
U32 const magicNumber = MEM_readLE32(src);
|
||||||
(unsigned)magicNumber, ZSTD_MAGICNUMBER);
|
DEBUGLOG(5, "reading magic number %08X", (unsigned)magicNumber);
|
||||||
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||||
|
/* skippable frame detected : skip it */
|
||||||
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
size_t const skippableSize = readSkippableFrameSize(src, srcSize);
|
||||||
FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
|
FORWARD_IF_ERROR(skippableSize, "invalid skippable frame");
|
||||||
assert(skippableSize <= srcSize);
|
assert(skippableSize <= srcSize);
|
||||||
|
|
||||||
src = (const BYTE *)src + skippableSize;
|
src = (const BYTE *)src + skippableSize;
|
||||||
srcSize -= skippableSize;
|
srcSize -= skippableSize;
|
||||||
continue;
|
continue; /* check next frame */
|
||||||
} }
|
} }
|
||||||
|
|
||||||
if (ddict) {
|
if (ddict) {
|
||||||
|
|||||||
Reference in New Issue
Block a user