Skip to content

Harden PCRE2 JIT allocator wrappers against NULL allocator_data and zero-size allocation#908

Open
orbisai0security wants to merge 2 commits intoPCRE2Project:mainfrom
orbisai0security:harden-jit-allocator-wrappers
Open

Harden PCRE2 JIT allocator wrappers against NULL allocator_data and zero-size allocation#908
orbisai0security wants to merge 2 commits intoPCRE2Project:mainfrom
orbisai0security:harden-jit-allocator-wrappers

Conversation

@orbisai0security
Copy link
Copy Markdown

While reviewing src/pcre2_jit_compile.c, I noticed that the SLJIT allocator wrapper functions assume allocator_data is always a valid pcre2_memctl*.

This patch proposes a small defensive hardening change:

  • Return NULL from pcre2_jit_malloc() if allocator_data == NULL or size == 0
  • Return early from pcre2_jit_free() if allocator_data == NULL or ptr == NULL

This is not intended to claim a confirmed exploitable vulnerability by itself. It is a robustness improvement to avoid potential NULL dereference or undefined behavior if these wrappers are ever called with invalid allocator context.

If this is acceptable upstream, downstream projects such as Notepad3 can pick it up through their normal PCRE2 vendor update process.

🤖 Generated with Claude Code

Add defensive NULL/zero-size guards to pcre2_jit_malloc() and
pcre2_jit_free() to avoid potential NULL pointer dereference if
these SLJIT allocator callbacks are ever invoked with invalid
allocator context.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@zherczeg
Copy link
Copy Markdown
Collaborator

zherczeg commented May 8, 2026

Thank you for reviewing the jit compiler. Could you trigger the NULL allocator in some way? As far as i remember there is a default allocator which is used when no allocator is passed to PCRE2. So the allocator pointer cannot be NULL. The if statement could be replaced with an ASSERT, since size must be > 0 as well.

@orbisai0security
Copy link
Copy Markdown
Author

Thanks, that makes sense. I don’t currently have a concrete trigger showing allocator_data == NULL through the public PCRE2 API. My concern was based on the wrapper contract rather than a proven reachable path.

Given your point that PCRE2 always supplies a default allocator and that size should also be non-zero, I agree this should not be treated as a security vulnerability.

Would you prefer this PR to be changed to debug assertions documenting those invariants instead, e.g. asserting allocator_data != NULL, size > 0 in pcre2_jit_malloc(), and allocator_data != NULL in pcre2_jit_free()?

@zherczeg
Copy link
Copy Markdown
Collaborator

zherczeg commented May 8, 2026

Yes, asserts are good.

This code ensures that the context always has a malloc/free:
https://github.com/PCRE2Project/pcre2/blob/main/src/pcre2_context.c#L111

The allocator comes from the regex: void *allocator_data = &re->memctl;
https://github.com/PCRE2Project/pcre2/blob/main/src/pcre2_jit_compile.c#L13536

Address review feedback: since PCRE2 always supplies a valid allocator
via pcre2_context_create() and allocator_data points to &re->memctl,
use assertions to document these invariants rather than defensive
runtime checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread src/pcre2_jit_compile.c
pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);
if (!allocator || size == 0) return NULL;
SLJIT_ASSERT(allocator != NULL);
SLJIT_ASSERT(size > 0);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a single assert with && is enough.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants