Fixed copyCCtx() on uninitialized cctx (reported by Oliver Lange)

This commit is contained in:
Yann Collet 2016-04-11 20:12:27 +02:00
parent 582933fde5
commit 887e7da785
3 changed files with 25 additions and 15 deletions

View File

@ -98,7 +98,7 @@ struct ZSTD_CCtx_s
U32 nextToUpdate3; /* index from which to continue dictionary update */
U32 hashLog3; /* dispatch table : larger == faster, more memory */
U32 loadedDictEnd;
U32 stage;
U32 stage; /* 0: created; 1: init,dictLoad; 2:started */
ZSTD_parameters params;
void* workSpace;
size_t workSpaceSize;
@ -273,7 +273,7 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
zc->seqStore.litStart = zc->seqStore.offCodeStart + maxNbSeq;
zc->hbSize = 0;
zc->stage = 0;
zc->stage = 1;
zc->loadedDictEnd = 0;
return 0;
@ -282,11 +282,11 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc,
/*! ZSTD_copyCCtx() :
* Duplicate an existing context `srcCCtx` into another one `dstCCtx`.
* Only works during stage 0 (i.e. before first call to ZSTD_compressContinue()).
* Only works during stage 1 (i.e. after creation, but before first call to ZSTD_compressContinue()).
* @return : 0, or an error code */
size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx)
{
if (srcCCtx->stage!=0) return ERROR(stage_wrong);
if (srcCCtx->stage!=1) return ERROR(stage_wrong);
dstCCtx->hashLog3 = srcCCtx->hashLog3; /* must be before ZSTD_resetCCtx_advanced */
ZSTD_resetCCtx_advanced(dstCCtx, srcCCtx->params);
@ -2076,10 +2076,11 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* zc,
const BYTE* const ip = (const BYTE*) src;
size_t hbSize = 0;
if (frame && (zc->stage==0)) {
if (zc->stage==0) return ERROR(stage_wrong);
if (frame && (zc->stage==1)) { /* copy saved header */
hbSize = zc->hbSize;
if (dstCapacity <= hbSize) return ERROR(dstSize_tooSmall);
zc->stage = 1;
zc->stage = 2;
memcpy(dst, zc->headerBuffer, hbSize);
dstCapacity -= hbSize;
dst = (char*)dst + hbSize;
@ -2279,7 +2280,6 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* zc,
zc->hbSize = ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId];
}
zc->stage = 0;
return ZSTD_compress_insertDictionary(zc, dict, dictSize);
}
@ -2335,11 +2335,14 @@ size_t ZSTD_compressEnd(ZSTD_CCtx* zc, void* dst, size_t dstCapacity)
BYTE* op = (BYTE*)dst;
size_t hbSize = 0;
/* special case : empty frame : header still within internal buffer */
if (zc->stage==0) {
/* not even init ! */
if (zc->stage==0) return ERROR(stage_wrong);
/* special case : empty frame */
if (zc->stage==1) {
hbSize = zc->hbSize;
if (dstCapacity <= hbSize) return ERROR(dstSize_tooSmall);
zc->stage = 1;
zc->stage = 2;
memcpy(dst, zc->headerBuffer, hbSize);
dstCapacity -= hbSize;
op += hbSize;
@ -2351,6 +2354,7 @@ size_t ZSTD_compressEnd(ZSTD_CCtx* zc, void* dst, size_t dstCapacity)
op[1] = 0;
op[2] = 0;
zc->stage = 0; /* return to "created by not init" status */
return 3+hbSize;
}

View File

@ -166,7 +166,7 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci
Start by initializing a context.
Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression,
or ZSTD_compressBegin_advanced(), for finer parameter control.
It's also possible to duplicate a reference context which has been initialized, using ZSTD_copyCCtx()
It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx()
Then, consume your input using ZSTD_compressContinue().
The interface is synchronous, so all input will be consumed and produce a compressed output.

View File

@ -176,11 +176,17 @@ static int basicUnitTests(U32 seed, double compressibility)
const size_t dictSize = 500;
size_t cSizeOrig;
DISPLAYLEVEL(4, "test%3i : copy context too soon : ", testNb++);
{ size_t const copyResult = ZSTD_copyCCtx(ctxDuplicated, ctxOrig);
if (!ZSTD_isError(copyResult)) goto _output_error; /* error should be detected */
}
DISPLAYLEVEL(4, "OK \n");
DISPLAYLEVEL(4, "test%3i : load dictionary into context : ", testNb++);
result = ZSTD_compressBegin_usingDict(ctxOrig, CNBuffer, dictSize, 2);
if (ZSTD_isError(result)) goto _output_error;
result = ZSTD_copyCCtx(ctxDuplicated, ctxOrig);
if (ZSTD_isError(result)) goto _output_error;
{ size_t const initResult = ZSTD_compressBegin_usingDict(ctxOrig, CNBuffer, dictSize, 2);
if (ZSTD_isError(initResult)) goto _output_error; }
{ size_t const copyResult = ZSTD_copyCCtx(ctxDuplicated, ctxOrig);
if (ZSTD_isError(copyResult)) goto _output_error; }
DISPLAYLEVEL(4, "OK \n");
DISPLAYLEVEL(4, "test%3i : compress with dictionary : ", testNb++);