X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fregex_internal.c;h=7e8c1bc25c9e78fca3e4898deda0896100bdba7f;hb=f68069b334f95cfd6d18db4bb059b792beb48158;hp=904b88ed934a2a19ab53db2fe2fcbe74b58a3d97;hpb=03da0525bfb3c3b63cce51a8d5932fc249953b83;p=gnulib.git diff --git a/lib/regex_internal.c b/lib/regex_internal.c index 904b88ed9..7e8c1bc25 100644 --- a/lib/regex_internal.c +++ b/lib/regex_internal.c @@ -1,6 +1,5 @@ /* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - Free Software Foundation, Inc. + Copyright (C) 2002-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Isamu Hasegawa . @@ -15,8 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + with this program; if not, see . */ static void re_string_construct_common (const char *str, Idx len, re_string_t *pstr, @@ -36,7 +34,7 @@ static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, re_string_reconstruct before using the object. */ static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len, RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) { @@ -64,7 +62,7 @@ re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len, /* This function allocate the buffers, and initialize them. */ static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_string_construct (re_string_t *pstr, const char *str, Idx len, RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) { @@ -127,7 +125,7 @@ re_string_construct (re_string_t *pstr, const char *str, Idx len, /* Helper functions for re_string_allocate, and re_string_construct. */ static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) { #ifdef RE_ENABLE_I18N @@ -135,9 +133,9 @@ re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) { wint_t *new_wcs; - /* Avoid overflow. */ - size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); - if (BE (SIZE_MAX / max_object_size < new_buf_len, 0)) + /* Avoid overflow in realloc. */ + const size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); + if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < new_buf_len, 0)) return REG_ESPACE; new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); @@ -237,13 +235,8 @@ build_wcs_buffer (re_string_t *pstr) else p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2, 0)) - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) + if (BE (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len), 0)) { /* We treat these cases as a singlebyte character. */ mbclen = 1; @@ -252,6 +245,12 @@ build_wcs_buffer (re_string_t *pstr) wc = pstr->trans[wc]; pstr->cur_state = prev_st; } + else if (BE (mbclen == (size_t) -2, 0)) + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } /* Write wide character and padding. */ pstr->wcs[byte_idx++] = wc; @@ -267,7 +266,7 @@ build_wcs_buffer (re_string_t *pstr) but for REG_ICASE. */ static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ build_wcs_upper_buffer (re_string_t *pstr) { mbstate_t prev_st; @@ -334,9 +333,11 @@ build_wcs_upper_buffer (re_string_t *pstr) for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } - else if (mbclen == (size_t) -1 || mbclen == 0) + else if (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) { - /* It is an invalid character or '\0'. Just use the byte. */ + /* It is an invalid character, an incomplete character + at the end of the string, or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; pstr->mbs[byte_idx] = ch; /* And also cast it to wide char. */ @@ -430,8 +431,8 @@ build_wcs_upper_buffer (re_string_t *pstr) src_idx += mbclen; continue; } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); + else + memcpy (pstr->mbs + byte_idx, p, mbclen); } else memcpy (pstr->mbs + byte_idx, p, mbclen); @@ -449,7 +450,8 @@ build_wcs_upper_buffer (re_string_t *pstr) for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) pstr->wcs[byte_idx++] = WEOF; } - else if (mbclen == (size_t) -1 || mbclen == 0) + else if (mbclen == (size_t) -1 || mbclen == 0 + || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len)) { /* It is an invalid character or '\0'. Just use the byte. */ int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; @@ -496,8 +498,7 @@ re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc) rawbuf_idx < new_raw_idx;) { wchar_t wc2; - Idx remain_len; - remain_len = pstr->len - rawbuf_idx; + Idx remain_len = pstr->raw_len - rawbuf_idx; prev_st = pstr->cur_state; mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx, remain_len, &pstr->cur_state); @@ -569,7 +570,7 @@ re_string_translate_buffer (re_string_t *pstr) convert to upper case in case of REG_ICASE, apply translation. */ static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) { Idx offset; @@ -736,16 +737,18 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) unsigned char buf[6]; size_t mbclen; + const unsigned char *pp = p; if (BE (pstr->trans != NULL, 0)) { int i = mlen < 6 ? mlen : 6; while (--i >= 0) buf[i] = pstr->trans[p[i]]; + pp = buf; } /* XXX Don't use mbrtowc, we know which conversion to use (UTF-8 -> UCS4). */ memset (&cur_state, 0, sizeof (cur_state)); - mbclen = __mbrtowc (&wc2, (const char *) p, mlen, + mbclen = __mbrtowc (&wc2, (const char *) pp, mlen, &cur_state); if (raw + offset - p <= mbclen && mbclen < (size_t) -2) @@ -867,7 +870,7 @@ re_string_peek_byte_case (const re_string_t *pstr, Idx idx) } static unsigned char -internal_function __attribute ((pure)) +internal_function re_string_fetch_byte_case (re_string_t *pstr) { if (BE (!pstr->mbs_allocated, 1)) @@ -964,7 +967,7 @@ re_string_context_at (const re_string_t *input, Idx idx, int eflags) /* Functions for set operation. */ static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_node_set_alloc (re_node_set *set, Idx size) { set->alloc = size; @@ -976,7 +979,7 @@ re_node_set_alloc (re_node_set *set, Idx size) } static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_node_set_init_1 (re_node_set *set, Idx elem) { set->alloc = 1; @@ -992,7 +995,7 @@ re_node_set_init_1 (re_node_set *set, Idx elem) } static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2) { set->alloc = 2; @@ -1022,7 +1025,7 @@ re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2) } static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_node_set_init_copy (re_node_set *dest, const re_node_set *src) { dest->nelem = src->nelem; @@ -1047,7 +1050,7 @@ re_node_set_init_copy (re_node_set *dest, const re_node_set *src) Note: We assume dest->elems is NULL, when dest->alloc is 0. */ static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, const re_node_set *src2) { @@ -1062,7 +1065,7 @@ re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, Idx new_alloc = src1->nelem + src2->nelem + dest->alloc; Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc); if (BE (new_elems == NULL, 0)) - return REG_ESPACE; + return REG_ESPACE; dest->elems = new_elems; dest->alloc = new_alloc; } @@ -1112,20 +1115,20 @@ re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, if (delta > 0 && REG_VALID_INDEX (id)) for (;;) { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (! REG_VALID_INDEX (--id)) - break; - } + if (dest->elems[is] > dest->elems[id]) + { + /* Copy from the top. */ + dest->elems[id + delta--] = dest->elems[is--]; + if (delta == 0) + break; + } + else + { + /* Slide from the bottom. */ + dest->elems[id + delta] = dest->elems[id]; + if (! REG_VALID_INDEX (--id)) + break; + } } /* Copy remaining SRC elements. */ @@ -1138,7 +1141,7 @@ re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_node_set_init_union (re_node_set *dest, const re_node_set *src1, const re_node_set *src2) { @@ -1191,7 +1194,7 @@ re_node_set_init_union (re_node_set *dest, const re_node_set *src1, DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ static reg_errcode_t -internal_function +internal_function __attribute_warn_unused_result__ re_node_set_merge (re_node_set *dest, const re_node_set *src) { Idx is, id, sbase, delta; @@ -1221,11 +1224,11 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src) REG_VALID_INDEX (is) && REG_VALID_INDEX (id); ) { if (dest->elems[id] == src->elems[is]) - is--, id--; + is--, id--; else if (dest->elems[id] < src->elems[is]) - dest->elems[--sbase] = src->elems[is--]; + dest->elems[--sbase] = src->elems[is--]; else /* if (dest->elems[id] > src->elems[is]) */ - --id; + --id; } if (REG_VALID_INDEX (is)) @@ -1247,21 +1250,21 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src) for (;;) { if (dest->elems[is] > dest->elems[id]) - { + { /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; + dest->elems[id + delta--] = dest->elems[is--]; if (delta == 0) break; } else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; + { + /* Slide from the bottom. */ + dest->elems[id + delta] = dest->elems[id]; if (! REG_VALID_INDEX (--id)) { /* Copy remaining SRC elements. */ memcpy (dest->elems, dest->elems + sbase, - delta * sizeof (Idx)); + delta * sizeof (Idx)); break; } } @@ -1275,7 +1278,7 @@ re_node_set_merge (re_node_set *dest, const re_node_set *src) Return true if successful. */ static bool -internal_function +internal_function __attribute_warn_unused_result__ re_node_set_insert (re_node_set *set, Idx elem) { Idx idx; @@ -1308,12 +1311,12 @@ re_node_set_insert (re_node_set *set, Idx elem) { idx = 0; for (idx = set->nelem; idx > 0; idx--) - set->elems[idx] = set->elems[idx - 1]; + set->elems[idx] = set->elems[idx - 1]; } else { for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) - set->elems[idx] = set->elems[idx - 1]; + set->elems[idx] = set->elems[idx - 1]; } /* Insert the new element. */ @@ -1327,7 +1330,7 @@ re_node_set_insert (re_node_set *set, Idx elem) Return true if successful. */ static bool -internal_function +internal_function __attribute_warn_unused_result__ re_node_set_insert_last (re_node_set *set, Idx elem) { /* Realloc if we need. */ @@ -1411,13 +1414,12 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token) Idx *new_nexts, *new_indices; re_node_set *new_edests, *new_eclosures; re_token_t *new_nodes; - size_t max_object_size = - MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - sizeof (Idx))); - /* Avoid overflows. */ - if (BE (SIZE_MAX / 2 / max_object_size < dfa->nodes_alloc, 0)) + /* Avoid overflows in realloc. */ + const size_t max_object_size = MAX (sizeof (re_token_t), + MAX (sizeof (re_node_set), + sizeof (Idx))); + if (BE (MIN (IDX_MAX, SIZE_MAX / max_object_size) < new_nodes_alloc, 0)) return REG_MISSING; new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); @@ -1473,7 +1475,7 @@ calc_state_hash (const re_node_set *nodes, unsigned int context) optimization. */ static re_dfastate_t * -internal_function +internal_function __attribute_warn_unused_result__ re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, const re_node_set *nodes) { @@ -1521,7 +1523,7 @@ re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, optimization. */ static re_dfastate_t * -internal_function +internal_function __attribute_warn_unused_result__ re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, const re_node_set *nodes, unsigned int context) { @@ -1549,7 +1551,7 @@ re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, && re_node_set_compare (state->entrance_nodes, nodes)) return state; } - /* There are no appropriate state in `dfa', create the new one. */ + /* There are no appropriate state in 'dfa', create the new one. */ new_state = create_cd_newstate (dfa, nodes, context, hash); if (BE (new_state == NULL, 0)) *err = REG_ESPACE; @@ -1562,6 +1564,7 @@ re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, indicates the error code if failed. */ static reg_errcode_t +__attribute_warn_unused_result__ register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, re_hashval_t hash) { @@ -1577,7 +1580,7 @@ register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, { Idx elem = newstate->nodes.elems[i]; if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) - if (BE (! re_node_set_insert_last (&newstate->non_eps_nodes, elem), 0)) + if (! re_node_set_insert_last (&newstate->non_eps_nodes, elem)) return REG_ESPACE; } @@ -1612,11 +1615,11 @@ free_state (re_dfastate_t *state) re_free (state); } -/* Create the new state which is independ of contexts. +/* Create the new state which is independent of contexts. Return the new state if succeeded, otherwise return NULL. */ static re_dfastate_t * -internal_function +internal_function __attribute_warn_unused_result__ create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, re_hashval_t hash) { @@ -1666,7 +1669,7 @@ create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, Return the new state if succeeded, otherwise return NULL. */ static re_dfastate_t * -internal_function +internal_function __attribute_warn_unused_result__ create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, unsigned int context, re_hashval_t hash) { @@ -1715,7 +1718,9 @@ create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, free_state (newstate); return NULL; } - re_node_set_init_copy (newstate->entrance_nodes, nodes); + if (re_node_set_init_copy (newstate->entrance_nodes, nodes) + != REG_NOERROR) + return NULL; nctx_nodes = 0; newstate->has_constraint = 1; }