From 28e7cefea97b0c19c60b261ba57879887d7a7ebb Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Thu, 3 Dec 2015 12:11:30 +0100 Subject: [PATCH 1/7] new zstd-noBench & zstd-frugal builds --- Makefile | 2 +- NEWS | 3 +++ programs/Makefile | 9 ++++++++- programs/zstdcli.c | 22 +++++++++++++++++----- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index a1b6d1230..4ee569e16 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ # ################################################################ # Version number -export VERSION := 0.4.2 +export VERSION := 0.4.3 PRGDIR = programs ZSTDDIR = lib diff --git a/NEWS b/NEWS index 00cfb8c2e..33b8dfc6a 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +v0.4.3 : +new : zstd-frugal + v0.4.2 : Generic minor improvements for small blocks Fixed : big-endian compatibility, by Peter Harris (#85) diff --git a/programs/Makefile b/programs/Makefile index 17fed5b0a..15b4e05c7 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -30,7 +30,7 @@ # fullbench32: Same as fullbench, but forced to compile in 32-bits mode # ########################################################################## -VERSION?= 0.4.2 +VERSION?= 0.4.3 DESTDIR?= PREFIX ?= /usr/local @@ -89,6 +89,13 @@ zstd-pgo : clean zstd rm zstd $(MAKE) zstd MOREFLAGS=-fprofile-use +zstd-noBench: $(ZSTD_FILES) $(ZSTDDIR)/zstd_buffered.c \ + zstdcli.c fileio.c $(ZSTD_FILEIO_LEGACY) + $(CC) $(FLAGS) -DZSTD_NOBENCH $^ -o zstd$(EXT) + +zstd-frugal: clean + CFLAGS=-Os $(MAKE) zstd-noBench ZSTD_LEGACY_SUPPORT=0 + fullbench : $(ZSTD_FILES) \ datagen.c fullbench.c $(CC) $(FLAGS) $^ -o $@$(EXT) diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 7904a616f..8c80b1573 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -138,11 +138,13 @@ static int usage_advanced(const char* programName) DISPLAY( " -q : suppress warnings; specify twice to suppress errors too\n"); DISPLAY( " -c : force write to standard output, even if it is the console\n"); //DISPLAY( " -t : test compressed file integrity\n"); +#ifndef ZSTD_NOBENCH DISPLAY( "Benchmark arguments :\n"); DISPLAY( " -b# : benchmark file(s), using # compression level (default : 1) \n"); DISPLAY( " -B# : cut file into independent blocks of size # (default : no block)\n"); DISPLAY( " -i# : iteration loops [1-9](default : 3)\n"); DISPLAY( " -r# : test all compression levels from 1 to # (default : disabled)\n"); +#endif return 0; } @@ -169,17 +171,19 @@ int main(int argCount, const char** argv) bench=0, decode=0, forceStdout=0, - main_pause=0, - rangeBench = 1; - unsigned fileNameStart = 0; - unsigned nbFiles = 0; + main_pause=0; unsigned cLevel = 1; const char* programName = argv[0]; const char* inFileName = NULL; const char* outFileName = NULL; char* dynNameSpace = NULL; const char extension[] = ZSTD_EXTENSION; + unsigned fileNameStart = 0; + unsigned nbFiles = 0; + int rangeBench = 1; + /* init */ + (void)rangeBench; (void)nbFiles; (void)fileNameStart; /* not used when ZSTD_NOBENCH set */ displayOut = stderr; /* Pick out basename component. Don't rely on stdlib because of conflicting behavior. */ for (i = (int)strlen(programName); i > 0; i--) { if (programName[i] == '/') { i++; break; } } @@ -260,6 +264,7 @@ int main(int argCount, const char** argv) /* keep source file (default anyway, so useless; only for xz/lzma compatibility) */ case 'k': argument++; break; +#ifndef ZSTD_NOBENCH /* Benchmark */ case 'b': bench=1; argument++; break; @@ -293,6 +298,7 @@ int main(int argCount, const char** argv) rangeBench = -1; argument++; break; +#endif /* ZSTD_NOBENCH */ /* Pause at the end (hidden option) */ case 'p': main_pause=1; argument++; break; @@ -320,7 +326,13 @@ int main(int argCount, const char** argv) DISPLAYLEVEL(3, WELCOME_MESSAGE); /* Check if benchmark is selected */ - if (bench) { BMK_benchFiles(argv+fileNameStart, nbFiles, cLevel*rangeBench); goto _end; } + if (bench) + { +#ifndef ZSTD_NOBENCH + BMK_benchFiles(argv+fileNameStart, nbFiles, cLevel*rangeBench); +#endif + goto _end; + } /* No input filename ==> use stdin */ if(!inFileName) { inFileName=stdinmark; } From 417890cec2d1374ee354a87fe56af7f6fb49256e Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 4 Dec 2015 17:16:37 +0100 Subject: [PATCH 2/7] strengthened streaming bufferless compression --- Makefile | 4 +- NEWS | 1 + lib/zstd.h | 2 +- lib/zstd_compress.c | 88 +++++++++++++++++++++++++++++++++++-------- lib/zstd_decompress.c | 32 +++++++++------- lib/zstd_static.h | 17 +++++++-- programs/fuzzer.c | 44 ++++++++++++++++++---- 7 files changed, 147 insertions(+), 41 deletions(-) diff --git a/Makefile b/Makefile index 4ee569e16..9e7b70ee0 100644 --- a/Makefile +++ b/Makefile @@ -87,8 +87,8 @@ gpptest: clean $(MAKE) all CC=g++ CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror" armtest: clean - $(MAKE) -C $(ZSTDDIR) -e all CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror" - $(MAKE) -C $(PRGDIR) -e CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror" + $(MAKE) -C $(ZSTDDIR) all CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror" + $(MAKE) -C $(PRGDIR) CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror -static" usan: clean $(MAKE) test CC=clang MOREFLAGS="-g -fsanitize=undefined" diff --git a/NEWS b/NEWS index 33b8dfc6a..ff276ac5f 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,6 @@ v0.4.3 : new : zstd-frugal +new : external dictionary API v0.4.2 : Generic minor improvements for small blocks diff --git a/lib/zstd.h b/lib/zstd.h index 15fc62633..e4d441497 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -48,7 +48,7 @@ extern "C" { ***************************************/ #define ZSTD_VERSION_MAJOR 0 /* for breaking interface changes */ #define ZSTD_VERSION_MINOR 4 /* for new (non-breaking) interface capabilities */ -#define ZSTD_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */ +#define ZSTD_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */ #define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) unsigned ZSTD_versionNumber (void); diff --git a/lib/zstd_compress.c b/lib/zstd_compress.c index 6304e2b6e..6d2fd2cb5 100644 --- a/lib/zstd_compress.c +++ b/lib/zstd_compress.c @@ -488,7 +488,7 @@ size_t ZSTD_compressSequences(void* dst, size_t maxDstSize, BYTE litLength = llTable[i]; /* (7)*/ /* (7)*/ FSE_encodeSymbol(&blockStream, &stateMatchLength, matchLength); /* 17 */ /* 17 */ if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */ - BIT_addBits(&blockStream, offset, nbBits); /* 32 */ /* 42 */ + BIT_addBits(&blockStream, offset, nbBits); /* 31 */ /* 42 */ /* 24 bits max in 32-bits mode */ if (MEM_32bits()) BIT_flushBits(&blockStream); /* 7 */ FSE_encodeSymbol(&blockStream, &stateOffsetBits, offCode); /* 16 */ /* 51 */ FSE_encodeSymbol(&blockStream, &stateLitLength, litLength); /* 26 */ /* 61 */ @@ -730,13 +730,30 @@ static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls) * Fast Scan ***************************************/ +#define FILLHASHSTEP 3 +static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls) +{ + U32* const hashTable = zc->hashTable; + const U32 hBits = zc->params.hashLog; + const BYTE* const base = zc->base; + const BYTE* ip = base + zc->nextToUpdate; + const BYTE* const iend = (const BYTE*) end; + + while(ip <= iend) + { + hashTable[ZSTD_hashPtr(ip, hBits, mls)] = (U32)(ip - base); + ip += FILLHASHSTEP; + } +} + + FORCE_INLINE size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc, void* dst, size_t maxDstSize, const void* src, size_t srcSize, const U32 mls) { - U32* hashTable = zc->hashTable; + U32* const hashTable = zc->hashTable; const U32 hBits = zc->params.hashLog; seqStore_t* seqStorePtr = &(zc->seqStore); const BYTE* const base = zc->base; @@ -1973,10 +1990,24 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* zc, void* dst, size_t dstSize, const void* src, size_t srcSize) { + U32 adressOverflow = 0; const BYTE* const ip = (const BYTE*) src; + /* Check if blocks follow each other */ + if (src != zc->nextSrc) + { + /* not contiguous */ + size_t delta = zc->nextSrc - ip; + zc->lowLimit = zc->dictLimit; + zc->dictLimit = (U32)(zc->nextSrc - zc->base); + zc->dictBase = zc->base; + if ((size_t)zc->base < delta) adressOverflow = zc->lowLimit; + zc->base -= delta; + zc->nextToUpdate = zc->dictLimit; + } + /* preemptive overflow correction */ - if ((zc->base > (const BYTE*)src) || (zc->lowLimit > (1<<30) )) + if (adressOverflow || (zc->lowLimit > (1<<30) )) { U32 correction = zc->lowLimit-1; ZSTD_reduceIndex(zc, correction); @@ -1988,17 +2019,6 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* zc, else zc->nextToUpdate -= correction; } - /* Check if blocks follow each other */ - if (src != zc->nextSrc) - { - /* not contiguous */ - zc->lowLimit = zc->dictLimit; - zc->dictLimit = (U32)(zc->nextSrc - zc->base); - zc->dictBase = zc->base; - zc->base += ip - zc->nextSrc; - zc->nextToUpdate = zc->dictLimit; - } - /* input-dictionary overlap */ if ((ip+srcSize > zc->dictBase + zc->lowLimit) && (ip < zc->dictBase + zc->dictLimit)) { @@ -2011,8 +2031,46 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* zc, return ZSTD_compress_generic (zc, dst, dstSize, src, srcSize); } +size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* zc, const void* src, size_t srcSize) +{ + const BYTE* const ip = (const BYTE*) src; + const BYTE* const iend = ip + srcSize; -/** ZSTD_compressBegin_advanced + /* input becomes current prefix */ + zc->lowLimit = zc->dictLimit; + zc->dictLimit = (U32)(zc->nextSrc - zc->base); + zc->dictBase = zc->base; + zc->base += ip - zc->nextSrc; + zc->nextToUpdate = zc->dictLimit; + + zc->nextSrc = iend; + if (srcSize <= 8) return 0; + + switch(zc->params.strategy) + { + case ZSTD_fast: + ZSTD_fillHashTable (zc, iend-8, zc->params.searchLength); + break; + + case ZSTD_greedy: + case ZSTD_lazy: + case ZSTD_lazy2: + ZSTD_insertAndFindFirstIndex (zc, iend-8, zc->params.searchLength); + break; + + case ZSTD_btlazy2: + ZSTD_updateTree(zc, iend-8, iend, 1 << zc->params.searchLog, zc->params.searchLength); + break; + + default: + return ERROR(GENERIC); /* strategy doesn't exist; impossible */ + } + + return 0; +} + + +/*! ZSTD_compressBegin_advanced * Write frame header, according to params * @return : nb of bytes written */ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* ctx, diff --git a/lib/zstd_decompress.c b/lib/zstd_decompress.c index 8940969f6..fe4ae972d 100644 --- a/lib/zstd_decompress.c +++ b/lib/zstd_decompress.c @@ -127,10 +127,10 @@ struct ZSTD_DCtx_s U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)]; U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)]; U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)]; - void* previousDstEnd; - void* base; - void* vBase; - void* dictEnd; + const void* previousDstEnd; + const void* base; + const void* vBase; + const void* dictEnd; size_t expected; size_t headerSize; ZSTD_parameters params; @@ -141,7 +141,7 @@ struct ZSTD_DCtx_s size_t litSize; BYTE litBuffer[BLOCKSIZE + 8 /* margin for wildcopy */]; BYTE headerBuffer[ZSTD_frameHeaderSize_max]; -}; /* typedef'd to ZSTD_Dctx within "zstd_static.h" */ +}; /* typedef'd to ZSTD_DCtx within "zstd_static.h" */ size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx) { @@ -505,7 +505,7 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) FORCE_INLINE size_t ZSTD_execSequence(BYTE* op, BYTE* const oend, seq_t sequence, const BYTE** litPtr, const BYTE* const litLimit_8, - BYTE* const base, BYTE* const vBase, BYTE* const dictEnd) + const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd) { static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */ @@ -607,9 +607,9 @@ static size_t ZSTD_decompressSequences( U32* DTableLL = dctx->LLTable; U32* DTableML = dctx->MLTable; U32* DTableOffb = dctx->OffTable; - BYTE* const base = (BYTE*) (dctx->base); - BYTE* const vBase = (BYTE*) (dctx->vBase); - BYTE* const dictEnd = (BYTE*) (dctx->dictEnd); + const BYTE* const base = (const BYTE*) (dctx->base); + const BYTE* const vBase = (const BYTE*) (dctx->vBase); + const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd); /* Build Decoding Tables */ errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength, @@ -691,7 +691,7 @@ size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, const v /* init */ - ctx->base = ctx->vBase = ctx->dictEnd = dst; + ctx->vBase = ctx->base = ctx->dictEnd = dst; /* Frame Header */ { @@ -776,7 +776,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, con if ((dst > ctx->base) && (dst < ctx->previousDstEnd)) /* rolling buffer : new segment into dictionary */ ctx->base = (char*)dst; /* temporary affectation, for vBase calculation */ ctx->dictEnd = ctx->previousDstEnd; - ctx->vBase = (char*)dst - ((char*)(ctx->previousDstEnd) - (char*)(ctx->base)); + ctx->vBase = (const char*)dst - ((const char*)(ctx->previousDstEnd) - (const char*)(ctx->base)); ctx->base = dst; ctx->previousDstEnd = dst; } @@ -827,10 +827,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, con ctx->bType = bp.blockType; ctx->stage = ZSTDds_decompressBlock; } - return 0; } - case 3: + case ZSTDds_decompressBlock: { /* Decompress : block content */ size_t rSize; @@ -862,3 +861,10 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, con } +void ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* src, size_t srcSize) +{ + ctx->dictEnd = ctx->previousDstEnd; + ctx->vBase = (const char*)src - ((const char*)(ctx->previousDstEnd) - (const char*)(ctx->base)); + ctx->base = src; + ctx->previousDstEnd = (const char*)src + srcSize; +} diff --git a/lib/zstd_static.h b/lib/zstd_static.h index f698153ec..5c3156248 100644 --- a/lib/zstd_static.h +++ b/lib/zstd_static.h @@ -104,6 +104,8 @@ size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx, ****************************************/ size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, void* dst, size_t maxDstSize, int compressionLevel); size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, ZSTD_parameters params); +size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* ctx, const void* src, size_t srcSize); + size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t maxDstSize); @@ -118,6 +120,10 @@ size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t maxDstSize); Use ZSTD_compressBegin(). You may also prefer the advanced derivative ZSTD_compressBegin_advanced(), for finer parameter control. + It's then possible to add a dictionary with ZSTD_compressDictionary() + Note that dictionary presence is a "hidden" information, + the decoder needs to be aware that it is required for proper decoding, or decoding will fail. + Then, consume your input using ZSTD_compressContinue(). The interface is synchronous, so all input will be consumed. You must ensure there is enough space in destination buffer to store compressed data under worst case scenario. @@ -131,12 +137,15 @@ size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t maxDstSize); typedef struct ZSTD_DCtx_s ZSTD_DCtx; ZSTD_DCtx* ZSTD_createDCtx(void); -size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx); size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); +size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx); size_t ZSTD_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcSize); +void ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* src, size_t srcSize); + size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx); size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); + /** Streaming decompression, bufferless mode @@ -146,15 +155,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 minimum amount of memory required during decoding. + 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, you can optionally insert a dictionary. This operation must mimic the compressor behavior, otherwise decompression will fail or be corrupted. + 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() requires this exact amount of bytes, or just fails. + ZSTD_decompressContinue() requires this exact amount of bytes, or it will fail. 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. diff --git a/programs/fuzzer.c b/programs/fuzzer.c index 793af7f9c..62f58f10a 100644 --- a/programs/fuzzer.c +++ b/programs/fuzzer.c @@ -294,9 +294,10 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit /* test loop */ for ( ; testNb <= nbTests; testNb++ ) { - size_t sampleSize, sampleStart; - size_t cSize, dSize, dSupSize; - U32 sampleSizeLog, buffNb, cLevelMod; + size_t sampleSize, sampleStart, maxTestSize, totalTestSize; + size_t cSize, dSize, dSupSize, errorCode; + U32 sampleSizeLog, buffNb, cLevelMod, nbChunks, n; + XXH64_state_t crc64; U64 crcOrig, crcDest; int cLevel; BYTE* sampleBuffer; @@ -342,7 +343,6 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit /* compression failure test : too small dest buffer */ if (cSize > 3) { - size_t errorCode; const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */ const size_t tooSmallSize = cSize - missing; static const U32 endMark = 0x4DC2B1A9; @@ -365,7 +365,6 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit /* truncated src decompression test */ { - size_t errorCode; const size_t missing = (FUZ_rand(&lseed) % (cSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */ const size_t tooSmallSize = cSize - missing; void* cBufferTooSmall = malloc(tooSmallSize); /* valgrind will catch overflows */ @@ -379,7 +378,6 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit /* too small dst decompression test */ if (sampleSize > 3) { - size_t errorCode; const size_t missing = (FUZ_rand(&lseed) % (sampleSize-2)) + 1; /* no problem, as cSize > 4 (frameHeaderSizer) */ const size_t tooSmallSize = sampleSize - missing; static const BYTE token = 0xA9; @@ -424,7 +422,6 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit U32 noiseSrc = FUZ_rand(&lseed) % 5; const U32 endMark = 0xA9B1C3D6; U32 endCheck; - size_t errorCode; srcBuffer = cNoiseBuffer[noiseSrc]; memcpy(dstBuffer+sampleSize, &endMark, 4); errorCode = ZSTD_decompress(dstBuffer, sampleSize, cBuffer, cSize); @@ -435,6 +432,39 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit CHECK(endMark!=endCheck, "ZSTD_decompress on noisy src : dst buffer overflow"); } } + + /* Multi - segments compression test */ + XXH64_reset(&crc64, 0); + nbChunks = (FUZ_rand(&lseed) & 127) + 2; + sampleSizeLog = FUZ_rand(&lseed) % maxSrcLog; + maxTestSize = (size_t)1 << sampleSizeLog; + maxTestSize += FUZ_rand(&lseed) & (maxTestSize-1); + totalTestSize = 0; + cSize = ZSTD_compressBegin(ctx, cBuffer, cBufferSize, (FUZ_rand(&lseed) % (20 - (sampleSizeLog/3))) + 1); + for (n=0; n maxTestSize) break; + } + errorCode = ZSTD_compressEnd(ctx, cBuffer+cSize, cBufferSize-cSize); + CHECK (ZSTD_isError(errorCode), "multi-segments epilogue error : %s", ZSTD_getErrorName(errorCode)); + cSize += errorCode; + crcOrig = XXH64_digest(&crc64); } DISPLAY("\rAll fuzzer tests completed \n"); From 553cf6a926434d90be23fc2ccb373f7ce201b5c2 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 4 Dec 2015 17:25:26 +0100 Subject: [PATCH 3/7] time-limited fuzzer tests --- programs/fuzzer.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/programs/fuzzer.c b/programs/fuzzer.c index 62f58f10a..d108ff976 100644 --- a/programs/fuzzer.c +++ b/programs/fuzzer.c @@ -79,11 +79,13 @@ static const U32 prime2 = 2246822519U; static U32 g_displayLevel = 2; #define DISPLAYUPDATE(l, ...) if (g_displayLevel>=l) { \ - if ((FUZ_GetMilliSpan(g_time) > g_refreshRate) || (g_displayLevel>=4)) \ - { g_time = FUZ_GetMilliStart(); DISPLAY(__VA_ARGS__); \ + if ((FUZ_GetMilliSpan(g_displayTime) > g_refreshRate) || (g_displayLevel>=4)) \ + { g_displayTime = FUZ_GetMilliStart(); DISPLAY(__VA_ARGS__); \ if (g_displayLevel>=4) fflush(stdout); } } static const U32 g_refreshRate = 150; -static U32 g_time = 0; +static U32 g_displayTime = 0; + +static U32 g_testTime = 0; /********************************************************* @@ -266,6 +268,7 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit U32 testNb = 0; U32 coreSeed = seed, lseed = 0; ZSTD_CCtx* ctx; + U32 startTime = FUZ_GetMilliStart(); /* allocation */ ctx = ZSTD_createCCtx(); @@ -292,7 +295,7 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit FUZ_rand(&coreSeed); /* test loop */ - for ( ; testNb <= nbTests; testNb++ ) + for ( ; (testNb <= nbTests) || (FUZ_GetMilliSpan(startTime) < g_testTime); testNb++ ) { size_t sampleSize, sampleStart, maxTestSize, totalTestSize; size_t cSize, dSize, dSupSize, errorCode; @@ -303,7 +306,9 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit BYTE* sampleBuffer; /* init */ - DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); + DISPLAYUPDATE(2, "\r%6u", testNb); + if (nbTests >= testNb) DISPLAYUPDATE(2, "\r/%6u", nbTests); + DISPLAYUPDATE(2, " "); FUZ_rand(&coreSeed); lseed = coreSeed ^ prime1; buffNb = FUZ_rand(&lseed) & 127; @@ -466,7 +471,7 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit cSize += errorCode; crcOrig = XXH64_digest(&crc64); } - DISPLAY("\rAll fuzzer tests completed \n"); + DISPLAY("\r%u fuzzer tests completed \n", testNb); _cleanup: ZSTD_freeCCtx(ctx); @@ -550,7 +555,7 @@ int main(int argc, char** argv) break; case 'i': - argument++; + argument++; g_testTime=0; nbTests=0; while ((*argument>='0') && (*argument<='9')) { @@ -560,6 +565,20 @@ int main(int argc, char** argv) } break; + case 'T': + argument++; + nbTests=0; g_testTime=0; + while ((*argument>='0') && (*argument<='9')) + { + g_testTime *= 10; + g_testTime += *argument - '0'; + argument++; + } + if (*argument=='m') g_testTime *=60, argument++; + if (*argument=='n') argument++; + g_testTime *= 1000; + break; + case 's': argument++; seed=0; From 1c2ddba469211965de6a26bb277e8141f2dd5410 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Fri, 4 Dec 2015 17:45:35 +0100 Subject: [PATCH 4/7] use time limited fuzzer tests in CI --- programs/Makefile | 5 +++-- programs/fuzzer.c | 11 +++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/programs/Makefile b/programs/Makefile index 15b4e05c7..c2a1ca267 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -65,6 +65,7 @@ VOID = /dev/null endif ZBUFFTEST = -T2mn +FUZZERTEST= -T5mn .PHONY: default all clean install uninstall test test32 test-all @@ -258,10 +259,10 @@ test-fullbench32: fullbench32 datagen ./fullbench32 -i1 -P0 test-fuzzer: fuzzer - ./fuzzer + ./fuzzer $(FUZZERTEST) test-fuzzer32: fuzzer32 - ./fuzzer32 + ./fuzzer32 $(FUZZERTEST) test-zbuff: zbufftest ./zbufftest $(ZBUFFTEST) diff --git a/programs/fuzzer.c b/programs/fuzzer.c index d108ff976..0079eebb9 100644 --- a/programs/fuzzer.c +++ b/programs/fuzzer.c @@ -306,9 +306,10 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit BYTE* sampleBuffer; /* init */ - DISPLAYUPDATE(2, "\r%6u", testNb); - if (nbTests >= testNb) DISPLAYUPDATE(2, "\r/%6u", nbTests); - DISPLAYUPDATE(2, " "); + if (nbTests >= testNb) + { DISPLAYUPDATE(2, "\r%6u/%6u ", testNb, nbTests); } + else { DISPLAYUPDATE(2, "\r%6u ", testNb); } + FUZ_rand(&coreSeed); lseed = coreSeed ^ prime1; buffNb = FUZ_rand(&lseed) & 127; @@ -471,7 +472,7 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit cSize += errorCode; crcOrig = XXH64_digest(&crc64); } - DISPLAY("\r%u fuzzer tests completed \n", testNb); + DISPLAY("\r%u fuzzer tests completed \n", testNb-1); _cleanup: ZSTD_freeCCtx(ctx); @@ -629,8 +630,6 @@ int main(int argc, char** argv) DISPLAY("Seed = %u\n", seed); if (proba!=FUZ_COMPRESSIBILITY_DEFAULT) DISPLAY("Compressibility : %i%%\n", proba); - if (nbTests<=0) nbTests=1; - if (testNb==0) result = basicUnitTests(0, ((double)proba) / 100); /* constant seed for predictability */ if (!result) result = fuzzerTests(seed, nbTests, testNb, ((double)proba) / 100); From e47c4e5f8ee18bf7b7ba442ea1a6b6f0543b08e0 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 5 Dec 2015 09:23:53 +0100 Subject: [PATCH 5/7] strengthened bufferless streaming decompression --- lib/zstd_compress.c | 22 +++++++++++----------- programs/Makefile | 2 +- programs/fuzzer.c | 41 ++++++++++++++++++++++++++++++++++++----- programs/zstdcli.c | 2 +- 4 files changed, 49 insertions(+), 18 deletions(-) diff --git a/lib/zstd_compress.c b/lib/zstd_compress.c index 6d2fd2cb5..c18d8f86c 100644 --- a/lib/zstd_compress.c +++ b/lib/zstd_compress.c @@ -769,12 +769,12 @@ size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc, /* init */ ZSTD_resetSeqStore(seqStorePtr); - if (ip < base+4) + if (ip < lowest+4) { - hashTable[ZSTD_hashPtr(base+1, hBits, mls)] = 1; - hashTable[ZSTD_hashPtr(base+2, hBits, mls)] = 2; - hashTable[ZSTD_hashPtr(base+3, hBits, mls)] = 3; - ip = base+4; + hashTable[ZSTD_hashPtr(lowest+1, hBits, mls)] = zc->dictLimit+1; + hashTable[ZSTD_hashPtr(lowest+2, hBits, mls)] = zc->dictLimit+2; + hashTable[ZSTD_hashPtr(lowest+3, hBits, mls)] = zc->dictLimit+3; + ip = lowest+4; } /* Main Search Loop */ @@ -1535,6 +1535,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx, const BYTE* anchor = istart; const BYTE* const iend = istart + srcSize; const BYTE* const ilimit = iend - 8; + const BYTE* const base = ctx->base + ctx->dictLimit; size_t offset_2=REPCODE_STARTVALUE, offset_1=REPCODE_STARTVALUE; const U32 maxSearches = 1 << ctx->params.searchLog; @@ -1547,7 +1548,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx, /* init */ ZSTD_resetSeqStore(seqStorePtr); - if (((ip-ctx->base) - ctx->dictLimit) < REPCODE_STARTVALUE) ip += REPCODE_STARTVALUE; + if ((ip-base) < REPCODE_STARTVALUE) ip = base + REPCODE_STARTVALUE; /* Match Loop */ while (ip < ilimit) @@ -1572,7 +1573,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx, matchLength = ml2, start = ip, offset=offsetFound; } - if (matchLength < MINMATCH) + if (matchLength < MINMATCH) { ip += ((ip-anchor) >> g_searchStrength) + 1; /* jump faster over incompressible sections */ continue; @@ -1633,7 +1634,7 @@ size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx, /* catch up */ if (offset) { - while ((start>anchor) && (start>ctx->base+offset) && (start[-1] == start[-1-offset])) /* only search for offset within prefix */ + while ((start>anchor) && (start>base+offset) && (start[-1] == start[-1-offset])) /* only search for offset within prefix */ { start--; matchLength++; } offset_2 = offset_1; offset_1 = offset; } @@ -1990,7 +1991,6 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* zc, void* dst, size_t dstSize, const void* src, size_t srcSize) { - U32 adressOverflow = 0; const BYTE* const ip = (const BYTE*) src; /* Check if blocks follow each other */ @@ -2001,13 +2001,13 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* zc, zc->lowLimit = zc->dictLimit; zc->dictLimit = (U32)(zc->nextSrc - zc->base); zc->dictBase = zc->base; - if ((size_t)zc->base < delta) adressOverflow = zc->lowLimit; zc->base -= delta; zc->nextToUpdate = zc->dictLimit; + if (zc->dictLimit - zc->lowLimit < 8) zc->lowLimit = zc->dictLimit; /* too small extDict */ } /* preemptive overflow correction */ - if (adressOverflow || (zc->lowLimit > (1<<30) )) + if ((zc->base > ip) || (zc->lowLimit > (1<<30) )) { U32 correction = zc->lowLimit-1; ZSTD_reduceIndex(zc, correction); diff --git a/programs/Makefile b/programs/Makefile index c2a1ca267..6e9d6b56f 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -281,7 +281,7 @@ valgrindTest: zstd datagen fuzzer fullbench zbufftest ./datagen -g64MB > tmp valgrind --leak-check=yes --error-exitcode=1 ./zstd -vf tmp $(VOID) @rm tmp - valgrind --leak-check=yes --error-exitcode=1 ./fuzzer -i1000 -t1 + valgrind --leak-check=yes --error-exitcode=1 ./fuzzer -T1mn -t1 valgrind --leak-check=yes --error-exitcode=1 ./fullbench -i1 valgrind --leak-check=yes --error-exitcode=1 ./zbufftest -T1mn diff --git a/programs/fuzzer.c b/programs/fuzzer.c index 0079eebb9..152d1c149 100644 --- a/programs/fuzzer.c +++ b/programs/fuzzer.c @@ -261,6 +261,7 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit BYTE* srcBuffer; BYTE* cBuffer; BYTE* dstBuffer; + BYTE* mirrorBuffer; size_t srcBufferSize = (size_t)1<= dstBufferSize) maxTestSize = dstBufferSize-1; totalTestSize = 0; cSize = ZSTD_compressBegin(ctx, cBuffer, cBufferSize, (FUZ_rand(&lseed) % (20 - (sampleSizeLog/3))) + 1); for (n=0; n maxTestSize) break; errorCode = ZSTD_compressContinue(ctx, cBuffer+cSize, cBufferSize-cSize, srcBuffer+sampleStart, sampleSize); CHECK (ZSTD_isError(errorCode), "multi-segments compression error : %s", ZSTD_getErrorName(errorCode)); cSize += errorCode; XXH64_update(&crc64, srcBuffer+sampleStart, sampleSize); + memcpy(mirrorBuffer + totalTestSize, srcBuffer+sampleStart, sampleSize); totalTestSize += sampleSize; - - if (totalTestSize > maxTestSize) break; } errorCode = ZSTD_compressEnd(ctx, cBuffer+cSize, cBufferSize-cSize); CHECK (ZSTD_isError(errorCode), "multi-segments epilogue error : %s", ZSTD_getErrorName(errorCode)); cSize += errorCode; crcOrig = XXH64_digest(&crc64); + + /* streaming decompression test */ + errorCode = ZSTD_resetDCtx(dctx); + CHECK (ZSTD_isError(errorCode), "cannot init DCtx : %s", ZSTD_getErrorName(errorCode)); + totalCSize = 0; + totalGenSize = 0; + while (totalCSize < cSize) + { + size_t inSize = ZSTD_nextSrcSizeToDecompress(dctx); + size_t genSize = ZSTD_decompressContinue(dctx, dstBuffer+totalGenSize, dstBufferSize-totalGenSize, cBuffer+totalCSize, inSize); + CHECK (ZSTD_isError(genSize), "streaming decompression error : %s", ZSTD_getErrorName(genSize)); + totalGenSize += genSize; + totalCSize += inSize; + } + CHECK (ZSTD_nextSrcSizeToDecompress(dctx) != 0, "frame not fully decoded"); + CHECK (totalGenSize != totalTestSize, "decompressed data : wrong size") + CHECK (totalCSize != cSize, "compressed data should be fully read") + crcDest = XXH64(dstBuffer, totalTestSize, 0); + if (crcDest!=crcOrig) + errorCode = findDiff(mirrorBuffer, dstBuffer, totalTestSize); + CHECK (crcDest!=crcOrig, "streaming decompressed data corrupted : byte %u / %u (%02X!=%02X)", + (U32)errorCode, (U32)totalTestSize, dstBuffer[errorCode], mirrorBuffer[errorCode]); + } DISPLAY("\r%u fuzzer tests completed \n", testNb-1); _cleanup: ZSTD_freeCCtx(ctx); + ZSTD_freeDCtx(dctx); free(cNoiseBuffer[0]); free(cNoiseBuffer[1]); free(cNoiseBuffer[2]); @@ -483,6 +513,7 @@ _cleanup: free(cNoiseBuffer[4]); free(cBuffer); free(dstBuffer); + free(mirrorBuffer); return result; _output_error: diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 8c80b1573..6f23c09a8 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -119,7 +119,7 @@ static int usage(const char* programName) DISPLAY( " with no FILE, or when FILE is - , read standard input\n"); DISPLAY( "Arguments :\n"); DISPLAY( " -1 : Fast compression (default) \n"); - DISPLAY( " -9 : High compression \n"); + DISPLAY( " -19 : High compression \n"); DISPLAY( " -d : decompression (default for %s extension)\n", ZSTD_EXTENSION); //DISPLAY( " -z : force compression\n"); DISPLAY( " -f : overwrite output without prompting \n"); From 4bfe415fa71e429bfd872e03d554b82ebd2e301d Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sun, 6 Dec 2015 13:18:37 +0100 Subject: [PATCH 6/7] validated external dictionary --- lib/zstd_decompress.c | 4 ++-- programs/fuzzer.c | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/zstd_decompress.c b/lib/zstd_decompress.c index fe4ae972d..d1e01c3e5 100644 --- a/lib/zstd_decompress.c +++ b/lib/zstd_decompress.c @@ -538,13 +538,13 @@ FORCE_INLINE size_t ZSTD_execSequence(BYTE* op, match = dictEnd - (base-match); if (match + sequence.matchLength <= dictEnd) { - memcpy(oLitEnd, match, sequence.matchLength); + memmove(oLitEnd, match, sequence.matchLength); return sequenceLength; } /* span extDict & currentPrefixSegment */ { size_t length1 = dictEnd - match; - memcpy(oLitEnd, match, length1); + memmove(oLitEnd, match, length1); op = oLitEnd + length1; sequence.matchLength -= length1; match = base; diff --git a/programs/fuzzer.c b/programs/fuzzer.c index 152d1c149..f3fda456a 100644 --- a/programs/fuzzer.c +++ b/programs/fuzzer.c @@ -309,6 +309,8 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit U64 crcOrig, crcDest; int cLevel; BYTE* sampleBuffer; + const BYTE* dict; + size_t dictSize; /* init */ if (nbTests >= testNb) @@ -451,8 +453,18 @@ int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compressibilit maxTestSize = (size_t)1 << sampleSizeLog; maxTestSize += FUZ_rand(&lseed) & (maxTestSize-1); if (maxTestSize >= dstBufferSize) maxTestSize = dstBufferSize-1; - totalTestSize = 0; + + sampleSizeLog = FUZ_rand(&lseed) % maxSampleLog; + sampleSize = (size_t)1 << sampleSizeLog; + sampleSize += FUZ_rand(&lseed) & (sampleSize-1); + sampleStart = FUZ_rand(&lseed) % (srcBufferSize - sampleSize); + dict = srcBuffer + sampleStart; + dictSize = sampleSize; + cSize = ZSTD_compressBegin(ctx, cBuffer, cBufferSize, (FUZ_rand(&lseed) % (20 - (sampleSizeLog/3))) + 1); + errorCode = ZSTD_compress_insertDictionary(ctx, dict, dictSize); + CHECK (ZSTD_isError(errorCode), "dictionary insertion error : %s", ZSTD_getErrorName(errorCode)); + totalTestSize = 0; for (n=0; n Date: Mon, 7 Dec 2015 10:44:25 +0100 Subject: [PATCH 7/7] update graph --- NEWS | 2 +- images/CSpeed.png | Bin 37278 -> 36039 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index ff276ac5f..ad8a737f9 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ v0.4.3 : -new : zstd-frugal new : external dictionary API +new : zstd-frugal v0.4.2 : Generic minor improvements for small blocks diff --git a/images/CSpeed.png b/images/CSpeed.png index 0289e2db7bb3be32482524d669017bbda26284c0..fe54752ef422bc5d0c098e5382a612ca2d18b907 100644 GIT binary patch literal 36039 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