Fixed : ZBUFF_compressEnd() called multiple times with too small dst buffer (#206)
This commit is contained in:
@@ -79,7 +79,7 @@ static size_t const ZBUFF_endFrameSize = ZSTD_BLOCKHEADERSIZE;
|
|||||||
* output : ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + ZBUFF_endFrameSize : ensures it's always possible to write/flush/end a full block at best speed.
|
* output : ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + ZBUFF_endFrameSize : ensures it's always possible to write/flush/end a full block at best speed.
|
||||||
* **************************************************/
|
* **************************************************/
|
||||||
|
|
||||||
typedef enum { ZBUFFcs_init, ZBUFFcs_load, ZBUFFcs_flush } ZBUFF_cStage;
|
typedef enum { ZBUFFcs_init, ZBUFFcs_load, ZBUFFcs_flush, ZBUFFcs_final } ZBUFF_cStage;
|
||||||
|
|
||||||
/* *** Resources *** */
|
/* *** Resources *** */
|
||||||
struct ZBUFF_CCtx_s {
|
struct ZBUFF_CCtx_s {
|
||||||
@@ -196,7 +196,7 @@ MEM_STATIC size_t ZBUFF_limitCopy(void* dst, size_t dstCapacity, const void* src
|
|||||||
static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc,
|
static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc,
|
||||||
void* dst, size_t* dstCapacityPtr,
|
void* dst, size_t* dstCapacityPtr,
|
||||||
const void* src, size_t* srcSizePtr,
|
const void* src, size_t* srcSizePtr,
|
||||||
int flush) /* aggregate : wait for full block before compressing */
|
int flush)
|
||||||
{
|
{
|
||||||
U32 notDone = 1;
|
U32 notDone = 1;
|
||||||
const char* const istart = (const char*)src;
|
const char* const istart = (const char*)src;
|
||||||
@@ -243,15 +243,15 @@ static size_t ZBUFF_compressContinue_generic(ZBUFF_CCtx* zbc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case ZBUFFcs_flush:
|
case ZBUFFcs_flush:
|
||||||
/* flush into dst */
|
case ZBUFFcs_final: /* flush into dst */
|
||||||
{ size_t const toFlush = zbc->outBuffContentSize - zbc->outBuffFlushedSize;
|
{ size_t const toFlush = zbc->outBuffContentSize - zbc->outBuffFlushedSize;
|
||||||
size_t const flushed = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outBuffFlushedSize, toFlush);
|
size_t const flushed = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outBuffFlushedSize, toFlush);
|
||||||
op += flushed;
|
op += flushed;
|
||||||
zbc->outBuffFlushedSize += flushed;
|
zbc->outBuffFlushedSize += flushed;
|
||||||
if (toFlush!=flushed) { notDone = 0; break; } /* not enough space within dst to store compressed block : stop there */
|
if (toFlush!=flushed) { notDone = 0; break; } /* dst too small to store flushed data : stop there */
|
||||||
zbc->outBuffContentSize = 0;
|
zbc->outBuffContentSize = zbc->outBuffFlushedSize = 0;
|
||||||
zbc->outBuffFlushedSize = 0;
|
if (zbc->stage==ZBUFFcs_flush) { zbc->stage = ZBUFFcs_load; break; }
|
||||||
zbc->stage = ZBUFFcs_load;
|
notDone=0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -291,19 +291,28 @@ size_t ZBUFF_compressEnd(ZBUFF_CCtx* zbc, void* dst, size_t* dstCapacityPtr)
|
|||||||
BYTE* const ostart = (BYTE*)dst;
|
BYTE* const ostart = (BYTE*)dst;
|
||||||
BYTE* const oend = ostart + *dstCapacityPtr;
|
BYTE* const oend = ostart + *dstCapacityPtr;
|
||||||
BYTE* op = ostart;
|
BYTE* op = ostart;
|
||||||
size_t outSize = *dstCapacityPtr;
|
|
||||||
size_t epilogueSize, remaining;
|
{ size_t outSize = *dstCapacityPtr;
|
||||||
ZBUFF_compressFlush(zbc, dst, &outSize); /* flush any remaining inBuff */
|
size_t const remainingToFlush = ZBUFF_compressFlush(zbc, dst, &outSize);
|
||||||
op += outSize;
|
op += outSize;
|
||||||
epilogueSize = ZSTD_compressEnd(zbc->zc, zbc->outBuff + zbc->outBuffContentSize, zbc->outBuffSize - zbc->outBuffContentSize); /* epilogue into outBuff */
|
if (remainingToFlush) {
|
||||||
zbc->outBuffContentSize += epilogueSize;
|
*dstCapacityPtr = op-ostart;
|
||||||
outSize = oend-op;
|
return remainingToFlush;
|
||||||
zbc->stage = ZBUFFcs_flush;
|
} }
|
||||||
remaining = ZBUFF_compressFlush(zbc, op, &outSize); /* attempt to flush epilogue into dst */
|
|
||||||
op += outSize;
|
if (zbc->stage == ZBUFFcs_final) { zbc->stage = ZBUFFcs_init; *dstCapacityPtr = op-ostart; return 0; }
|
||||||
if (!remaining) zbc->stage = ZBUFFcs_init; /* close only if nothing left to flush */
|
|
||||||
*dstCapacityPtr = op-ostart; /* tells how many bytes were written */
|
/* outBuff is flushed */
|
||||||
return remaining;
|
{ size_t outSize = oend-op;
|
||||||
|
size_t remainingToFlush;
|
||||||
|
zbc->outBuffContentSize = ZSTD_compressEnd(zbc->zc, zbc->outBuff, zbc->outBuffSize); /* epilogue into outBuff */
|
||||||
|
zbc->stage = ZBUFFcs_flush;
|
||||||
|
remainingToFlush = ZBUFF_compressFlush(zbc, op, &outSize);
|
||||||
|
op += outSize;
|
||||||
|
zbc->stage = remainingToFlush ? ZBUFFcs_final : ZBUFFcs_init; /* close only if nothing left to flush */
|
||||||
|
*dstCapacityPtr = op-ostart; /* how many bytes were written */
|
||||||
|
return remainingToFlush;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -427,10 +427,9 @@ static int fuzzerTests(U32 seed, U32 nbTests, unsigned startTest, double compres
|
|||||||
size_t dstBuffSize = MIN(cBufferSize - cSize, randomDstSize);
|
size_t dstBuffSize = MIN(cBufferSize - cSize, randomDstSize);
|
||||||
remainingToFlush = ZBUFF_compressEnd(zc, cBuffer+cSize, &dstBuffSize);
|
remainingToFlush = ZBUFF_compressEnd(zc, cBuffer+cSize, &dstBuffSize);
|
||||||
CHECK (ZBUFF_isError(remainingToFlush), "flush error : %s", ZBUFF_getErrorName(remainingToFlush));
|
CHECK (ZBUFF_isError(remainingToFlush), "flush error : %s", ZBUFF_getErrorName(remainingToFlush));
|
||||||
DISPLAY("flush %u bytes : still within context : %i \n", (U32)dstBuffSize, (int)remainingToFlush);
|
//DISPLAY("flush %u bytes : still within context : %i \n", (U32)dstBuffSize, (int)remainingToFlush);
|
||||||
cSize += dstBuffSize;
|
cSize += dstBuffSize;
|
||||||
}
|
} }
|
||||||
}
|
|
||||||
crcOrig = XXH64_digest(&xxhState);
|
crcOrig = XXH64_digest(&xxhState);
|
||||||
|
|
||||||
/* multi - fragments decompression test */
|
/* multi - fragments decompression test */
|
||||||
|
|||||||
Reference in New Issue
Block a user