From: Yann Collet Date: Thu, 28 Jul 2016 18:30:25 +0000 (+0200) Subject: fixed : frame concatenation without checksum X-Git-Tag: v0.8.0^2~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c5bbf64f99de06355fdc08b8e6f869813ef83d8;p=thirdparty%2Fzstd.git fixed : frame concatenation without checksum --- diff --git a/lib/decompress/zbuff_decompress.c b/lib/decompress/zbuff_decompress.c index b22bd84a6..908120fc7 100644 --- a/lib/decompress/zbuff_decompress.c +++ b/lib/decompress/zbuff_decompress.c @@ -282,7 +282,7 @@ size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd, *dstCapacityPtr = op-ostart; { size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zbd->zd); if (!nextSrcSizeHint) return (zbd->outEnd != zbd->outStart); /* return 0 only if fully flushed too */ - if (nextSrcSizeHint > 4) nextSrcSizeHint += ZSTD_blockHeaderSize; + nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zbd->zd) == ZSTDnit_block); if (zbd->inPos > nextSrcSizeHint) return ERROR(GENERIC); /* should never happen */ nextSrcSizeHint -= zbd->inPos; /* already loaded*/ return nextSrcSizeHint; diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 5aa43790a..972a8143d 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -984,6 +984,27 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr ************************************/ size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; } +ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) { + switch(dctx->stage) + { + default: /* should not happen */ + case ZSTDds_getFrameHeaderSize: + case ZSTDds_decodeFrameHeader: + return ZSTDnit_frameHeader; + case ZSTDds_decodeBlockHeader: + return ZSTDnit_blockHeader; + case ZSTDds_decompressBlock: + return ZSTDnit_block; + case ZSTDds_decompressLastBlock: + return ZSTDnit_lastBlock; + case ZSTDds_checkChecksum: + return ZSTDnit_checksum; + case ZSTDds_decodeSkippableHeader: + case ZSTDds_skipFrame: + return ZSTDnit_skippableFrame; + } +} + int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; } /* for zbuff */ /** ZSTD_decompressContinue() : diff --git a/lib/zstd.h b/lib/zstd.h index 01ac7d268..46338aeac 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -370,6 +370,9 @@ ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx) ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx); ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); +typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e; +ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx); + /* Buffer-less streaming decompression (synchronous mode) @@ -408,6 +411,8 @@ ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t ds A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero. Context can then be reset to start a new decompression. + Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType(). + But this information is not required to properly decode a frame. == Special case : skippable frames == diff --git a/programs/playTests.sh b/programs/playTests.sh index 05eb49fce..1fc508f9d 100755 --- a/programs/playTests.sh +++ b/programs/playTests.sh @@ -96,6 +96,13 @@ cat hello.zstd world.zstd > helloworld.zstd $ZSTD -dc helloworld.zstd > result.tmp cat result.tmp sdiff helloworld.tmp result.tmp +$ECHO "frame concatenation without checksum" +$ZSTD -c hello.tmp > hello.zstd --no-check +$ZSTD -c world.tmp > world.zstd --no-check +cat hello.zstd world.zstd > helloworld.zstd +$ZSTD -dc helloworld.zstd > result.tmp +cat result.tmp +sdiff helloworld.tmp result.tmp rm ./*.tmp ./*.zstd $ECHO "frame concatenation tests completed"