fixed ZSTD_refPrefix with Multithread-enabled CCtx
This commit is contained in:
@@ -71,12 +71,17 @@
|
|||||||
|
|
||||||
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
|
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
static unsigned g_debugLevel = ZSTD_DEBUG;
|
/* recommended values for ZSTD_DEBUG display levels :
|
||||||
# define DEBUGLOG(l, ...) { \
|
* 2 : reserved for currently active debugging path
|
||||||
if (l<=g_debugLevel) { \
|
* 3 : events once per object lifetime (CCtx, CDict)
|
||||||
fprintf(stderr, __FILE__ ": "); \
|
* 4 : events once per frame
|
||||||
fprintf(stderr, __VA_ARGS__); \
|
* 5 : events once per block
|
||||||
fprintf(stderr, " \n"); \
|
* 6 : events once per sequence (*very* verbose) */
|
||||||
|
# define DEBUGLOG(l, ...) { \
|
||||||
|
if (l<=ZSTD_DEBUG) { \
|
||||||
|
fprintf(stderr, __FILE__ ": "); \
|
||||||
|
fprintf(stderr, __VA_ARGS__); \
|
||||||
|
fprintf(stderr, " \n"); \
|
||||||
} }
|
} }
|
||||||
#else
|
#else
|
||||||
# define DEBUGLOG(l, ...) {} /* disabled */
|
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||||
|
|||||||
@@ -3924,29 +3924,30 @@ size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
|||||||
|
|
||||||
if (cctx->streamStage == zcss_init) {
|
if (cctx->streamStage == zcss_init) {
|
||||||
/* transparent reset */
|
/* transparent reset */
|
||||||
|
const void* const prefix = cctx->prefix;
|
||||||
|
size_t const prefixSize = cctx->prefixSize;
|
||||||
ZSTD_parameters params = cctx->requestedParams;
|
ZSTD_parameters params = cctx->requestedParams;
|
||||||
if (cctx->compressionLevel != ZSTD_CLEVEL_CUSTOM)
|
if (cctx->compressionLevel != ZSTD_CLEVEL_CUSTOM)
|
||||||
params.cParams = ZSTD_getCParams(cctx->compressionLevel,
|
params.cParams = ZSTD_getCParams(cctx->compressionLevel,
|
||||||
cctx->pledgedSrcSizePlusOne-1, 0 /* dictSize */);
|
cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/);
|
||||||
|
cctx->prefix = NULL; cctx->prefixSize = 0; /* single usage */
|
||||||
|
assert(prefix==NULL || cctx->cdict==NULL); /* only one can be set */
|
||||||
|
|
||||||
#ifdef ZSTD_MULTITHREAD
|
#ifdef ZSTD_MULTITHREAD
|
||||||
if (cctx->nbThreads > 1) {
|
if (cctx->nbThreads > 1) {
|
||||||
DEBUGLOG(4, "call ZSTDMT_initCStream_internal");
|
DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbThreads=%u", cctx->nbThreads);
|
||||||
CHECK_F( ZSTDMT_initCStream_internal(cctx->mtctx, NULL, 0, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
|
CHECK_F( ZSTDMT_initCStream_internal(cctx->mtctx, prefix, prefixSize, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
|
||||||
cctx->streamStage = zcss_load;
|
cctx->streamStage = zcss_load;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
const void* const prefix = cctx->prefix;
|
|
||||||
size_t const prefixSize = cctx->prefixSize;
|
|
||||||
cctx->prefix = NULL; cctx->prefixSize = 0; /* single usage */
|
|
||||||
CHECK_F( ZSTD_resetCStream_internal(cctx, prefix, prefixSize, cctx->dictMode, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
|
CHECK_F( ZSTD_resetCStream_internal(cctx, prefix, prefixSize, cctx->dictMode, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
|
||||||
} }
|
} }
|
||||||
|
|
||||||
#ifdef ZSTD_MULTITHREAD
|
#ifdef ZSTD_MULTITHREAD
|
||||||
if (cctx->nbThreads > 1) {
|
if (cctx->nbThreads > 1) {
|
||||||
size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
|
size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
|
||||||
DEBUGLOG(4, "ZSTDMT_compressStream_generic : %u", (U32)flushMin);
|
DEBUGLOG(5, "ZSTDMT_compressStream_generic : %u", (U32)flushMin);
|
||||||
if ( ZSTD_isError(flushMin)
|
if ( ZSTD_isError(flushMin)
|
||||||
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
|
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
|
||||||
ZSTD_startNewCompression(cctx);
|
ZSTD_startNewCompression(cctx);
|
||||||
|
|||||||
@@ -586,7 +586,7 @@ size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
|
|||||||
if (dict) {
|
if (dict) {
|
||||||
ZSTD_freeCDict(zcs->cdictLocal);
|
ZSTD_freeCDict(zcs->cdictLocal);
|
||||||
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
|
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
|
||||||
0 /* byRef */, ZSTD_dm_auto,
|
0 /* byRef */, ZSTD_dm_auto, /* note : a loadPrefix becomes an internal CDict */
|
||||||
params.cParams, zcs->cMem);
|
params.cParams, zcs->cMem);
|
||||||
zcs->cdict = zcs->cdictLocal;
|
zcs->cdict = zcs->cdictLocal;
|
||||||
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
||||||
|
|||||||
@@ -750,6 +750,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
|||||||
const BYTE* const istart = (const BYTE* const)src;
|
const BYTE* const istart = (const BYTE* const)src;
|
||||||
const BYTE* const iend = istart + srcSize;
|
const BYTE* const iend = istart + srcSize;
|
||||||
const BYTE* ip = istart;
|
const BYTE* ip = istart;
|
||||||
|
DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
|
||||||
|
|
||||||
/* check */
|
/* check */
|
||||||
if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
|
if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
|
||||||
@@ -930,12 +931,18 @@ static seq_t ZSTD_decodeSequence(seqState_t* seqState)
|
|||||||
seq.offset = offset;
|
seq.offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
|
seq.matchLength = ML_base[mlCode]
|
||||||
|
+ ((mlCode>31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
|
||||||
if (MEM_32bits() && (mlBits+llBits>24)) BIT_reloadDStream(&seqState->DStream);
|
if (MEM_32bits() && (mlBits+llBits>24)) BIT_reloadDStream(&seqState->DStream);
|
||||||
|
|
||||||
seq.litLength = LL_base[llCode] + ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
|
seq.litLength = LL_base[llCode]
|
||||||
if (MEM_32bits() ||
|
+ ((llCode>15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
|
||||||
(totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BIT_reloadDStream(&seqState->DStream);
|
if ( MEM_32bits()
|
||||||
|
|| (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) )
|
||||||
|
BIT_reloadDStream(&seqState->DStream);
|
||||||
|
|
||||||
|
DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
|
||||||
|
(U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
|
||||||
|
|
||||||
/* ANS state update */
|
/* ANS state update */
|
||||||
FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
|
FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
|
||||||
@@ -975,7 +982,8 @@ size_t ZSTD_execSequence(BYTE* op,
|
|||||||
/* copy Match */
|
/* copy Match */
|
||||||
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
if (sequence.offset > (size_t)(oLitEnd - base)) {
|
||||||
/* offset beyond prefix -> go into extDict */
|
/* offset beyond prefix -> go into extDict */
|
||||||
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
|
if (sequence.offset > (size_t)(oLitEnd - vBase))
|
||||||
|
return ERROR(corruption_detected);
|
||||||
match = dictEnd + (match - base);
|
match = dictEnd + (match - base);
|
||||||
if (match + sequence.matchLength <= dictEnd) {
|
if (match + sequence.matchLength <= dictEnd) {
|
||||||
memmove(oLitEnd, match, sequence.matchLength);
|
memmove(oLitEnd, match, sequence.matchLength);
|
||||||
@@ -1043,9 +1051,12 @@ static size_t ZSTD_decompressSequences(
|
|||||||
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
|
const BYTE* const vBase = (const BYTE*) (dctx->vBase);
|
||||||
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
||||||
int nbSeq;
|
int nbSeq;
|
||||||
|
DEBUGLOG(5, "ZSTD_decompressSequences");
|
||||||
|
|
||||||
/* Build Decoding Tables */
|
/* Build Decoding Tables */
|
||||||
{ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
|
{ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
|
||||||
|
DEBUGLOG(5, "ZSTD_decodeSeqHeaders: size=%u, nbSeq=%i",
|
||||||
|
(U32)seqHSize, nbSeq);
|
||||||
if (ZSTD_isError(seqHSize)) return seqHSize;
|
if (ZSTD_isError(seqHSize)) return seqHSize;
|
||||||
ip += seqHSize;
|
ip += seqHSize;
|
||||||
}
|
}
|
||||||
@@ -1064,11 +1075,13 @@ static size_t ZSTD_decompressSequences(
|
|||||||
nbSeq--;
|
nbSeq--;
|
||||||
{ seq_t const sequence = ZSTD_decodeSequence(&seqState);
|
{ seq_t const sequence = ZSTD_decodeSequence(&seqState);
|
||||||
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
|
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
|
||||||
|
DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
|
||||||
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
||||||
op += oneSeqSize;
|
op += oneSeqSize;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
/* check if reached exact end */
|
/* check if reached exact end */
|
||||||
|
DEBUGLOG(5, "after decode loop, remaining nbSeq : %i", nbSeq);
|
||||||
if (nbSeq) return ERROR(corruption_detected);
|
if (nbSeq) return ERROR(corruption_detected);
|
||||||
/* save reps for next block */
|
/* save reps for next block */
|
||||||
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
|
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
|
||||||
@@ -1355,11 +1368,13 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
|||||||
const void* src, size_t srcSize)
|
const void* src, size_t srcSize)
|
||||||
{ /* blockType == blockCompressed */
|
{ /* blockType == blockCompressed */
|
||||||
const BYTE* ip = (const BYTE*)src;
|
const BYTE* ip = (const BYTE*)src;
|
||||||
|
DEBUGLOG(5, "ZSTD_decompressBlock_internal");
|
||||||
|
|
||||||
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
|
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
|
||||||
|
|
||||||
/* Decode literals section */
|
/* Decode literals section */
|
||||||
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
||||||
|
DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize);
|
||||||
if (ZSTD_isError(litCSize)) return litCSize;
|
if (ZSTD_isError(litCSize)) return litCSize;
|
||||||
ip += litCSize;
|
ip += litCSize;
|
||||||
srcSize -= litCSize;
|
srcSize -= litCSize;
|
||||||
@@ -1697,6 +1712,7 @@ static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skip
|
|||||||
* or an error code, which can be tested using ZSTD_isError() */
|
* or an error code, which can be tested using ZSTD_isError() */
|
||||||
size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
|
DEBUGLOG(5, "ZSTD_decompressContinue");
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
if (srcSize != dctx->expected) return ERROR(srcSize_wrong); /* unauthorized */
|
if (srcSize != dctx->expected) return ERROR(srcSize_wrong); /* unauthorized */
|
||||||
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
|
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
|
||||||
@@ -1756,10 +1772,12 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|||||||
}
|
}
|
||||||
case ZSTDds_decompressLastBlock:
|
case ZSTDds_decompressLastBlock:
|
||||||
case ZSTDds_decompressBlock:
|
case ZSTDds_decompressBlock:
|
||||||
|
DEBUGLOG(5, "case ZSTDds_decompressBlock");
|
||||||
{ size_t rSize;
|
{ size_t rSize;
|
||||||
switch(dctx->bType)
|
switch(dctx->bType)
|
||||||
{
|
{
|
||||||
case bt_compressed:
|
case bt_compressed:
|
||||||
|
DEBUGLOG(5, "case bt_compressed");
|
||||||
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
|
rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
|
||||||
break;
|
break;
|
||||||
case bt_raw :
|
case bt_raw :
|
||||||
@@ -2323,7 +2341,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
} }
|
} }
|
||||||
|
|
||||||
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
||||||
DEBUGLOG(5, "Consume header");
|
DEBUGLOG(4, "Consume header");
|
||||||
CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict));
|
CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict));
|
||||||
|
|
||||||
if ((MEM_readLE32(zds->headerBuffer) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
if ((MEM_readLE32(zds->headerBuffer) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
||||||
@@ -2336,7 +2354,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* control buffer memory usage */
|
/* control buffer memory usage */
|
||||||
DEBUGLOG(5, "Control max buffer memory usage");
|
DEBUGLOG(4, "Control max buffer memory usage");
|
||||||
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
||||||
if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
|
if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
|
||||||
|
|
||||||
@@ -2346,12 +2364,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
zds->blockSize = blockSize;
|
zds->blockSize = blockSize;
|
||||||
if ((zds->inBuffSize < blockSize) || (zds->outBuffSize < neededOutSize)) {
|
if ((zds->inBuffSize < blockSize) || (zds->outBuffSize < neededOutSize)) {
|
||||||
size_t const bufferSize = blockSize + neededOutSize;
|
size_t const bufferSize = blockSize + neededOutSize;
|
||||||
DEBUGLOG(5, "inBuff : from %u to %u",
|
DEBUGLOG(4, "inBuff : from %u to %u",
|
||||||
(U32)zds->inBuffSize, (U32)blockSize);
|
(U32)zds->inBuffSize, (U32)blockSize);
|
||||||
DEBUGLOG(5, "outBuff : from %u to %u",
|
DEBUGLOG(4, "outBuff : from %u to %u",
|
||||||
(U32)zds->outBuffSize, (U32)neededOutSize);
|
(U32)zds->outBuffSize, (U32)neededOutSize);
|
||||||
if (zds->staticSize) { /* static DCtx */
|
if (zds->staticSize) { /* static DCtx */
|
||||||
DEBUGLOG(5, "staticSize : %u", (U32)zds->staticSize);
|
DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
|
||||||
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
||||||
if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx))
|
if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx))
|
||||||
return ERROR(memory_allocation);
|
return ERROR(memory_allocation);
|
||||||
|
|||||||
+4
-1
@@ -1382,8 +1382,10 @@ static int fuzzerTests_newAPI(U32 seed, U32 nbTests, unsigned startTest, double
|
|||||||
|
|
||||||
/* multi - fragments decompression test */
|
/* multi - fragments decompression test */
|
||||||
if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) {
|
if (!dictSize /* don't reset if dictionary : could be different */ && (FUZ_rand(&lseed) & 1)) {
|
||||||
|
DISPLAYLEVEL(5, "resetting DCtx (dict:%08X) \n", (U32)(size_t)dict);
|
||||||
CHECK_Z( ZSTD_resetDStream(zd) );
|
CHECK_Z( ZSTD_resetDStream(zd) );
|
||||||
} else {
|
} else {
|
||||||
|
DISPLAYLEVEL(5, "using dict of size %u \n", (U32)dictSize);
|
||||||
CHECK_Z( ZSTD_initDStream_usingDict(zd, dict, dictSize) );
|
CHECK_Z( ZSTD_initDStream_usingDict(zd, dict, dictSize) );
|
||||||
}
|
}
|
||||||
{ size_t decompressionResult = 1;
|
{ size_t decompressionResult = 1;
|
||||||
@@ -1395,7 +1397,8 @@ static int fuzzerTests_newAPI(U32 seed, U32 nbTests, unsigned startTest, double
|
|||||||
size_t const dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize);
|
size_t const dstBuffSize = MIN(dstBufferSize - totalGenSize, randomDstSize);
|
||||||
inBuff.size = inBuff.pos + readCSrcSize;
|
inBuff.size = inBuff.pos + readCSrcSize;
|
||||||
outBuff.size = inBuff.pos + dstBuffSize;
|
outBuff.size = inBuff.pos + dstBuffSize;
|
||||||
DISPLAYLEVEL(5, "ZSTD_decompressStream input %u bytes \n", (U32)readCSrcSize);
|
DISPLAYLEVEL(5, "ZSTD_decompressStream input %u bytes (pos:%u/%u)\n",
|
||||||
|
(U32)readCSrcSize, (U32)inBuff.pos, (U32)cSize);
|
||||||
decompressionResult = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
decompressionResult = ZSTD_decompressStream(zd, &outBuff, &inBuff);
|
||||||
CHECK (ZSTD_isError(decompressionResult), "decompression error : %s", ZSTD_getErrorName(decompressionResult));
|
CHECK (ZSTD_isError(decompressionResult), "decompression error : %s", ZSTD_getErrorName(decompressionResult));
|
||||||
DISPLAYLEVEL(5, "inBuff.pos = %u \n", (U32)readCSrcSize);
|
DISPLAYLEVEL(5, "inBuff.pos = %u \n", (U32)readCSrcSize);
|
||||||
|
|||||||
Reference in New Issue
Block a user