]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
Fixed copyCCtx() on uninitialized cctx (reported by Oliver Lange)
authorYann Collet <yann.collet.73@gmail.com>
Mon, 11 Apr 2016 18:12:27 +0000 (20:12 +0200)
committerYann Collet <yann.collet.73@gmail.com>
Mon, 11 Apr 2016 18:12:27 +0000 (20:12 +0200)
lib/zstd_compress.c
lib/zstd_static.h
programs/fuzzer.c

index 48874673c1f94c1767bbcf67d2a5b2940367af54..3749a89a5019bbf5ac98d9d361669a215f29a8e8 100644 (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;
 }
 
index e804a5083971fe03ce6d8baab40c13c105c3182e..52dfae9d651aedb928a19d05a57a35e136e7b0a4 100644 (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.
index d93ca75c163af9a8b5142dcd84f09b34a09d92bf..c4b3118e8d8cfbd745a02f82f1df80ace9fc5c6d 100644 (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++);