This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] fix bug regex/9697
- From: Paolo Bonzini <bonzini at gnu dot org>
- To: Libc <libc-alpha at sourceware dot org>
- Date: Sat, 3 Jan 2009 13:35:34 +0100
- Subject: [PATCH] fix bug regex/9697
This patch fixes bug 9697, which is about wrong handling of COMPLEX_BRACKETs
in re_compile_fastmap_iter. Here is the logic I used:
- for [[.elem.]] and ranges, try at every position that might start a
multibyte collation element. Singlebyte collation elements are
taken care of by SIMPLE_BRACKETs.
- for [^...], [[:class:]], [[=elem=] try at every position that starts a
multibyte character. The correct singlebyte character positions are
also selected by the corresponding the corresponding SIMPLE_BRACKET.
- unless the second bullet is used, lead bytes of multibyte characters must
be added separately to the fastmap.
Tested on i686-pc-linux-gnu together with the other patch I sent on
2008-12-31, and on which this depends. Ok?
Paolo
2009-01-04 Paolo Bonzini <bonzini@gnu.org>
[BZ 9697]
* posix/bug-regex17.c: Add testcases.
* posix/regcomp.c (re_compile_fastmap_iter): Rewrite COMPLEX_BRACKET
handling.
---
posix/bug-regex17.c | 11 +++++++
posix/regcomp.c | 76 ++++++++++++++++++++++++++++++++-------------------
2 files changed, 59 insertions(+), 28 deletions(-)
diff --git a/posix/bug-regex17.c b/posix/bug-regex17.c
index b42f9b6..0a23870 100644
--- a/posix/bug-regex17.c
+++ b/posix/bug-regex17.c
@@ -1,5 +1,5 @@
-/* Turkish regular expression tests.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* German regular expression tests.
+ Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
@@ -45,6 +45,17 @@ struct
{ { 2, 10 }, { -1, -1 } } },
{ "[^x]\xc3\x96*\xc3\xb6$", "aB\xc3\xa4\xc3\xb6\xc3\xb6\xc3\x96", REG_ICASE, 2,
{ { 2, 10 }, { -1, -1 } } },
+
+ /* Tests for bug 9697:
+ \xc3\x9f LATIN SMALL LETTER SHARP S
+ \xcb\x9a RING ABOVE
+ \xcb\xa2 MODIFIER LETTER SMALL S */
+ { "[a-z]|[^a-z]", "\xcb\xa2", REG_EXTENDED, 2,
+ { { 0, 2 }, { -1, -1 } } },
+ { "[a-z]", "\xc3\x9f", REG_EXTENDED, 2,
+ { { 0, 2 }, { -1, -1 } } },
+ { "[^a-z]", "\xcb\x9a", REG_EXTENDED, 2,
+ { { 0, 2 }, { -1, -1 } } },
};
int
diff --git a/posix/regcomp.c b/posix/regcomp.c
index d5a0535..cb9466d 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -1,5 +1,6 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
+ Copyright (C) 2002,2003,2004,2005,2006,2007,2009
+ Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -350,47 +351,67 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
#ifdef RE_ENABLE_I18N
else if (type == COMPLEX_BRACKET)
{
- int i;
re_charset_t *cset = dfa->nodes[node].opr.mbcset;
- if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes
- || cset->nranges || cset->nchar_classes)
- {
+ int i;
+
# ifdef _LIBC
- if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0)
+ /* See if we have to try all bytes which start multiple collation
+ elements.
+ e.g. In da_DK, we want to catch 'a' since "aa" is a valid
+ collation element, and don't catch 'b' since 'b' is
+ the only collation element which starts from 'b' (and
+ it is caught by SIMPLE_BRACKET). */
+ if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0
+ && (cset->ncoll_syms || cset->nranges))
{
- /* In this case we want to catch the bytes which are
- the first byte of any collation elements.
- e.g. In da_DK, we want to catch 'a' since "aa"
- is a valid collation element, and don't catch
- 'b' since 'b' is the only collation element
- which starts from 'b'. */
const int32_t *table = (const int32_t *)
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
for (i = 0; i < SBC_MAX; ++i)
if (table[i] < 0)
re_set_fastmap (fastmap, icase, i);
}
-# else
- if (dfa->mb_cur_max > 1)
- for (i = 0; i < SBC_MAX; ++i)
- if (__btowc (i) == WEOF)
- re_set_fastmap (fastmap, icase, i);
-# endif /* not _LIBC */
- }
- for (i = 0; i < cset->nmbchars; ++i)
+# endif /* _LIBC */
+
+ /* See if we have to start the match at all multibyte characters,
+ i.e. where we would not find an invalid sequence. This only
+ applies to multibyte character sets; for single byte character
+ sets, the SIMPLE_BRACKET again suffices. */
+ if (dfa->mb_cur_max > 1
+ && (cset->nchar_classes || cset->non_match
+# ifdef _LIBC
+ || cset->nequiv_classes
+# endif /* _LIBC */
+ ))
{
- char buf[256];
- mbstate_t state;
- memset (&state, '\0', sizeof (state));
- if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
- re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
- if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+ unsigned char c = 0;
+ do
{
- if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
- != (size_t) -1)
- re_set_fastmap (fastmap, 0, *(unsigned char *) buf);
+ mbstate_t mbs;
+ memset (&mbs, 0, sizeof (mbs));
+ if (__mbrtowc (NULL, (char *) &c, 1, &mbs) == (size_t) -2)
+ re_set_fastmap (fastmap, false, (int) c);
}
+ while (++c != 0);
}
+
+ else
+ {
+ /* ... Else catch all bytes which can start the mbchars. */
+ for (i = 0; i < cset->nmbchars; ++i)
+ {
+ char buf[256];
+ mbstate_t state;
+ memset (&state, '\0', sizeof (state));
+ if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
+ re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
+ if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
+ {
+ if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
+ != (size_t) -1)
+ re_set_fastmap (fastmap, false, *(unsigned char *) buf);
+ }
+ }
+ }
}
#endif /* RE_ENABLE_I18N */
else if (type == OP_PERIOD
--
1.5.6.5