Skip to content

Record customMem before the pool's first failure point - #4859

Open
Huang-404-Q wants to merge 1 commit into
meta:devfrom
Huang-404-Q:fix/pool-custommem-before-init
Open

Huang-404-Q wants to merge 1 commit into
meta:devfrom
Huang-404-Q:fix/pool-custommem-before-init

Conversation

@Huang-404-Q

Copy link
Copy Markdown

Problem

POOL_create_advanced assigns ctx->customMem only after the queue has been allocated and its mutex/cond initialized, but the init failure path runs earlier:

ctx = ZSTD_customCalloc(sizeof(POOL_ctx), customMem);   /* zero-initialized */
...
if (error) { POOL_free(ctx); return NULL; }             /* customMem is still empty here */
...
ctx->customMem = customMem;                             /* too late */

ZSTD_customCalloc memsets the context, so POOL_free(ctx) sees an empty allocator and calls the default free() on memory that came from the caller's customAlloc. With a custom allocator that is not malloc-compatible this is undefined behavior; with a counting allocator the allocation is never returned through customFree.

Fix

Assign customMem immediately after the allocation that produces the context, before anything can fail.

Verification

Built lib/common/pool.c on Linux with a wrapper that makes the second pthread_cond_init return ENOMEM, and counted allocations through a ZSTD_customMem:

# before
allocs=2 custom_frees=0
MISMATCH: 2 allocations, 0 custom frees -> default free() used

# after
allocs=2 custom_frees=2
OK

Reproducer: gcc -O0 -DZSTD_MULTITHREAD -I lib -I lib/common -Wl,--wrap=pthread_cond_init repro.c lib/common/threading.c -lpthread

This only reproduces on POSIX: the Windows build maps these init calls to InitializeCriticalSection/InitializeConditionVariable and always returns 0.

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.
@meta-cla

meta-cla Bot commented Oct 22, 2026

Copy link
Copy Markdown

Hi @Huang-404-Q!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla meta-cla Bot added the CLA Signed label Oct 22, 2026
@meta-cla

meta-cla Bot commented Oct 22, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant