Thanks, I reviewed the changes to posix/regcomp.c, posix/regex_internal.c, and
posix/regexec.c and they all look good. I did not review the test case.
I propagated those fixes into Gnulib by installing the attached patches. In
hindsight I should have merged them into one Gnulib patch but two patches
suffice.
From 9277ec4eaac372c9b887d9af6686d96fbab1e5e1 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Wed, 11 Nov 2026 16:41:07 -0800
Subject: [PATCH 1/2] regex: fix double-frees
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Problem and fix reported by Adhemerval Zanella in:
https://sourceware.org/pipermail/libc-alpha/2026-November/182054.html
* lib/regcomp.c (build_range_exp):
* lib/regexec.c (match_ctx_add_entry):
Don’t free storage twice if an allocation fails.
---
ChangeLog | 9 +++++++++
lib/regcomp.c | 6 ++++--
lib/regexec.c | 5 +----
3 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index b19fd11383..6c76c1df20 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2026-11-11 Paul Eggert <[email protected]>
+
+ regex: fix double-frees
+ Problem and fix reported by Adhemerval Zanella in:
+ https://sourceware.org/pipermail/libc-alpha/2026-November/182054.html
+ * lib/regcomp.c (build_range_exp):
+ * lib/regexec.c (match_ctx_add_entry):
+ Don’t free storage twice if an allocation fails.
+
2026-11-11 Collin Funk <[email protected]>
selinux-at: Define functions that don't perform context translation.
diff --git a/lib/regcomp.c b/lib/regcomp.c
index e3af96f4c8..c9bb0555a5 100644
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -2960,15 +2960,17 @@ build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc,
new_nranges = 2 * mbcset->nranges + 1;
new_array_start = re_realloc (mbcset->range_starts, uint32_t,
new_nranges);
+ if (new_array_start != NULL)
+ mbcset->range_starts = new_array_start;
new_array_end = re_realloc (mbcset->range_ends, uint32_t,
new_nranges);
+ if (new_array_end != NULL)
+ mbcset->range_ends = new_array_end;
if (__glibc_unlikely (new_array_start == NULL
|| new_array_end == NULL))
return REG_ESPACE;
- mbcset->range_starts = new_array_start;
- mbcset->range_ends = new_array_end;
*range_alloc = new_nranges;
}
diff --git a/lib/regexec.c b/lib/regexec.c
index 370e71cceb..def8202d14 100644
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -4179,10 +4179,7 @@ match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from,
new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry,
mctx->abkref_ents * 2);
if (__glibc_unlikely (new_entry == NULL))
- {
- re_free (mctx->bkref_ents);
- return REG_ESPACE;
- }
+ return REG_ESPACE;
mctx->bkref_ents = new_entry;
memset (mctx->bkref_ents + mctx->nbkref_ents, '\0',
sizeof (struct re_backref_cache_entry) * mctx->abkref_ents);
--
2.56.0
From 02eb8274389a58565fb83ef7365f56a1a609456b Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Wed, 11 Nov 2026 17:01:26 -0800
Subject: [PATCH 2/2] regex: fix another build_range_exp double-free
* lib/regcomp.c (build_range_exp): Fix another double free.
---
lib/regcomp.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/lib/regcomp.c b/lib/regcomp.c
index c9bb0555a5..59a5e4ead9 100644
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -2744,19 +2744,17 @@ build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc,
are NULL if *range_alloc == 0. */
new_array_start = re_realloc (mbcset->range_starts, wchar_t,
new_nranges);
+ if (new_array_start != NULL)
+ mbcset->range_starts = new_array_start;
new_array_end = re_realloc (mbcset->range_ends, wchar_t,
new_nranges);
+ if (new_array_end != NULL)
+ mbcset->range_ends = new_array_end;
if (__glibc_unlikely (new_array_start == NULL
|| new_array_end == NULL))
- {
- re_free (new_array_start);
- re_free (new_array_end);
- return REG_ESPACE;
- }
-
- mbcset->range_starts = new_array_start;
- mbcset->range_ends = new_array_end;
+ return REG_ESPACE;
+
*range_alloc = new_nranges;
}
--
2.56.0