regcomp, regexec, fnmatch: avoid array bounds read error
authorUlrich Drepper <drepper@redhat.com>
Mon, 4 Jan 2010 10:18:51 +0000 (11:18 +0100)
committerJim Meyering <meyering@redhat.com>
Mon, 4 Jan 2010 15:22:19 +0000 (16:22 +0100)
* lib/regcomp.c (build_equiv_class): From glibc:
Use only the low 24 bits of a findidx return value as an index
into the weights array.  Patch by Ulrich Drepper:
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commit;h=b7d1c5fa30
* lib/regexec.c (check_node_accept_bytes): Likewise.
* lib/fnmatch_loop.c (FCT): Likewise.

ChangeLog
lib/fnmatch_loop.c
lib/regcomp.c
lib/regexec.c

index f906c28..7456904 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2010-01-04  Jim Meyering  <meyering@redhat.com>
 
+       regcomp, regexec, fnmatch: avoid array bounds read error
+       * lib/regcomp.c (build_equiv_class): From glibc:
+       Use only the low 24 bits of a findidx return value as an index
+       into the weights array.  Patch by Ulrich Drepper:
+       http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commit;h=b7d1c5fa30
+       * lib/regexec.c (check_node_accept_bytes): Likewise.
+       * lib/fnmatch_loop.c (FCT): Likewise.
+
        regcomp: skip collseq lookup when there are no rules
        * lib/regcomp.c (lookup_collation_sequence_value): From glibc:
        http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a532a41df58
index bb24904..8cd4444 100644 (file)
@@ -382,15 +382,20 @@ FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end,
                             /* We found a table entry.  Now see whether the
                                character we are currently at has the same
                                equivalance class value.  */
-                            int len = weights[idx];
+                            int len = weights[idx & 0xffffff];
                             int32_t idx2;
                             const UCHAR *np = (const UCHAR *) n;
 
                             idx2 = findidx (&np);
-                            if (idx2 != 0 && len == weights[idx2])
+                            if (idx2 != 0
+                                && (idx >> 24) == (idx2 >> 24)
+                                && len == weights[idx2 & 0xffffff])
                               {
                                 int cnt = 0;
 
+                                idx &= 0xffffff;
+                                idx2 &= 0xffffff;
+
                                 while (cnt < len
                                        && (weights[idx + 1 + cnt]
                                            == weights[idx2 + 1 + cnt]))
index 8ba0616..ebb696a 100644 (file)
@@ -3436,7 +3436,7 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
 
       /* Build single byte matcing table for this equivalence class.  */
       char_buf[1] = (unsigned char) '\0';
-      len = weights[idx1];
+      len = weights[idx1 & 0xffffff];
       for (ch = 0; ch < SBC_MAX; ++ch)
        {
          char_buf[0] = ch;
@@ -3448,11 +3448,15 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name)
          if (idx2 == 0)
            /* This isn't a valid character.  */
            continue;
-         if (len == weights[idx2])
+         /* Compare only if the length matches and the collation rule
+            index is the same.  */
+         if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24))
            {
              int cnt = 0;
+
              while (cnt <= len &&
-                    weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt])
+                    weights[(idx1 & 0xffffff) + 1 + cnt]
+                    == weights[(idx2 & 0xffffff) + 1 + cnt])
                ++cnt;
 
              if (cnt > len)
index 0d48a95..05979b1 100644 (file)
@@ -3949,15 +3949,20 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx,
                _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
              indirect = (const int32_t *)
                _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);
-             idx = findidx (&cp);
+             int32_t idx = findidx (&cp);
              if (idx > 0)
                for (i = 0; i < cset->nequiv_classes; ++i)
                  {
                    int32_t equiv_class_idx = cset->equiv_classes[i];
-                   size_t weight_len = weights[idx];
-                   if (weight_len == weights[equiv_class_idx])
+                   size_t weight_len = weights[idx & 0xffffff];
+                   if (weight_len == weights[equiv_class_idx & 0xffffff]
+                       && (idx >> 24) == (equiv_class_idx >> 24))
                      {
                        Idx cnt = 0;
+
+                       idx &= 0xffffff;
+                       equiv_class_idx &= 0xffffff;
+
                        while (cnt <= weight_len
                               && (weights[equiv_class_idx + 1 + cnt]
                                   == weights[idx + 1 + cnt]))