From cef5a5611a3792cf9eaab5826f48e92c7c287f0a Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Tue, 17 Mar 2026 13:08:14 -0700 Subject: [PATCH] Fix unintended high memory usage --- lib/compress/zstd_ldm.c | 6 +++++- tests/fuzzer.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/compress/zstd_ldm.c b/lib/compress/zstd_ldm.c index 070551cad..7bf36cd86 100644 --- a/lib/compress/zstd_ldm.c +++ b/lib/compress/zstd_ldm.c @@ -152,7 +152,11 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, } } if (params->hashLog == 0) { - params->hashLog = BOUNDED(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog, ZSTD_HASHLOG_MAX); + if (params->windowLog <= params->hashRateLog) { + params->hashLog = ZSTD_HASHLOG_MIN; + } else { + params->hashLog = BOUNDED(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog, ZSTD_HASHLOG_MAX); + } } if (params->minMatchLength == 0) { params->minMatchLength = LDM_MIN_MATCH_LENGTH; diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 472f8c8b3..7b7c9d666 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -1414,6 +1414,37 @@ static int basicUnitTests(U32 const seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : ldm hashRateLog > windowLog underflow check : ", testNb++); + { + /* Test that when windowLog < hashRateLog, we don't get excessive memory usage + * due to underflow in hashLog calculation (windowLog - hashRateLog). */ + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + + size_t const size = (1U << 10); // 1 KB + size_t const dstCapacity = ZSTD_compressBound(size); + void* src = (void*)malloc(size); + void* dst = (void*)malloc(dstCapacity); + + RDG_genBuffer(src, size, 0.5, 0.5, seed); + + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_enableLongDistanceMatching, ZSTD_ps_enable)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashLog, 0)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, 12)); + CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_ldmHashRateLog, 13)); + + CHECK_Z(ZSTD_compress2(cctx, dst, dstCapacity, src, size)); + + { size_t const cctxSize = ZSTD_sizeof_CCtx(cctx); + DISPLAYLEVEL(3, "CCtx size: %u bytes ", (unsigned)cctxSize); + CHECK_LT(cctxSize, 50 MB); + } + + ZSTD_freeCCtx(cctx); + free(src); + free(dst); + } + DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : testing dict compression with enableLdm and forceMaxWindow : ", testNb++); { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); -- 2.47.3