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 (®ex); } + 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 (®ex, 0, sizeof regex); + regex.fastmap = malloc (UCHAR_MAX + 1); + if (!regex.fastmap) + { + report_error ("malloc failed"); + continue; + } + s = re_compile_pattern (pat, patlen, ®ex); + if (s) + { + report_error ("re_compile_pattern [\\x%02x] failed: %s", + (unsigned char) str[i][0], s); + continue; + } + if (re_compile_fastmap (®ex) != 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 (®ex); + } + return exit_status; } -- 2.51.0
