changeset 6186:7a0537a5ad1b

* lib/regex_internal.c (re_string_reconstruct): Don't assume buffer lengths fit in regoff_t; this isn't true if regoff_t is the same width as size_t. * lib/regex.c (re_search_internal): 5th arg is LAST_START (= START + RANGE) instead of RANGE. This avoids overflow problems when regoff_t is the same width as size_t. All callers changed. (re_search_2_stub): Check for overflow when adding the sizes of the two strings. (re_search_stub): Check for overflow when adding START to RANGE; if it occurs, substitute the extreme value. * config/srclist.txt: Add glibc bug 1284.
author Paul Eggert <eggert@cs.ucla.edu>
date Thu, 01 Sep 2005 07:03:01 +0000
parents 6b09f7f6ba73
children 6fb0d3a30d33
files config/ChangeLog config/srclist.txt lib/ChangeLog lib/regex_internal.c lib/regexec.c
diffstat 5 files changed, 61 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,6 +1,6 @@
 2005-08-31  Paul Eggert  <eggert@cs.ucla.edu>
 
-	* srclist.txt: Add glibc bugs 1273, 1278-1282.
+	* srclist.txt: Add glibc bugs 1273, 1278-1282, 1284.
 
 2005-08-25  Paul Eggert  <eggert@cs.ucla.edu>
 
--- a/config/srclist.txt
+++ b/config/srclist.txt
@@ -1,4 +1,4 @@
-# $Id: srclist.txt,v 1.94 2005-08-31 23:36:43 eggert Exp $
+# $Id: srclist.txt,v 1.95 2005-09-01 07:03:01 eggert Exp $
 # Files for which we are not the source.  See ./srclistvars.sh for the
 # variable definitions.
 
@@ -132,6 +132,7 @@
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1248
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1281
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1282
+# http://sources.redhat.com/bugzilla/show_bug.cgi?id=1284
 #$LIBCSRC/posix/regex_internal.c		lib gpl
 #
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1054
@@ -158,6 +159,7 @@
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1280
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1281
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1282
+# http://sources.redhat.com/bugzilla/show_bug.cgi?id=1284
 #$LIBCSRC/posix/regexec.c		lib gpl
 #
 # c89 changes $LIBCSRC/string/strdup.c		lib gpl
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,17 @@
+2005-08-31  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* regex_internal.c (re_string_reconstruct): Don't assume buffer
+	lengths fit in regoff_t; this isn't true if regoff_t is the same
+	width as size_t.
+	* regex.c (re_search_internal): 5th arg is LAST_START
+	(= START + RANGE) instead of RANGE.  This avoids overflow
+	problems when regoff_t is the same width as size_t.
+	All callers changed.
+	(re_search_2_stub): Check for overflow when adding the
+	sizes of the two strings.
+	(re_search_stub): Check for overflow when adding START
+	to RANGE; if it occurs, substitute the extreme value.
+
 2005-08-31  Jim Meyering  <jim@meyering.net>
 
 	* regcomp.c (search_duplicated_node): Make first pointer arg
--- a/lib/regex_internal.c
+++ b/lib/regex_internal.c
@@ -557,8 +557,11 @@
 internal_function
 re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags)
 {
-  regoff_t offset = (regoff_t) idx - (regoff_t) pstr->raw_mbs_idx;
-  if (BE (offset < 0, 0))
+  Idx offset;
+
+  if (BE (pstr->raw_mbs_idx <= idx, 0))
+    offset = idx - pstr->raw_mbs_idx;
+  else
     {
       /* Reset buffer.  */
 #ifdef RE_ENABLE_I18N
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -37,7 +37,7 @@
      internal_function;
 static reg_errcode_t re_search_internal (const regex_t *preg,
 					 const char *string, Idx length,
-					 Idx start, regoff_t range, Idx stop,
+					 Idx start, Idx last_start, Idx stop,
 					 size_t nmatch, regmatch_t pmatch[],
 					 int eflags) internal_function;
 static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp,
@@ -221,10 +221,10 @@
 
   __libc_lock_lock (dfa->lock);
   if (preg->re_no_sub)
-    err = re_search_internal (preg, string, length, start, length - start,
+    err = re_search_internal (preg, string, length, start, length,
 			      length, 0, NULL, eflags);
   else
-    err = re_search_internal (preg, string, length, start, length - start,
+    err = re_search_internal (preg, string, length, start, length,
 			      length, nmatch, pmatch, eflags);
   __libc_lock_unlock (dfa->lock);
   return err != REG_NOERROR;
@@ -338,7 +338,7 @@
   Idx len = length1 + length2;
   int free_str = 0;
 
-  if (BE (length1 < 0 || length2 < 0 || stop < 0, 0))
+  if (BE (length1 < 0 || length2 < 0 || stop < 0 || len < length1, 0))
     return -2;
 
   /* Concatenate the strings.  */
@@ -386,6 +386,7 @@
 #ifdef _LIBC
   re_dfa_t *dfa = (re_dfa_t *) bufp->re_buffer;
 #endif
+  Idx last_start = start + range;
 
   /* Check for out-of-range.  */
   if (BE (start < 0 || start > length, 0))
@@ -395,16 +396,25 @@
       regoff_t length_offset = length;
       regoff_t start_offset = start;
       if (BE (length_offset - start_offset < range, 0))
-	range = length_offset - start_offset;
+	last_start = length;
       else if (BE (range < - start_offset, 0))
-	range = -start_offset;
+	last_start = 0;
     }
   else
     {
-      if (BE (start + range > length, 0))
-	range = length - start;
-      else if (BE (start + range < 0, 0))
-	range = -start;
+      if (BE ((last_start < start) != (range < 0), 0))
+	{
+	  /* Overflow occurred when computing last_start; substitute
+	     the extreme value.  */
+	  last_start = range < 0 ? 0 : length;
+	}
+      else
+	{
+	  if (BE (length < last_start, 0))
+	    last_start = length;
+	  else if (BE (last_start < 0, 0))
+	    last_start = 0;
+	}
     }
 
   __libc_lock_lock (dfa->lock);
@@ -413,7 +423,8 @@
   eflags |= (bufp->re_not_eol) ? REG_NOTEOL : 0;
 
   /* Compile fastmap if we haven't yet.  */
-  if (range > 0 && bufp->re_fastmap != NULL && !bufp->re_fastmap_accurate)
+  if (start < last_start && bufp->re_fastmap != NULL
+      && !bufp->re_fastmap_accurate)
     re_compile_fastmap (bufp);
 
   if (BE (bufp->re_no_sub, 0))
@@ -442,7 +453,7 @@
       goto out;
     }
 
-  result = re_search_internal (bufp, string, length, start, range, stop,
+  result = re_search_internal (bufp, string, length, start, last_start, stop,
 			       nregs, pmatch, eflags);
 
   rval = 0;
@@ -584,18 +595,18 @@
 
 /* Searches for a compiled pattern PREG in the string STRING, whose
    length is LENGTH.  NMATCH, PMATCH, and EFLAGS have the same
-   mingings with regexec.  START, and RANGE have the same meanings
-   with re_search.
+   meaning as with regexec.  LAST_START is START + RANGE, where
+   START and RANGE have the same meaning as with re_search.
    Return REG_NOERROR if we find a match, and REG_NOMATCH if not,
    otherwise return the error code.
    Note: We assume front end functions already check ranges.
-   (START + RANGE >= 0 && START + RANGE <= LENGTH)  */
+   (0 <= LAST_START && LAST_START <= LENGTH)  */
 
 static reg_errcode_t
 internal_function
 re_search_internal (const regex_t *preg,
 		    const char *string, Idx length,
-		    Idx start, regoff_t range, Idx stop,
+		    Idx start, Idx last_start, Idx stop,
 		    size_t nmatch, regmatch_t pmatch[],
 		    int eflags)
 {
@@ -612,8 +623,9 @@
 #else
   re_match_context_t mctx;
 #endif
-  char *fastmap = (preg->re_fastmap != NULL && preg->re_fastmap_accurate
-		   && range && !preg->re_can_be_null) ? preg->re_fastmap : NULL;
+  char *fastmap = ((preg->re_fastmap != NULL && preg->re_fastmap_accurate
+		    && start != last_start && !preg->re_can_be_null)
+		   ? preg->re_fastmap : NULL);
   unsigned REG_TRANSLATE_TYPE t =
     (unsigned REG_TRANSLATE_TYPE) preg->re_translate;
 
@@ -633,7 +645,7 @@
 
 #ifdef DEBUG
   /* We assume front-end functions already check them.  */
-  assert (start + range >= 0 && start + range <= length);
+  assert (0 <= last_start && last_start <= length);
 #endif
 
   /* If initial states with non-begbuf contexts have no elements,
@@ -644,9 +656,9 @@
       && (dfa->init_state_nl->nodes.nelem == 0
 	  || !preg->re_newline_anchor))
     {
-      if (start != 0 && start + range != 0)
+      if (start != 0 && last_start != 0)
         return REG_NOMATCH;
-      start = range = 0;
+      start = last_start = 0;
     }
 
   /* We must check the longest matching, if nmatch > 0.  */
@@ -686,14 +698,14 @@
 			   : CONTEXT_NEWLINE | CONTEXT_BEGBUF;
 
   /* Check incrementally whether of not the input string match.  */
-  incr = (range < 0) ? -1 : 1;
-  left_lim = (range < 0) ? start + range : start;
-  right_lim = (range < 0) ? start : start + range;
+  incr = (last_start < start) ? -1 : 1;
+  left_lim = (last_start < start) ? last_start : start;
+  right_lim = (last_start < start) ? start : last_start;
   sb = dfa->mb_cur_max == 1;
   match_kind =
     (fastmap
      ? ((sb || !(preg->re_syntax & REG_IGNORE_CASE || t) ? 4 : 0)
-	| (range >= 0 ? 2 : 0)
+	| (start <= last_start ? 2 : 0)
 	| (t != NULL ? 1 : 0))
      : 8);
 
@@ -803,7 +815,7 @@
       /* We assume that the matching starts from 0.  */
       mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
       match_last = check_matching (&mctx, fl_longest_match,
-				   range >= 0 ? &match_first : NULL);
+				   start <= last_start ? &match_first : NULL);
       if (match_last != REG_MISSING)
 	{
 	  if (BE (match_last == REG_ERROR, 0))