With the latest Gnulib (2cf60fe51e 2026-10-09), regexec does not find
case-insensitive matches of bracket expressions in single-byte locales
when the input character has a different case than the one in the
bracket.
Test program icase.c:
#include <config.h>
#include <locale.h>
#include <regex.h>
#include <stdio.h>
int
main (void)
{
const char *pats[] = { "[A]", "[Ab]", "A" };
setlocale (LC_ALL, "");
for (int p = 0; p < 3; p++)
{
regex_t re;
regcomp (&re, pats[p], REG_ICASE);
printf ("%s->", pats[p]);
for (const char *c = "aAbB"; *c; c++)
{
char s[2] = { *c, 0 };
if (regexec (&re, s, 0, NULL, 0) == 0)
putchar (*c);
}
printf (" ");
regfree (&re);
}
printf ("\n");
return 0;
}
Output:
$ LC_ALL=C ./icase
[A]->A [Ab]->AB A->aA
$ LC_ALL=en_US.ISO-8859-15 ./icase
[A]->A [Ab]->AB A->aA
$ LC_ALL=C.UTF-8 ./icase
[A]->aA [Ab]->aAbB A->aA
Expected in all locales: [A]->aA [Ab]->aAbB A->aA.
I attach a suggestion for a fix.
Cheers,
Arno
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -345,7 +345,11 @@
bitset_word_t w = dfa->nodes[node].opr.sbcset[i];
for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
if (w & ((bitset_word_t) 1 << j))
- re_set_fastmap (fastmap, ch);
+ {
+ re_set_fastmap (fastmap, ch);
+ if (bufp->syntax & RE_ICASE)
+ re_set_fastmap (fastmap, tolower (ch));
+ }
}
}
else if (type == COMPLEX_BRACKET)