Add ZSTD_d_maxBlockSize parameter
Reduces memory when blocks are guaranteed to be smaller than allowed by the format. This is useful for streaming compression in conjunction with ZSTD_c_maxBlockSize. This PR saves 2 * (formatMaxBlockSize - paramMaxBlockSize) when streaming. Once it is rebased on top of PR #3616 it will save 3 * (formatMaxBlockSize - paramMaxBlockSize).
This commit is contained in:
committed by
Nick Terrell
parent
ed313342f1
commit
61efb2a047
@@ -90,6 +90,9 @@ static size_t roundTripTest(void *result, size_t resultCapacity,
|
||||
FUZZ_ASSERT(XXH64(compressed, cSize, 0) == hash0);
|
||||
}
|
||||
}
|
||||
if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) {
|
||||
FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, maxBlockSize));
|
||||
}
|
||||
dSize = ZSTD_decompressDCtx(dctx, result, resultCapacity, compressed, cSize);
|
||||
FUZZ_ZASSERT(dSize);
|
||||
FUZZ_ASSERT_MSG(dSize == srcSize, "Incorrect regenerated size");
|
||||
|
||||
@@ -63,6 +63,8 @@ static size_t compress(uint8_t *dst, size_t capacity,
|
||||
size_t dstSize = 0;
|
||||
ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);
|
||||
FUZZ_setRandomParameters(cctx, srcSize, producer);
|
||||
int maxBlockSize;
|
||||
FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_maxBlockSize, &maxBlockSize));
|
||||
|
||||
while (srcSize > 0) {
|
||||
ZSTD_inBuffer in = makeInBuffer(&src, &srcSize, producer);
|
||||
@@ -93,6 +95,8 @@ static size_t compress(uint8_t *dst, size_t capacity,
|
||||
if (FUZZ_dataProducer_uint32Range(producer, 0, 7) == 0) {
|
||||
size_t const remaining = in.size - in.pos;
|
||||
FUZZ_setRandomParameters(cctx, remaining, producer);
|
||||
/* Always use the same maxBlockSize */
|
||||
FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, maxBlockSize));
|
||||
}
|
||||
mode = -1;
|
||||
}
|
||||
@@ -132,6 +136,23 @@ static size_t compress(uint8_t *dst, size_t capacity,
|
||||
return dstSize;
|
||||
}
|
||||
|
||||
size_t decompress(void* dst, size_t dstCapacity, void const* src, size_t srcSize, FUZZ_dataProducer_t* producer)
|
||||
{
|
||||
ZSTD_inBuffer in = {src, srcSize, 0};
|
||||
ZSTD_outBuffer out = {dst, dstCapacity, 0};
|
||||
int maxBlockSize;
|
||||
FUZZ_ZASSERT(ZSTD_CCtx_getParameter(cctx, ZSTD_c_maxBlockSize, &maxBlockSize));
|
||||
if (FUZZ_dataProducer_uint32Range(producer, 0, 1)) {
|
||||
FUZZ_ZASSERT(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, maxBlockSize));
|
||||
}
|
||||
while (in.pos < in.size) {
|
||||
size_t const ret = ZSTD_decompressStream(dctx, &out, &in);
|
||||
FUZZ_ZASSERT(ret);
|
||||
FUZZ_ASSERT(ret == 0);
|
||||
}
|
||||
return out.pos;
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
{
|
||||
FUZZ_SEQ_PROD_SETUP();
|
||||
@@ -163,8 +184,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
|
||||
|
||||
{
|
||||
size_t const cSize = compress(cBuf, neededBufSize, src, size, producer);
|
||||
size_t const rSize =
|
||||
ZSTD_decompressDCtx(dctx, rBuf, neededBufSize, cBuf, cSize);
|
||||
size_t const rSize = decompress(rBuf, neededBufSize, cBuf, cSize, producer);
|
||||
FUZZ_ZASSERT(rSize);
|
||||
FUZZ_ASSERT_MSG(rSize == size, "Incorrect regenerated size");
|
||||
FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!");
|
||||
|
||||
@@ -952,6 +952,25 @@ static int basicUnitTests(U32 const seed, double compressibility)
|
||||
ZSTD_freeCDict(cdict);
|
||||
ZSTD_freeCCtx(cctx);
|
||||
}
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : maxBlockSize = 2K", testNb++);
|
||||
{
|
||||
ZSTD_CCtx* cctx = ZSTD_createCCtx();
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 2048));
|
||||
CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 2048));
|
||||
|
||||
cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBuffSize);
|
||||
CHECK_Z(cSize);
|
||||
CHECK_Z(ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize));
|
||||
|
||||
CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 1024));
|
||||
CHECK(ZSTD_isError(ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize)));
|
||||
|
||||
ZSTD_freeDCtx(dctx);
|
||||
ZSTD_freeCCtx(cctx);
|
||||
}
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : ldm fill dict out-of-bounds check", testNb++);
|
||||
{
|
||||
|
||||
@@ -722,6 +722,67 @@ static int basicUnitTests(U32 seed, double compressibility, int bigTests)
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
DISPLAYLEVEL(3, "test%3i : maxBlockSize = 2KB : ", testNb++);
|
||||
{
|
||||
ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||
size_t singlePassSize, streamingSize, streaming2KSize;
|
||||
|
||||
{
|
||||
ZSTD_CCtx* cctx = ZSTD_createCCtx();
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 18));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, 0));
|
||||
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_maxBlockSize, 2048));
|
||||
cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize);
|
||||
CHECK_Z(cSize);
|
||||
ZSTD_freeCCtx(cctx);
|
||||
}
|
||||
|
||||
CHECK_Z(ZSTD_decompressDCtx(dctx, decodedBuffer, CNBufferSize, compressedBuffer, cSize));
|
||||
singlePassSize = ZSTD_sizeof_DCtx(dctx);
|
||||
CHECK_Z(singlePassSize);
|
||||
|
||||
inBuff.src = compressedBuffer;
|
||||
inBuff.size = cSize;
|
||||
|
||||
outBuff.dst = decodedBuffer;
|
||||
outBuff.size = decodedBufferSize;
|
||||
|
||||
CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 2048));
|
||||
inBuff.pos = 0;
|
||||
outBuff.pos = 0;
|
||||
{
|
||||
size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);
|
||||
CHECK_Z(r);
|
||||
CHECK(r != 0, "Entire frame must be decompressed");
|
||||
}
|
||||
streaming2KSize = ZSTD_sizeof_DCtx(dctx);
|
||||
CHECK_Z(streaming2KSize);
|
||||
|
||||
CHECK_Z(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_and_parameters));
|
||||
inBuff.pos = 0;
|
||||
outBuff.pos = 0;
|
||||
{
|
||||
size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);
|
||||
CHECK_Z(r);
|
||||
CHECK(r != 0, "Entire frame must be decompressed");
|
||||
}
|
||||
streamingSize = ZSTD_sizeof_DCtx(dctx);
|
||||
CHECK_Z(streamingSize);
|
||||
|
||||
CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_maxBlockSize, 1024));
|
||||
inBuff.pos = 0;
|
||||
outBuff.pos = 0;
|
||||
CHECK(!ZSTD_isError(ZSTD_decompressStream(dctx, &outBuff, &inBuff)), "decompression must fail");
|
||||
|
||||
CHECK(streamingSize < singlePassSize + (1 << 18) + 3 * ZSTD_BLOCKSIZE_MAX, "Streaming doesn't use the right amount of memory");
|
||||
CHECK(streamingSize != streaming2KSize + 3 * (ZSTD_BLOCKSIZE_MAX - 2048), "ZSTD_d_blockSizeMax didn't save the right amount of memory");
|
||||
DISPLAYLEVEL(3, "| %zu | %zu | %zu | ", singlePassSize, streaming2KSize, streamingSize);
|
||||
|
||||
ZSTD_freeDCtx(dctx);
|
||||
}
|
||||
DISPLAYLEVEL(3, "OK \n");
|
||||
|
||||
/* Decompression with ZSTD_d_stableOutBuffer */
|
||||
cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize, 1);
|
||||
CHECK_Z(cSize);
|
||||
@@ -2845,6 +2906,13 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
|
||||
if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_forceMaxWindow, FUZ_rand(&lseed) & 1, opaqueAPI) );
|
||||
if (FUZ_rand(&lseed) & 1) CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_deterministicRefPrefix, FUZ_rand(&lseed) & 1, opaqueAPI) );
|
||||
|
||||
/* Set max block size parameters */
|
||||
if (FUZ_rand(&lseed) & 1) {
|
||||
int maxBlockSize = (int)(FUZ_rand(&lseed) % ZSTD_BLOCKSIZE_MAX);
|
||||
maxBlockSize = MAX(1024, maxBlockSize);
|
||||
CHECK_Z( setCCtxParameter(zc, cctxParams, ZSTD_c_maxBlockSize, maxBlockSize, opaqueAPI) );
|
||||
}
|
||||
|
||||
/* Apply parameters */
|
||||
if (opaqueAPI) {
|
||||
DISPLAYLEVEL(5, "t%u: applying CCtxParams \n", testNb);
|
||||
@@ -2976,6 +3044,13 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
|
||||
if (FUZ_rand(&lseed) & 1) {
|
||||
CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_disableHuffmanAssembly, FUZ_rand(&lseed) & 1));
|
||||
}
|
||||
if (FUZ_rand(&lseed) & 1) {
|
||||
int maxBlockSize;
|
||||
CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_maxBlockSize, &maxBlockSize));
|
||||
CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_maxBlockSize, maxBlockSize));
|
||||
} else {
|
||||
CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_maxBlockSize, 0));
|
||||
}
|
||||
{ size_t decompressionResult = 1;
|
||||
ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
|
||||
ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };
|
||||
|
||||
Reference in New Issue
Block a user