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

Reply via email to