This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]