From d55324f119e0f203590486bbf4760a1dc25d7735 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 4 Jan 2010 11:18:51 +0100 Subject: [PATCH] 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. --- ChangeLog | 8 ++++++++ lib/fnmatch_loop.c | 9 +++++++-- lib/regcomp.c | 10 +++++++--- lib/regexec.c | 11 ++++++++--- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index f906c28c8..74569041b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2010-01-04 Jim Meyering + 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 diff --git a/lib/fnmatch_loop.c b/lib/fnmatch_loop.c index bb24904de..8cd444404 100644 --- a/lib/fnmatch_loop.c +++ b/lib/fnmatch_loop.c @@ -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])) diff --git a/lib/regcomp.c b/lib/regcomp.c index 8ba0616fe..ebb696ac2 100644 --- a/lib/regcomp.c +++ b/lib/regcomp.c @@ -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) diff --git a/lib/regexec.c b/lib/regexec.c index 0d48a955f..05979b19b 100644 --- a/lib/regexec.c +++ b/lib/regexec.c @@ -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])) -- 2.11.0