From 2fe9126591ea7f436710fe0dd3a79bd473195c40 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 27 Jan 2017 11:56:02 -0800 Subject: [PATCH 1/7] Add multithread support to COVER --- lib/dictBuilder/cover.c | 38 ++++++++++++++++++-------------------- lib/dictBuilder/zdict.h | 5 +++-- programs/zstdcli.c | 1 + 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/dictBuilder/cover.c b/lib/dictBuilder/cover.c index 089f077c..c5b606db 100644 --- a/lib/dictBuilder/cover.c +++ b/lib/dictBuilder/cover.c @@ -14,11 +14,10 @@ #include /* malloc, free, qsort */ #include /* memset */ #include /* clock */ -#ifdef ZSTD_PTHREAD -#include "threading.h" -#endif -#include "mem.h" /* read */ +#include "mem.h" /* read */ +#include "pool.h" +#include "threading.h" #include "zstd_internal.h" /* includes zstd.h */ #ifndef ZDICT_STATIC_LINKING_ONLY #define ZDICT_STATIC_LINKING_ONLY @@ -690,11 +689,9 @@ ZDICTLIB_API size_t COVER_trainFromBuffer( * compiled with multithreaded support. */ typedef struct COVER_best_s { -#ifdef ZSTD_PTHREAD pthread_mutex_t mutex; pthread_cond_t cond; size_t liveJobs; -#endif void *dict; size_t dictSize; COVER_params_t parameters; @@ -708,11 +705,9 @@ static void COVER_best_init(COVER_best_t *best) { if (!best) { return; } -#ifdef ZSTD_PTHREAD pthread_mutex_init(&best->mutex, NULL); pthread_cond_init(&best->cond, NULL); best->liveJobs = 0; -#endif best->dict = NULL; best->dictSize = 0; best->compressedSize = (size_t)-1; @@ -726,13 +721,11 @@ static void COVER_best_wait(COVER_best_t *best) { if (!best) { return; } -#ifdef ZSTD_PTHREAD pthread_mutex_lock(&best->mutex); while (best->liveJobs != 0) { pthread_cond_wait(&best->cond, &best->mutex); } pthread_mutex_unlock(&best->mutex); -#endif } /** @@ -746,10 +739,8 @@ static void COVER_best_destroy(COVER_best_t *best) { if (best->dict) { free(best->dict); } -#ifdef ZSTD_PTHREAD pthread_mutex_destroy(&best->mutex); pthread_cond_destroy(&best->cond); -#endif } /** @@ -760,11 +751,9 @@ static void COVER_best_start(COVER_best_t *best) { if (!best) { return; } -#ifdef ZSTD_PTHREAD pthread_mutex_lock(&best->mutex); ++best->liveJobs; pthread_mutex_unlock(&best->mutex); -#endif } /** @@ -779,12 +768,10 @@ static void COVER_best_finish(COVER_best_t *best, size_t compressedSize, return; } { -#ifdef ZSTD_PTHREAD size_t liveJobs; pthread_mutex_lock(&best->mutex); --best->liveJobs; liveJobs = best->liveJobs; -#endif /* If the new dictionary is better */ if (compressedSize < best->compressedSize) { /* Allocate space if necessary */ @@ -805,12 +792,10 @@ static void COVER_best_finish(COVER_best_t *best, size_t compressedSize, best->parameters = parameters; best->compressedSize = compressedSize; } -#ifdef ZSTD_PTHREAD pthread_mutex_unlock(&best->mutex); if (liveJobs == 0) { pthread_cond_broadcast(&best->cond); } -#endif } } @@ -928,11 +913,12 @@ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void *dictBuffer, unsigned nbSamples, COVER_params_t *parameters) { /* constants */ + const unsigned nbThreads = parameters->nbThreads; const unsigned kMinD = parameters->d == 0 ? 6 : parameters->d; const unsigned kMaxD = parameters->d == 0 ? 16 : parameters->d; const unsigned kMinK = parameters->k == 0 ? kMaxD : parameters->k; const unsigned kMaxK = parameters->k == 0 ? 2048 : parameters->k; - const unsigned kSteps = parameters->steps == 0 ? 256 : parameters->steps; + const unsigned kSteps = parameters->steps == 0 ? 32 : parameters->steps; const unsigned kStepSize = MAX((kMaxK - kMinK) / kSteps, 1); const unsigned kIterations = (1 + (kMaxD - kMinD) / 2) * (1 + (kMaxK - kMinK) / kStepSize); @@ -942,6 +928,7 @@ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void *dictBuffer, unsigned d; unsigned k; COVER_best_t best; + POOL_ctx *pool = NULL; /* Checks */ if (kMinK < kMaxD || kMaxK < kMinK) { LOCALDISPLAYLEVEL(displayLevel, 1, "Incorrect parameters\n"); @@ -956,6 +943,12 @@ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void *dictBuffer, ZDICT_DICTSIZE_MIN); return ERROR(dstSize_tooSmall); } + if (nbThreads > 1) { + pool = POOL_create(nbThreads, 1); + if (!pool) { + return ERROR(memory_allocation); + } + } /* Initialization */ COVER_best_init(&best); /* Turn down global display level to clean up display at level 2 and below */ @@ -998,7 +991,11 @@ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void *dictBuffer, } /* Call the function and pass ownership of data to it */ COVER_best_start(&best); - COVER_tryParameters(data); + if (pool) { + POOL_add(pool, &COVER_tryParameters, data); + } else { + COVER_tryParameters(data); + } /* Print status */ LOCALDISPLAYUPDATE(displayLevel, 2, "\r%u%% ", (U32)((iteration * 100) / kIterations)); @@ -1018,6 +1015,7 @@ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void *dictBuffer, *parameters = best.parameters; memcpy(dictBuffer, best.dict, dictSize); COVER_best_destroy(&best); + POOL_free(pool); return dictSize; } } diff --git a/lib/dictBuilder/zdict.h b/lib/dictBuilder/zdict.h index 1b3bcb5b..aba538c4 100644 --- a/lib/dictBuilder/zdict.h +++ b/lib/dictBuilder/zdict.h @@ -93,8 +93,9 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_advanced(void* dictBuffer, size_t dict typedef struct { unsigned k; /* Segment size : constraint: 0 < k : Reasonable range [16, 2048+] */ unsigned d; /* dmer size : constraint: 0 < d <= k : Reasonable range [6, 16] */ - unsigned steps; /* Number of steps : Only used for optimization : 0 means default (256) : Higher means more parameters checked */ + unsigned steps; /* Number of steps : Only used for optimization : 0 means default (32) : Higher means more parameters checked */ + unsigned nbThreads; /* Number of threads : constraint: 0 < nbThreads : 1 means single-threaded : Only used for optimization : Ignored if ZSTD_MULTITHREAD is not defined */ unsigned notificationLevel; /* Write to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */ unsigned dictID; /* 0 means auto mode (32-bits random value); other : force dictID value */ int compressionLevel; /* 0 means default; target a specific zstd compression level */ @@ -132,7 +133,7 @@ ZDICTLIB_API size_t COVER_trainFromBuffer(void* dictBuffer, size_t dictBufferCap @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) or an error code, which can be tested with ZDICT_isError(). On success `*parameters` contains the parameters selected. - Note : COVER_optimizeTrainFromBuffer() requires about 9 bytes of memory for each input byte. + Note : COVER_optimizeTrainFromBuffer() requires about 4 bytes of memory for each input byte and additionally another 4 bytes of memory for each byte of memory for each tread. */ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void* dictBuffer, size_t dictBufferCapacity, const void* samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, diff --git a/programs/zstdcli.c b/programs/zstdcli.c index 64f2c919..8b8a16b2 100644 --- a/programs/zstdcli.c +++ b/programs/zstdcli.c @@ -577,6 +577,7 @@ int main(int argCount, const char* argv[]) if (operation==zom_train) { #ifndef ZSTD_NODICT if (cover) { + coverParams.nbThreads = nbThreads; coverParams.compressionLevel = dictCLevel; coverParams.notificationLevel = displayLevel; coverParams.dictID = dictID; From 89599104128ca28f368a48a6f43a12b80a4a24b2 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 27 Jan 2017 12:29:27 -0800 Subject: [PATCH 2/7] Add threading and pool to build configs --- build/VS2005/zstdlib/zstdlib.vcproj | 24 ++++++++++++++++++++ build/VS2008/zstdlib/zstdlib.vcproj | 24 ++++++++++++++++++++ build/VS2010/libzstd-dll/libzstd-dll.vcxproj | 6 +++++ build/VS2010/libzstd/libzstd.vcxproj | 6 +++++ build/cmake/lib/CMakeLists.txt | 2 ++ 5 files changed, 62 insertions(+) diff --git a/build/VS2005/zstdlib/zstdlib.vcproj b/build/VS2005/zstdlib/zstdlib.vcproj index 828cc828..f4c9950f 100644 --- a/build/VS2005/zstdlib/zstdlib.vcproj +++ b/build/VS2005/zstdlib/zstdlib.vcproj @@ -335,6 +335,14 @@ RelativePath="..\..\..\lib\dictBuilder\divsufsort.c" > + + + + @@ -383,6 +391,10 @@ RelativePath="..\..\..\lib\common\zstd_common.c" > + + @@ -433,6 +445,14 @@ RelativePath="..\..\..\lib\dictBuilder\divsufsort.h" > + + + + @@ -493,6 +513,10 @@ RelativePath="..\..\..\lib\compress\zstd_opt.h" > + + diff --git a/build/VS2008/zstdlib/zstdlib.vcproj b/build/VS2008/zstdlib/zstdlib.vcproj index 69b742d1..cba0ff90 100644 --- a/build/VS2008/zstdlib/zstdlib.vcproj +++ b/build/VS2008/zstdlib/zstdlib.vcproj @@ -336,6 +336,14 @@ RelativePath="..\..\..\lib\dictBuilder\divsufsort.c" > + + + + @@ -372,6 +380,10 @@ RelativePath="..\..\..\lib\common\zstd_common.c" > + + @@ -422,6 +434,14 @@ RelativePath="..\..\..\lib\dictBuilder\divsufsort.h" > + + + + @@ -478,6 +498,10 @@ RelativePath="..\..\..\lib\compress\zstd_opt.h" > + + diff --git a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj index f0feecb2..14589051 100644 --- a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj +++ b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj @@ -19,6 +19,8 @@ + + @@ -27,6 +29,7 @@ + @@ -44,6 +47,8 @@ + + @@ -63,6 +68,7 @@ + diff --git a/build/VS2010/libzstd/libzstd.vcxproj b/build/VS2010/libzstd/libzstd.vcxproj index c8d21dd4..22d5d4e1 100644 --- a/build/VS2010/libzstd/libzstd.vcxproj +++ b/build/VS2010/libzstd/libzstd.vcxproj @@ -19,6 +19,8 @@ + + @@ -27,6 +29,7 @@ + @@ -44,6 +47,8 @@ + + @@ -63,6 +68,7 @@ + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} diff --git a/build/cmake/lib/CMakeLists.txt b/build/cmake/lib/CMakeLists.txt index db752784..08ae3e9a 100644 --- a/build/cmake/lib/CMakeLists.txt +++ b/build/cmake/lib/CMakeLists.txt @@ -59,6 +59,8 @@ SET(Sources SET(Headers ${LIBRARY_DIR}/zstd.h + ${LIBRARY_DIR}/common/pool.h + ${LIBRARY_DIR}/common/threading.h ${LIBRARY_DIR}/common/bitstream.h ${LIBRARY_DIR}/common/error_private.h ${LIBRARY_DIR}/common/zstd_errors.h From 6570167f8b21da01b68fc373ee898cf8005e4204 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 27 Jan 2017 13:56:41 -0800 Subject: [PATCH 3/7] Fix VS fuzzer build configs --- build/VS2005/fuzzer/fuzzer.vcproj | 24 ++++++++++++++++++++++++ build/VS2008/fuzzer/fuzzer.vcproj | 24 ++++++++++++++++++++++++ build/VS2010/fuzzer/fuzzer.vcxproj | 6 ++++++ 3 files changed, 54 insertions(+) diff --git a/build/VS2005/fuzzer/fuzzer.vcproj b/build/VS2005/fuzzer/fuzzer.vcproj index d6ec14d1..c64c5037 100644 --- a/build/VS2005/fuzzer/fuzzer.vcproj +++ b/build/VS2005/fuzzer/fuzzer.vcproj @@ -343,10 +343,22 @@ RelativePath="..\..\..\lib\common\entropy_common.c" > + + + + + + @@ -393,6 +405,14 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > + + + + @@ -449,6 +469,10 @@ RelativePath="..\..\..\lib\common\zstd_internal.h" > + + diff --git a/build/VS2008/fuzzer/fuzzer.vcproj b/build/VS2008/fuzzer/fuzzer.vcproj index f6912b8d..72540d24 100644 --- a/build/VS2008/fuzzer/fuzzer.vcproj +++ b/build/VS2008/fuzzer/fuzzer.vcproj @@ -340,6 +340,14 @@ RelativePath="..\..\..\lib\dictBuilder\divsufsort.c" > + + + + @@ -380,6 +388,10 @@ RelativePath="..\..\..\lib\common\zstd_common.c" > + + @@ -402,6 +414,14 @@ RelativePath="..\..\..\lib\dictBuilder\divsufsort.h" > + + + + @@ -450,6 +470,10 @@ RelativePath="..\..\..\lib\common\zstd_internal.h" > + + diff --git a/build/VS2010/fuzzer/fuzzer.vcxproj b/build/VS2010/fuzzer/fuzzer.vcxproj index 623a9ca4..07ae508b 100644 --- a/build/VS2010/fuzzer/fuzzer.vcxproj +++ b/build/VS2010/fuzzer/fuzzer.vcxproj @@ -155,6 +155,8 @@ + + @@ -163,6 +165,7 @@ + @@ -172,6 +175,8 @@ + + @@ -179,6 +184,7 @@ + From b42dd27ef5ad325943174b43334c3c63d1e94a35 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 27 Jan 2017 16:00:19 -0800 Subject: [PATCH 4/7] Add include guards and extern C --- lib/common/pool.h | 10 ++++++++++ lib/compress/zstdmt_compress.c | 2 +- lib/compress/zstdmt_compress.h | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/common/pool.h b/lib/common/pool.h index c26f543f..50cb25b1 100644 --- a/lib/common/pool.h +++ b/lib/common/pool.h @@ -9,6 +9,11 @@ #ifndef POOL_H #define POOL_H +#if defined (__cplusplus) +extern "C" { +#endif + + #include /* size_t */ typedef struct POOL_ctx_s POOL_ctx; @@ -43,4 +48,9 @@ typedef void (*POOL_add_function)(void *, POOL_function, void *); */ void POOL_add(void *ctx, POOL_function function, void *opaque); + +#if defined (__cplusplus) +} +#endif + #endif diff --git a/lib/compress/zstdmt_compress.c b/lib/compress/zstdmt_compress.c index 5f0bf2ab..7423d9db 100644 --- a/lib/compress/zstdmt_compress.c +++ b/lib/compress/zstdmt_compress.c @@ -21,7 +21,7 @@ /* ====== Dependencies ====== */ #include /* malloc */ #include /* memcpy */ -#include /* threadpool */ +#include "pool.h" /* threadpool */ #include "threading.h" /* mutex */ #include "zstd_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */ #include "zstdmt_compress.h" diff --git a/lib/compress/zstdmt_compress.h b/lib/compress/zstdmt_compress.h index 92de52d6..3a26b93d 100644 --- a/lib/compress/zstdmt_compress.h +++ b/lib/compress/zstdmt_compress.h @@ -7,6 +7,13 @@ * of patent rights can be found in the PATENTS file in the same directory. */ + #ifndef ZSTDMT_COMPRESS_H + #define ZSTDMT_COMPRESS_H + + #if defined (__cplusplus) + extern "C" { + #endif + /* Note : All prototypes defined in this file shall be considered experimental. * There is no guarantee of API continuity (yet) on any of these prototypes */ @@ -62,3 +69,10 @@ typedef enum { * Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions. * @return : 0, or an error code (which can be tested using ZSTD_isError()) */ ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSDTMT_parameter parameter, unsigned value); + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTDMT_COMPRESS_H */ From 90db3afdee20459eb65e00f58879c6802b92acb9 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 27 Jan 2017 17:32:16 -0800 Subject: [PATCH 5/7] Fix typos in VS2010 build config --- build/VS2010/fuzzer/fuzzer.vcxproj | 4 ++-- build/VS2010/libzstd-dll/libzstd-dll.vcxproj | 8 ++++---- build/VS2010/libzstd/libzstd.vcxproj | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build/VS2010/fuzzer/fuzzer.vcxproj b/build/VS2010/fuzzer/fuzzer.vcxproj index 07ae508b..e30511a7 100644 --- a/build/VS2010/fuzzer/fuzzer.vcxproj +++ b/build/VS2010/fuzzer/fuzzer.vcxproj @@ -175,8 +175,8 @@ - - + + diff --git a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj index 14589051..f78598fb 100644 --- a/build/VS2010/libzstd-dll/libzstd-dll.vcxproj +++ b/build/VS2010/libzstd-dll/libzstd-dll.vcxproj @@ -19,8 +19,8 @@ - - + + @@ -46,7 +46,7 @@ - + @@ -68,7 +68,7 @@ - + diff --git a/build/VS2010/libzstd/libzstd.vcxproj b/build/VS2010/libzstd/libzstd.vcxproj index 22d5d4e1..72779551 100644 --- a/build/VS2010/libzstd/libzstd.vcxproj +++ b/build/VS2010/libzstd/libzstd.vcxproj @@ -46,9 +46,9 @@ - - - + + + From 43474313f83eb2840687d307b0e7cb45a5874729 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Fri, 27 Jan 2017 18:43:05 -0800 Subject: [PATCH 6/7] Fix documentation about memory usage --- lib/dictBuilder/zdict.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dictBuilder/zdict.h b/lib/dictBuilder/zdict.h index aba538c4..4d0a62a2 100644 --- a/lib/dictBuilder/zdict.h +++ b/lib/dictBuilder/zdict.h @@ -133,7 +133,7 @@ ZDICTLIB_API size_t COVER_trainFromBuffer(void* dictBuffer, size_t dictBufferCap @return : size of dictionary stored into `dictBuffer` (<= `dictBufferCapacity`) or an error code, which can be tested with ZDICT_isError(). On success `*parameters` contains the parameters selected. - Note : COVER_optimizeTrainFromBuffer() requires about 4 bytes of memory for each input byte and additionally another 4 bytes of memory for each byte of memory for each tread. + Note : COVER_optimizeTrainFromBuffer() requires about 8 bytes of memory for each input byte and additionally another 5 bytes of memory for each byte of memory for each thread. */ ZDICTLIB_API size_t COVER_optimizeTrainFromBuffer(void* dictBuffer, size_t dictBufferCapacity, const void* samplesBuffer, const size_t *samplesSizes, unsigned nbSamples, From b5fd15ccb2137c625e2ec8e37f67f6ebabff8afb Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Mon, 30 Jan 2017 10:45:58 -0800 Subject: [PATCH 7/7] fixed : legacy decoders v04 and v05 --- lib/legacy/zstd_v04.c | 16 ++++++++-------- lib/legacy/zstd_v05.c | 6 ++++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/legacy/zstd_v04.c b/lib/legacy/zstd_v04.c index e9509070..723242c6 100644 --- a/lib/legacy/zstd_v04.c +++ b/lib/legacy/zstd_v04.c @@ -3012,20 +3012,19 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) /* Literal length */ litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); prevOffset = litLength ? seq->offset : seqState->prevOffset; - if (litLength == MaxLL) - { + if (litLength == MaxLL) { U32 add = *dumps++; if (add < 255) litLength += add; else { - litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */ + litLength = dumps[0] + (dumps[1]<<8) + (dumps[2]<<16); dumps += 3; } - if (dumps >= de) { dumps = de-1; litLength = MaxLL+255; } /* late correction, to avoid read overflow (data is now corrupted anyway) */ + if (dumps > de) { litLength = MaxLL+255; } /* late correction, to avoid using uninitialized memory */ + if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */ } /* Offset */ - { - static const U32 offsetPrefix[MaxOff+1] = { + { static const U32 offsetPrefix[MaxOff+1] = { 1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 }; @@ -3046,10 +3045,11 @@ static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState) U32 add = *dumps++; if (add < 255) matchLength += add; else { - matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */ + matchLength = dumps[0] + (dumps[1]<<8) + (dumps[2]<<16); dumps += 3; } - if (dumps >= de) { dumps = de-1; matchLength = MaxML+255; } /* late correction, to avoid read overflow (data is now corrupted anyway) */ + if (dumps > de) { matchLength = MaxML+255; } /* late correction, to avoid using uninitialized memory */ + if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */ } matchLength += MINMATCH; diff --git a/lib/legacy/zstd_v05.c b/lib/legacy/zstd_v05.c index 43943d81..f1359242 100644 --- a/lib/legacy/zstd_v05.c +++ b/lib/legacy/zstd_v05.c @@ -3230,7 +3230,8 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState) if (litLength&1) litLength>>=1, dumps += 3; else litLength = (U16)(litLength)>>1, dumps += 2; } - if (dumps >= de) { dumps = de-1; litLength = MaxLL+255; } /* late correction, to avoid read overflow (data is now corrupted anyway) */ + if (dumps > de) { litLength = MaxLL+255; } /* late correction, to avoid using uninitialized memory */ + if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */ } /* Offset */ @@ -3263,7 +3264,8 @@ static void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState) if (matchLength&1) matchLength>>=1, dumps += 3; else matchLength = (U16)(matchLength)>>1, dumps += 2; } - if (dumps >= de) { dumps = de-1; matchLength = MaxML+255; } /* late correction, to avoid read overflow (data is now corrupted anyway) */ + if (dumps > de) { matchLength = MaxML+255; } /* late correction, to avoid using uninitialized memory */ + if (dumps >= de) { dumps = de-1; } /* late correction, to avoid read overflow (data is now corrupted anyway) */ } matchLength += MINMATCH;