Oh, many thanks for the quick fix and explanation!  The problem is quite
a bit more complicated than I thought.

Your extended patch works on all of my test cases.  However, I noticed a
slow-down because of the new SIMPLE_BRACKET code, which adds case
counterparts to the fastmap.  In your code, this happens even without
RE_ICASE.  This is different from the CHARACTER branch.

I think that's unnecessary.  I attach a patch on top of your fixes,
checking for RE_ICASE.
>From d366957d5b957a27f8aefe9fc5d6c2013852b821 Mon Sep 17 00:00:00 2001
From: Arno Onken <[email protected]>
Date: Mon, 12 Oct 2026 12:00:00 +0100
Subject: [PATCH] regex: fold case in bracket fastmap only if RE_ICASE

* lib/regcomp.c (re_compile_fastmap_iter): For SIMPLE_BRACKET, set
fastmap for case folded counterparts only if RE_ICASE.
* tests/test-regex-el.c (main): Make sure that the fastmap of a
bracket expression does not include the case folded counterparts
without RE_ICASE.
---
 ChangeLog             |  9 +++++++++
 lib/regcomp.c         | 11 +++++++----
 tests/test-regex-el.c | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index be2fcbefc5..0a41f0dc97 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2026-10-12  Arno Onken  <[email protected]>
+
+	regex: fold case in bracket fastmap only if RE_ICASE
+	* lib/regcomp.c (re_compile_fastmap_iter): For SIMPLE_BRACKET, set
+	fastmap for case folded counterparts only if RE_ICASE.
+	* tests/test-regex-el.c (main): Make sure that the fastmap of a
+	bracket expression does not include the case folded counterparts
+	without RE_ICASE.
+
 2026-10-11  Paul Eggert  <[email protected]>
 
 	localeinfo: improve comments
diff --git a/lib/regcomp.c b/lib/regcomp.c
index 89e16bcaef..5cd18a7639 100644
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -347,10 +347,13 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
 		if (w & ((bitset_word_t) 1 << j))
 		  {
 		    re_set_fastmap (fastmap, ch);
-		    wchar_t wc;
-		    mbstate_t state = {0};
-		    if (__mbrtowc (&wc, (char *) &ch, 1, &state) == 1)
-		      re_set_fastmap_icase (fastmap, wc, &state);
+		    if (bufp->syntax & RE_ICASE)
+		      {
+			wchar_t wc;
+			mbstate_t state = {0};
+			if (__mbrtowc (&wc, (char *) &ch, 1, &state) == 1)
+			  re_set_fastmap_icase (fastmap, wc, &state);
+		      }
 		  }
 	    }
 	}
diff --git a/tests/test-regex-el.c b/tests/test-regex-el.c
index 1e2589a3b2..9b6032e963 100644
--- a/tests/test-regex-el.c
+++ b/tests/test-regex-el.c
@@ -120,5 +120,39 @@ main ()
           regfree (&regex);
         }
 
+  for (int i = 0; i < 3; i++)
+    {
+      static char const str[3][2] = { "\xd3", "\xf2", "\xf3" };
+      char pat[4];
+      int patlen = sprintf (pat, "[%s]", str[i]);
+      re_set_syntax (0);
+      memset (&regex, 0, sizeof regex);
+      regex.fastmap = malloc (UCHAR_MAX + 1);
+      if (!regex.fastmap)
+        {
+          report_error ("malloc failed");
+          continue;
+        }
+      s = re_compile_pattern (pat, patlen, &regex);
+      if (s)
+        {
+          report_error ("re_compile_pattern [\\x%02x] failed: %s",
+                        (unsigned char) str[i][0], s);
+          continue;
+        }
+      if (re_compile_fastmap (&regex) != 0)
+        report_error ("re_compile_fastmap [\\x%02x] failed",
+                      (unsigned char) str[i][0]);
+      else
+        for (int j = 0; j < 3; j++)
+          if (!regex.fastmap[(unsigned char) str[j][0]] != (i != j))
+            report_error ("fastmap mismatch: pattern = [\\x%02x],"
+                          " byte = \\x%02x, fastmap = %d",
+                          (unsigned char) str[i][0],
+                          (unsigned char) str[j][0],
+                          regex.fastmap[(unsigned char) str[j][0]]);
+      regfree (&regex);
+    }
+
   return exit_status;
 }
-- 
2.51.0

Reply via email to