From 800fa6c37857c5e4bc72114c6755afb5de1cd58c Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 27 Nov 2015 14:30:23 +0100 Subject: [PATCH] stronger tests for zbuff decompression --- lib/zstd_static.h | 10 +++++----- programs/zbufftest.c | 12 +++++++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/zstd_static.h b/lib/zstd_static.h index f0656c942..ba16fa87d 100644 --- a/lib/zstd_static.h +++ b/lib/zstd_static.h @@ -126,17 +126,17 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, co First operation is to retrieve frame parameters, using ZSTD_getFrameParams(). This function doesn't consume its input. It needs enough input data to properly decode the frame header. - The objective is to retrieve *params.windowlog, to know how much memory is required during decoding. - Result : 0 if successfull, it means the ZSTD_parameters structure has been filled. + The objective is to retrieve *params.windowlog, to know minimum amount of memory required during decoding. + Result : 0 when successful, it means the ZSTD_parameters structure has been filled. >0 : means there is not enough data into src. Provides the expected size to successfully decode header. errorCode, which can be tested using ZSTD_isError() (For example, if it's not a ZSTD header) Then it's possible to start decompression. Use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively. ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue(). - ZSTD_decompressContinue() will use previous data blocks during decompress. - They should be located contiguously prior to current block. Alternatively, a round buffer is possible. - Just make sure that the combined of current and accessible past blocks is a minimum of (1 << windowlog). + ZSTD_decompressContinue() requires this exact amount of bytes, or just fails. + ZSTD_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog). + They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible. @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst'. It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header. diff --git a/programs/zbufftest.c b/programs/zbufftest.c index f1fb5e387..590393561 100644 --- a/programs/zbufftest.c +++ b/programs/zbufftest.c @@ -371,7 +371,10 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit sampleSize = (size_t)1 << sampleSizeLog; sampleSize += FUZ_rand(&lseed) & (sampleSize-1); readSize = sampleSize; - genSize = dstBufferSize - totalGenSize; + sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog; + sampleSize = (size_t)1 << sampleSizeLog; + sampleSize += FUZ_rand(&lseed) & (sampleSize-1); + genSize = MIN(sampleSize, dstBufferSize - totalGenSize); errorCode = ZBUFF_decompressContinue(zd, dstBuffer+totalGenSize, &genSize, cBuffer+totalCSize, &readSize); CHECK (ZBUFF_isError(errorCode), "decompression error : %s", ZBUFF_getErrorName(errorCode)); totalGenSize += genSize; @@ -405,13 +408,16 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit ZBUFF_decompressInit(zd); totalCSize = 0; totalGenSize = 0; - while (totalCSize < cSize) + while ( (totalCSize < cSize) && (totalGenSize < dstBufferSize) ) { sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog; sampleSize = (size_t)1 << sampleSizeLog; sampleSize += FUZ_rand(&lseed) & (sampleSize-1); readSize = sampleSize; - genSize = dstBufferSize - totalGenSize; + sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog; + sampleSize = (size_t)1 << sampleSizeLog; + sampleSize += FUZ_rand(&lseed) & (sampleSize-1); + genSize = MIN(sampleSize, dstBufferSize - totalGenSize); errorCode = ZBUFF_decompressContinue(zd, dstBuffer+totalGenSize, &genSize, cBuffer+totalCSize, &readSize); if (ZBUFF_isError(errorCode)) break; /* error correctly detected */ totalGenSize += genSize;