Mercurial > hg > octave-kai > gnulib-hg
diff lib/regexec.c @ 6206:ca2f5d46eeb6
Check for arithmetic overflow when calculating sizes, to prevent
some buffer-overflow issues. These patches are conservative, in the
sense that when I couldn't determine whether an overflow was possible,
I inserted a run-time check.
* regex_internal.h (re_xmalloc, re_xrealloc, re_x2realloc): New macros.
(SIZE_MAX) [!defined SIZE_MAX]: New macro.
(re_alloc_oversized, re_x2alloc_oversized, re_xnmalloc):
(re_xnrealloc, re_x2nrealloc): New inline functions.
* lib/regcomp.c (init_dfa, analyze, build_range_exp, parse_bracket_exp):
(build_equiv_class, build_charclass): Check for arithmetic overflow
in size expression calculations.
* lib/regex_internal.c (re_string_realloc_buffers):
(build_wcs_upper_buffer, re_node_set_add_intersect):
(re_node_set_init_union, re_node_set_insert, re_node_set_insert_last):
(re_dfa_add_node, register_state): Likewise.
* lib/regexec.c (re_search_stub, re_copy_regs, re_search_internal):
(prune_impossible_nodes, push_fail_stack, set_regs, check_arrival):
(build_trtable, extend_buffers, match_ctx_init, match_ctx_add_entry):
(match_ctx_add_subtop, match_ctx_add_sublast): Likewise.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Fri, 02 Sep 2005 22:54:59 +0000 (2005-09-02) |
parents | 25eaa608fc4e |
children | afb93b90dcb8 |
line wrap: on
line diff
--- a/lib/regexec.c +++ b/lib/regexec.c @@ -434,7 +434,7 @@ if (regs == NULL) nregs = 1; else if (BE (bufp->re_regs_allocated == REG_FIXED - && regs->rm_num_regs < bufp->re_nsub + 1, 0)) + && regs->rm_num_regs <= bufp->re_nsub, 0)) { nregs = regs->rm_num_regs; if (BE (nregs < 1, 0)) @@ -446,7 +446,7 @@ } else nregs = bufp->re_nsub + 1; - pmatch = re_malloc (regmatch_t, nregs); + pmatch = re_xmalloc (regmatch_t, nregs); if (BE (pmatch == NULL, 0)) { rval = -2; @@ -500,7 +500,7 @@ /* Have the register data arrays been allocated? */ if (regs_allocated == REG_UNALLOCATED) { /* No. So allocate them with malloc. */ - regs->rm_start = re_malloc (regoff_t, need_regs); + regs->rm_start = re_xmalloc (regoff_t, need_regs); regs->rm_end = re_malloc (regoff_t, need_regs); if (BE (regs->rm_start == NULL, 0) || BE (regs->rm_end == NULL, 0)) return REG_UNALLOCATED; @@ -513,7 +513,7 @@ if (BE (need_regs > regs->rm_num_regs, 0)) { regoff_t *new_start = - re_realloc (regs->rm_start, regoff_t, need_regs); + re_xrealloc (regs->rm_start, regoff_t, need_regs); regoff_t *new_end = re_realloc (regs->rm_end, regoff_t, need_regs); if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0)) return REG_UNALLOCATED; @@ -685,7 +685,7 @@ multi character collating element. */ if (nmatch > 1 || dfa->has_mb_node) { - mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); + mctx.state_log = re_xmalloc (re_dfastate_t *, mctx.input.bufs_len + 1); if (BE (mctx.state_log == NULL, 0)) { err = REG_ESPACE; @@ -945,7 +945,7 @@ #endif match_last = mctx->match_last; halt_node = mctx->last_node; - sifted_states = re_malloc (re_dfastate_t *, match_last + 1); + sifted_states = re_xmalloc (re_dfastate_t *, match_last + 1); if (BE (sifted_states == NULL, 0)) { ret = REG_ESPACE; @@ -953,7 +953,7 @@ } if (dfa->nbackref) { - lim_states = re_malloc (re_dfastate_t *, match_last + 1); + lim_states = re_xmalloc (re_dfastate_t *, match_last + 1); if (BE (lim_states == NULL, 0)) { ret = REG_ESPACE; @@ -1343,15 +1343,14 @@ if (fs->num == fs->alloc) { struct re_fail_stack_ent_t *new_array = - re_realloc (fs->stack, struct re_fail_stack_ent_t, fs->alloc * 2); + re_x2realloc (fs->stack, struct re_fail_stack_ent_t, &fs->alloc); if (new_array == NULL) return REG_ESPACE; - fs->alloc *= 2; fs->stack = new_array; } fs->stack[num].idx = str_idx; fs->stack[num].node = dest_node; - fs->stack[num].regs = re_malloc (regmatch_t, nregs); + fs->stack[num].regs = re_xmalloc (regmatch_t, nregs); if (fs->stack[num].regs == NULL) return REG_ESPACE; memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); @@ -1399,7 +1398,7 @@ if (fl_backtrack) { fs = &fs_body; - fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); + fs->stack = re_xmalloc (struct re_fail_stack_ent_t, fs->alloc); if (fs->stack == NULL) return REG_ESPACE; } @@ -1409,6 +1408,11 @@ cur_node = dfa->init_node; re_node_set_init_empty (&eps_via_nodes); + if (re_alloc_oversized (nmatch, sizeof (regmatch_t))) + { + free_fail_stack_return (fs); + return REG_ESPACE; + } if (__libc_use_alloca (nmatch * sizeof (regmatch_t))) prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t)); else @@ -2872,16 +2876,16 @@ { re_dfastate_t **new_array; Idx old_alloc = path->alloc; - path->alloc += last_str + mctx->max_mb_elem_len + 1; - new_array = re_realloc (path->array, re_dfastate_t *, path->alloc); - if (new_array == NULL) - { - path->alloc = old_alloc; - return REG_ESPACE; - } + Idx new_alloc = old_alloc + last_str + mctx->max_mb_elem_len + 1; + if (BE (new_alloc < old_alloc, 0)) + return REG_ESPACE; + new_array = re_xrealloc (path->array, re_dfastate_t *, new_alloc); + if (BE (new_array == NULL, 0)) + return REG_ESPACE; path->array = new_array; + path->alloc = new_alloc; memset (new_array + old_alloc, '\0', - sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); + sizeof (re_dfastate_t *) * (new_alloc - old_alloc)); } str_idx = path->next_idx == 0 ? top_str : path->next_idx; @@ -3336,6 +3340,12 @@ if (BE (err != REG_NOERROR, 0)) goto out_free; + /* Avoid arithmetic overflow in size calculation. */ + if (BE (((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX) + / (3 * sizeof (re_dfastate_t *))) + < ndests, 0)) + goto out_free; + if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX + ndests * 3 * sizeof (re_dfastate_t *))) dest_states = (re_dfastate_t **) @@ -4057,8 +4067,8 @@ /* XXX We have no indication of the size of this buffer. If this allocation fail we have no indication that the state_log array does not have the right size. */ - re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, - pstr->bufs_len + 1); + re_dfastate_t **new_array = re_xrealloc (mctx->state_log, re_dfastate_t *, + pstr->bufs_len + 1); if (BE (new_array == NULL, 0)) return REG_ESPACE; mctx->state_log = new_array; @@ -4106,8 +4116,8 @@ mctx->match_last = REG_MISSING; if (n > 0) { - mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); - mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); + mctx->bkref_ents = re_xmalloc (struct re_backref_cache_entry, n); + mctx->sub_tops = re_xmalloc (re_sub_match_top_t *, n); if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0)) return REG_ESPACE; } @@ -4179,8 +4189,8 @@ if (mctx->nbkref_ents >= mctx->abkref_ents) { struct re_backref_cache_entry* new_entry; - new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, - mctx->abkref_ents * 2); + new_entry = re_x2realloc (mctx->bkref_ents, struct re_backref_cache_entry, + &mctx->abkref_ents); if (BE (new_entry == NULL, 0)) { re_free (mctx->bkref_ents); @@ -4188,8 +4198,8 @@ } mctx->bkref_ents = new_entry; memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', - sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); - mctx->abkref_ents *= 2; + (sizeof (struct re_backref_cache_entry) + * (mctx->abkref_ents - mctx->nbkref_ents))); } if (mctx->nbkref_ents > 0 && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) @@ -4253,10 +4263,10 @@ #endif if (BE (mctx->nsub_tops == mctx->asub_tops, 0)) { - Idx new_asub_tops = mctx->asub_tops * 2; - re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, - re_sub_match_top_t *, - new_asub_tops); + Idx new_asub_tops = mctx->asub_tops; + re_sub_match_top_t **new_array = re_x2realloc (mctx->sub_tops, + re_sub_match_top_t *, + &new_asub_tops); if (BE (new_array == NULL, 0)) return REG_ESPACE; mctx->sub_tops = new_array; @@ -4280,10 +4290,10 @@ re_sub_match_last_t *new_entry; if (BE (subtop->nlasts == subtop->alasts, 0)) { - Idx new_alasts = 2 * subtop->alasts + 1; - re_sub_match_last_t **new_array = re_realloc (subtop->lasts, - re_sub_match_last_t *, - new_alasts); + Idx new_alasts = subtop->alasts; + re_sub_match_last_t **new_array = re_x2realloc (subtop->lasts, + re_sub_match_last_t *, + &new_alasts); if (BE (new_array == NULL, 0)) return NULL; subtop->lasts = new_array;