And now, for the regex patch that I wanted to install originally! Most of the other regex patches were in preparation for this one. This patch duplicates some of the ideas from the xmalloc module, but I judged that better than trying to get the glibc folks to adopt xmalloc.
The regex code currently misbehaves badly if there's an arithmetic overflow when calculating sizes, e.g., when doubling buffer sizes. I installed this patch into gnulib and filed glibc bug 1291. 2005-09-02 Paul Eggert <[EMAIL PROTECTED]> 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. --- lib/regex_internal.h 1 Sep 2005 19:41:07 -0000 1.11 +++ lib/regex_internal.h 2 Sep 2005 22:39:27 -0000 @@ -442,9 +442,69 @@ static unsigned int re_string_context_at #endif #define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) +#define re_xmalloc(t,n) ((t *) re_xnmalloc (n, sizeof (t))) #define re_calloc(t,n) ((t *) calloc (n, sizeof (t))) #define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) +#define re_xrealloc(p,t,n) ((t *) re_xnrealloc (p, n, sizeof (t))) +#define re_x2realloc(p,t,pn) ((t *) re_x2nrealloc (p, pn, sizeof (t))) #define re_free(p) free (p) + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +/* Return true if an array of N objects, each of size S, cannot exist + due to size arithmetic overflow. S must be nonzero. */ +static inline bool +re_alloc_oversized (size_t n, size_t s) +{ + return BE (SIZE_MAX / s < n, 0); +} + +/* Return true if an array of (2 * N + 1) objects, each of size S, + cannot exist due to size arithmetic overflow. S must be nonzero. */ +static inline bool +re_x2alloc_oversized (size_t n, size_t s) +{ + return BE ((SIZE_MAX / s - 1) / 2 < n, 0); +} + +/* Allocate an array of N objects, each with S bytes of memory, + dynamically, with error checking. S must be nonzero. */ +static inline void * +re_xnmalloc (size_t n, size_t s) +{ + return re_alloc_oversized (n, s) ? NULL : malloc (n * s); +} + +/* Change the size of an allocated block of memory P to an array of N + objects each of S bytes, with error checking. S must be nonzero. */ +static inline void * +re_xnrealloc (void *p, size_t n, size_t s) +{ + return re_alloc_oversized (n, s) ? NULL : realloc (p, n * s); +} + +/* Reallocate a block of memory P to an array of (2 * (*PN) + 1) + objects each of S bytes, with error checking. S must be nonzero. + If the allocation is successful, set *PN to the new allocation + count and return the resulting pointer. Otherwise, return + NULL. */ +static inline void * +re_x2nrealloc (void *p, size_t *pn, size_t s) +{ + if (re_x2alloc_oversized (*pn, s)) + return NULL; + else + { + /* Add 1 in case *PN is zero. */ + size_t n1 = 2 * *pn + 1; + p = realloc (p, n1 * s); + if (BE (p != NULL, 1)) + *pn = n1; + return p; + } +} struct bin_tree_t { --- lib/regcomp.c 1 Sep 2005 19:41:07 -0000 1.15 +++ lib/regcomp.c 2 Sep 2005 22:39:28 -0000 @@ -808,7 +808,7 @@ init_dfa (re_dfa_t *dfa, Idx pat_len) dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; dfa->nodes_alloc = pat_len + 1; - dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); + dfa->nodes = re_xmalloc (re_token_t, dfa->nodes_alloc); /* table_size = 2 ^ ceil(log pat_len) */ for (table_size = 1; table_size <= pat_len; table_size <<= 1) @@ -1083,13 +1083,13 @@ analyze (regex_t *preg) /* Allocate arrays. */ dfa->nexts = re_malloc (Idx, dfa->nodes_alloc); dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc); - dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); + dfa->edests = re_xmalloc (re_node_set, dfa->nodes_alloc); dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL || dfa->eclosures == NULL, 0)) return REG_ESPACE; - dfa->subexp_map = re_malloc (Idx, preg->re_nsub); + dfa->subexp_map = re_xmalloc (Idx, preg->re_nsub); if (dfa->subexp_map != NULL) { Idx i; @@ -1125,7 +1125,7 @@ analyze (regex_t *preg) if ((!preg->re_no_sub && preg->re_nsub > 0 && dfa->has_plural_match) || dfa->nbackref) { - dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); + dfa->inveclosures = re_xmalloc (re_node_set, dfa->nodes_len); if (BE (dfa->inveclosures == NULL, 0)) return REG_ESPACE; ret = calc_inveclosure (dfa); @@ -2608,12 +2608,11 @@ build_range_exp (re_bitset_ptr_t sbcset, wchar_t *new_array_start, *new_array_end; Idx new_nranges; - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; + new_nranges = mbcset->nranges; /* Use realloc since mbcset->range_starts and mbcset->range_ends are NULL if *range_alloc == 0. */ - new_array_start = re_realloc (mbcset->range_starts, wchar_t, - new_nranges); + new_array_start = re_x2realloc (mbcset->range_starts, wchar_t, + &new_nranges); new_array_end = re_realloc (mbcset->range_ends, wchar_t, new_nranges); @@ -2840,10 +2839,9 @@ parse_bracket_exp (re_string_t *regexp, uint32_t *new_array_end; Idx new_nranges; - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - new_array_start = re_realloc (mbcset->range_starts, uint32_t, - new_nranges); + new_nranges = mbcset->nranges; + new_array_start = re_x2realloc (mbcset->range_starts, uint32_t, + &new_nranges); new_array_end = re_realloc (mbcset->range_ends, uint32_t, new_nranges); @@ -2914,12 +2912,11 @@ parse_bracket_exp (re_string_t *regexp, if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0)) { /* Not enough, realloc it. */ - /* +1 in case of mbcset->ncoll_syms is 0. */ - Idx new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; + Idx new_coll_sym_alloc = mbcset->ncoll_syms; /* Use realloc since mbcset->coll_syms is NULL if *alloc == 0. */ - int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, - new_coll_sym_alloc); + int32_t *new_coll_syms = re_x2realloc (mbcset->coll_syms, int32_t, + &new_coll_sym_alloc); if (BE (new_coll_syms == NULL, 0)) return REG_ESPACE; mbcset->coll_syms = new_coll_syms; @@ -3103,11 +3100,10 @@ parse_bracket_exp (re_string_t *regexp, { wchar_t *new_mbchars; /* Not enough, realloc it. */ - /* +1 in case of mbcset->nmbchars is 0. */ - mbchar_alloc = 2 * mbcset->nmbchars + 1; + mbchar_alloc = mbcset->nmbchars; /* Use realloc since array is NULL if *alloc == 0. */ - new_mbchars = re_realloc (mbcset->mbchars, wchar_t, - mbchar_alloc); + new_mbchars = re_x2realloc (mbcset->mbchars, wchar_t, + &mbchar_alloc); if (BE (new_mbchars == NULL, 0)) goto parse_bracket_exp_espace; mbcset->mbchars = new_mbchars; @@ -3381,12 +3377,11 @@ build_equiv_class (re_bitset_ptr_t sbcse if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0)) { /* Not enough, realloc it. */ - /* +1 in case of mbcset->nequiv_classes is 0. */ - Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; + Idx new_equiv_class_alloc = mbcset->nequiv_classes; /* Use realloc since the array is NULL if *alloc == 0. */ - int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, - int32_t, - new_equiv_class_alloc); + int32_t *new_equiv_classes = re_x2realloc (mbcset->equiv_classes, + int32_t, + &new_equiv_class_alloc); if (BE (new_equiv_classes == NULL, 0)) return REG_ESPACE; mbcset->equiv_classes = new_equiv_classes; @@ -3431,11 +3426,10 @@ build_charclass (unsigned REG_TRANSLATE_ if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) { /* Not enough, realloc it. */ - /* +1 in case of mbcset->nchar_classes is 0. */ - Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1; + Idx new_char_class_alloc = mbcset->nchar_classes; /* Use realloc since array is NULL if *alloc == 0. */ - wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, - new_char_class_alloc); + wctype_t *new_char_classes = re_x2realloc (mbcset->char_classes, wctype_t, + &new_char_class_alloc); if (BE (new_char_classes == NULL, 0)) return REG_ESPACE; mbcset->char_classes = new_char_classes; --- lib/regex_internal.c 1 Sep 2005 22:10:59 -0000 1.15 +++ lib/regex_internal.c 2 Sep 2005 22:39:28 -0000 @@ -132,13 +132,13 @@ re_string_realloc_buffers (re_string_t * #ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { - wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); + wint_t *new_wcs = re_xrealloc (pstr->wcs, wint_t, new_buf_len); if (BE (new_wcs == NULL, 0)) return REG_ESPACE; pstr->wcs = new_wcs; if (pstr->offsets != NULL) { - Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len); + Idx *new_offsets = re_xrealloc (pstr->offsets, Idx, new_buf_len); if (BE (new_offsets == NULL, 0)) return REG_ESPACE; pstr->offsets = new_offsets; @@ -392,7 +392,7 @@ build_wcs_upper_buffer (re_string_t *pst if (pstr->offsets == NULL) { - pstr->offsets = re_malloc (Idx, pstr->bufs_len); + pstr->offsets = re_xmalloc (Idx, pstr->bufs_len); if (pstr->offsets == NULL) return REG_ESPACE; @@ -873,7 +873,7 @@ re_node_set_alloc (re_node_set *set, Idx { set->alloc = size; set->nelem = 0; - set->elems = re_malloc (Idx, size); + set->elems = re_xmalloc (Idx, size); if (BE (set->elems == NULL, 0)) return REG_ESPACE; return REG_NOERROR; @@ -964,7 +964,12 @@ re_node_set_add_intersect (re_node_set * if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) { Idx new_alloc = src1->nelem + src2->nelem + dest->alloc; - Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc); + Idx *new_elems; + if (sizeof (Idx) < 3 + && (new_alloc < dest->alloc + || ((Idx) (src1->nelem + src2->nelem) < src1->nelem))) + return REG_ESPACE; + new_elems = re_xrealloc (dest->elems, Idx, new_alloc); if (BE (new_elems == NULL, 0)) return REG_ESPACE; dest->elems = new_elems; @@ -1050,7 +1055,9 @@ re_node_set_init_union (re_node_set *des if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) { dest->alloc = src1->nelem + src2->nelem; - dest->elems = re_malloc (Idx, dest->alloc); + if (sizeof (Idx) < 2 && dest->alloc < src1->nelem) + return REG_ESPACE; + dest->elems = re_xmalloc (Idx, dest->alloc); if (BE (dest->elems == NULL, 0)) return REG_ESPACE; } @@ -1101,10 +1108,17 @@ re_node_set_merge (re_node_set *dest, co Idx is, id, sbase, delta; if (src == NULL || src->nelem == 0) return REG_NOERROR; + if (sizeof (Idx) < 3 + && ((Idx) (2 * src->nelem) < src->nelem + || (Idx) (2 * src->nelem + dest->nelem) < dest->nelem)) + return REG_ESPACE; if (dest->alloc < 2 * src->nelem + dest->nelem) { - Idx new_alloc = 2 * (src->nelem + dest->alloc); - Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc); + Idx new_alloc = src->nelem + dest->alloc; + Idx *new_buffer; + if (sizeof (Idx) < 4 && new_alloc < dest->alloc) + return REG_ESPACE; + new_buffer = re_x2realloc (dest->elems, Idx, &new_alloc); if (BE (new_buffer == NULL, 0)) return REG_ESPACE; dest->elems = new_buffer; @@ -1199,9 +1213,7 @@ re_node_set_insert (re_node_set *set, Id /* Realloc if we need. */ if (set->alloc == set->nelem) { - Idx *new_elems; - set->alloc = set->alloc * 2; - new_elems = re_realloc (set->elems, Idx, set->alloc); + Idx *new_elems = re_x2realloc (set->elems, Idx, &set->alloc); if (BE (new_elems == NULL, 0)) return false; set->elems = new_elems; @@ -1239,8 +1251,7 @@ re_node_set_insert_last (re_node_set *se if (set->alloc == set->nelem) { Idx *new_elems; - set->alloc = (set->alloc + 1) * 2; - new_elems = re_realloc (set->elems, Idx, set->alloc); + new_elems = re_x2realloc (set->elems, Idx, &set->alloc); if (BE (new_elems == NULL, 0)) return false; set->elems = new_elems; @@ -1313,18 +1324,18 @@ re_dfa_add_node (re_dfa_t *dfa, re_token int type = token.type; if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) { - Idx new_nodes_alloc = dfa->nodes_alloc * 2; + Idx new_nodes_alloc = dfa->nodes_alloc; Idx *new_nexts, *new_indices; re_node_set *new_edests, *new_eclosures; - re_token_t *new_nodes = re_realloc (dfa->nodes, re_token_t, - new_nodes_alloc); + re_token_t *new_nodes = re_x2realloc (dfa->nodes, re_token_t, + &new_nodes_alloc); if (BE (new_nodes == NULL, 0)) return REG_MISSING; dfa->nodes = new_nodes; new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc); new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc); - new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); + new_edests = re_xrealloc (dfa->edests, re_node_set, new_nodes_alloc); new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); if (BE (new_nexts == NULL || new_indices == NULL || new_edests == NULL || new_eclosures == NULL, 0)) @@ -1487,9 +1498,9 @@ register_state (const re_dfa_t *dfa, re_ spot = dfa->state_table + (hash & dfa->state_hash_mask); if (BE (spot->alloc <= spot->num, 0)) { - Idx new_alloc = 2 * spot->num + 2; - re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, - new_alloc); + Idx new_alloc = spot->num; + re_dfastate_t **new_array = re_x2realloc (spot->array, re_dfastate_t *, + &new_alloc); if (BE (new_array == NULL, 0)) return REG_ESPACE; spot->array = new_array; --- lib/regexec.c 1 Sep 2005 19:41:07 -0000 1.16 +++ lib/regexec.c 2 Sep 2005 22:39:28 -0000 @@ -434,7 +434,7 @@ re_search_stub (struct re_pattern_buffer 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 @@ re_search_stub (struct re_pattern_buffer } 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 @@ re_copy_regs (struct re_registers *regs, /* 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 @@ re_copy_regs (struct re_registers *regs, 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 @@ re_search_internal (const regex_t *preg, 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 @@ prune_impossible_nodes (re_match_context #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 @@ prune_impossible_nodes (re_match_context } 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 @@ push_fail_stack (struct re_fail_stack_t 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 @@ set_regs (const regex_t *preg, const re_ 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 @@ set_regs (const regex_t *preg, const re_ 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 @@ check_arrival (re_match_context_t *mctx, { 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 @@ build_trtable (re_dfa_t *dfa, re_dfastat 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 @@ extend_buffers (re_match_context_t *mctx /* 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 @@ match_ctx_init (re_match_context_t *mctx 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 @@ match_ctx_add_entry (re_match_context_t 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 @@ match_ctx_add_entry (re_match_context_t } 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 @@ match_ctx_add_subtop (re_match_context_t #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 @@ match_ctx_add_sublast (re_sub_match_top_ 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; _______________________________________________ bug-gnulib mailing list bug-gnulib@gnu.org http://lists.gnu.org/mailman/listinfo/bug-gnulib