From df3927c78c465c9d9b363144219feffb9ad5cf91 Mon Sep 17 00:00:00 2001 From: Felipe Zipitria Date: Tue, 13 Oct 2026 09:18:48 -0300 Subject: [PATCH] fix: register the regex pool cleanup right after a successful compile msc_pregcomp_ex registered msc_pcre_cleanup only at the very end, so on the failure paths between the compile and the return (the match context allocation with PCRE2, the pcre_extra allocation with legacy PCRE) the function returned NULL and the compiled pattern was never freed. The cleanup is now registered as soon as the compile succeeds; it already tolerates a NULL match context / pcre_extra. Fixes #2407 Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_0181jBv5JdNQviwDzfnkf1Gy --- apache2/msc_pcre.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/apache2/msc_pcre.c b/apache2/msc_pcre.c index edaac3ff8f..4f368b1ed5 100644 --- a/apache2/msc_pcre.c +++ b/apache2/msc_pcre.c @@ -88,12 +88,17 @@ void *msc_pregcomp_ex(apr_pool_t *pool, const char *pattern, int options, return NULL; } + /* Register the cleanup as soon as there is something to free, so the + * compiled pattern is released even if a later step fails (#2407). */ + regex->match_context = NULL; + apr_pool_cleanup_register(pool, (void *)regex, + (apr_status_t (*)(void *))msc_pcre_cleanup, apr_pool_cleanup_null); + #ifdef WITH_PCRE_JIT regex->jit_compile_rc = pcre2_jit_compile(regex->re, PCRE2_JIT_COMPLETE); #endif /* Setup the pcre2 match context */ - regex->match_context = NULL; match_context = pcre2_match_context_create(NULL); if (match_context == NULL) { return NULL; @@ -131,9 +136,6 @@ void *msc_pregcomp_ex(apr_pool_t *pool, const char *pattern, int options, regex->match_context = match_context; - apr_pool_cleanup_register(pool, (void *)regex, - (apr_status_t (*)(void *))msc_pcre_cleanup, apr_pool_cleanup_null); - return regex; } #else /* not WITH_PCRE2 */ @@ -154,6 +156,10 @@ void *msc_pregcomp_ex(apr_pool_t *pool, const char *pattern, int options, } if (regex->re == NULL) return NULL; + /* Register the cleanup as soon as there is something to free (#2407). */ + apr_pool_cleanup_register(pool, (void *)regex, + (apr_status_t (*)(void *))msc_pcre_cleanup, apr_pool_cleanup_null); + #ifdef WITH_PCRE_STUDY #ifdef WITH_PCRE_JIT pe = pcre_study(regex->re, PCRE_STUDY_JIT_COMPILE, &errptr); @@ -211,9 +217,6 @@ void *msc_pregcomp_ex(apr_pool_t *pool, const char *pattern, int options, regex->pe = pe; - apr_pool_cleanup_register(pool, (void *)regex, - (apr_status_t (*)(void *))msc_pcre_cleanup, apr_pool_cleanup_null); - return regex; } #endif /* WITH_PCRE2 */