From 9323f44ba7a164c75d2c3ec20bc9ae5bb35b4576 Mon Sep 17 00:00:00 2001 From: huang <13165998033@163.com> Date: Thu, 22 Oct 2026 14:35:07 +0800 Subject: [PATCH] Record customMem before the pool's first failure point POOL_create_advanced assigns ctx->customMem only after allocating and initializing the queue, but the mutex/cond init failure path calls POOL_free() before that. ctx comes from ZSTD_customCalloc, which zeroes it, so POOL_free saw an empty allocator and released custom-allocated memory with the default free(). Assign the allocator immediately after the context allocation. --- lib/common/pool.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/common/pool.c b/lib/common/pool.c index dd5fb0c4d4b..11a1fbc064d 100644 --- a/lib/common/pool.c +++ b/lib/common/pool.c @@ -121,6 +121,9 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, /* Allocate the context and zero initialize */ ctx = (POOL_ctx*)ZSTD_customCalloc(sizeof(POOL_ctx), customMem); if (!ctx) { return NULL; } + /* Record the allocator before anything can fail: POOL_free() needs it to release the + * allocations below with the same allocator that produced them. */ + ctx->customMem = customMem; /* Initialize the job queue. * It needs one extra space since one space is wasted to differentiate * empty and full queues. @@ -143,7 +146,6 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ctx->threads = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), customMem); ctx->threadCapacity = 0; ctx->threadLimit = numThreads; - ctx->customMem = customMem; /* Check for errors */ if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; } /* Initialize the threads */