From: Yann Collet Date: Mon, 11 Apr 2016 18:12:27 +0000 (+0200) Subject: Fixed copyCCtx() on uninitialized cctx (reported by Oliver Lange) X-Git-Tag: v0.6.0^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=887e7da7854d0fd8a01ccb318e745338c5fb094d;p=thirdparty%2Fzstd.git Fixed copyCCtx() on uninitialized cctx (reported by Oliver Lange) --- diff --git a/lib/zstd_compress.c b/lib/zstd_compress.c index 48874673c..3749a89a5 100644 --- a/lib/zstd_compress.c +++ b/lib/zstd_compress.c @@ -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; } diff --git a/lib/zstd_static.h b/lib/zstd_static.h index e804a5083..52dfae9d6 100644 --- a/lib/zstd_static.h +++ b/lib/zstd_static.h @@ -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. diff --git a/programs/fuzzer.c b/programs/fuzzer.c index d93ca75c1..c4b3118e8 100644 --- a/programs/fuzzer.c +++ b/programs/fuzzer.c @@ -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++);