Index: regcomp.c =================================================================== --- regcomp.c (revision 21387) +++ regcomp.c (working copy) @@ -19,6 +19,27 @@ #include +void *xxmalloc(size_t size) +{ + void *ptr; + if (rand() < RAND_MAX / 50) { + fprintf(stderr, "fail\n"); + return 0; + } + ptr = malloc(size); + return ptr; +} + +void *xxrealloc(void *ptr, size_t size) +{ + if (rand() < RAND_MAX / 50) { + fprintf(stderr, "rfail\n"); + return 0; + } + ptr = realloc(ptr, size); + return ptr; +} + static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, size_t length, reg_syntax_t syntax); static void re_compile_fastmap_iter (regex_t *bufp, @@ -1165,7 +1186,10 @@ 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; + { + postorder (dfa->str_tree, free_tree, NULL); + return REG_ESPACE; + } dfa->subexp_map = re_malloc (int, preg->re_nsub); if (dfa->subexp_map != NULL) @@ -1185,15 +1209,21 @@ } ret = postorder (dfa->str_tree, lower_subexps, preg); - if (BE (ret != REG_NOERROR, 0)) + if (BE (ret != REG_NOERROR, 0)) { + postorder (dfa->str_tree, free_tree, NULL); return ret; + } ret = postorder (dfa->str_tree, calc_first, dfa); - if (BE (ret != REG_NOERROR, 0)) + if (BE (ret != REG_NOERROR, 0)) { + postorder (dfa->str_tree, free_tree, NULL); return ret; + } preorder (dfa->str_tree, calc_next, dfa); ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); - if (BE (ret != REG_NOERROR, 0)) + if (BE (ret != REG_NOERROR, 0)) { + postorder (dfa->str_tree, free_tree, NULL); return ret; + } ret = calc_eclosure (dfa); if (BE (ret != REG_NOERROR, 0)) return ret; @@ -1320,12 +1350,16 @@ if (node->left && node->left->token.type == SUBEXP) { node->left = lower_subexp (&err, preg, node->left); + if (BE (err != REG_NOERROR && node->left == NULL, 0)) + return err; if (node->left) node->left->parent = node; } if (node->right && node->right->token.type == SUBEXP) { node->right = lower_subexp (&err, preg, node->right); + if (BE (err != REG_NOERROR && node->left == NULL, 0)) + return err; if (node->right) node->right->parent = node; } @@ -1353,12 +1387,44 @@ /* Convert the SUBEXP node to the concatenation of an OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ + + if (body) { + /* + Disconnect body (node->left) from the tree to prevent traversal + to upper levels when cleaning up after error + */ + body->parent = NULL; + node->left = NULL; + } + op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); + if (BE (op == NULL, 0)) + { + if (body) + postorder (body, free_tree, NULL); + *err = REG_ESPACE; + return NULL; + } cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); + if (BE (cls == NULL, 0)) + { + if (body) + postorder (body, free_tree, NULL); + *err = REG_ESPACE; + return NULL; + } tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; + if (BE (tree1 == NULL, 0)) + { + if (body) + postorder (body, free_tree, NULL); + *err = REG_ESPACE; + return NULL; + } tree = create_tree (dfa, op, tree1, CONCAT); - if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0)) + if (BE (tree == NULL, 0)) { + postorder (tree1, free_tree, NULL); *err = REG_ESPACE; return NULL; } @@ -1385,6 +1451,8 @@ node->node_idx = re_dfa_add_node (dfa, node->token); if (BE (node->node_idx == -1, 0)) return REG_ESPACE; + /* avoid double free in free_dfa_content */ + node->token.duplicated = 1; if (node->token.type == ANCHOR) dfa->nodes[node->node_idx].constraint = node->token.opr.ctx_type; } @@ -1707,8 +1775,10 @@ { err = duplicate_node_closure (dfa, node, node, node, dfa->nodes[node].constraint); - if (BE (err != REG_NOERROR, 0)) + if (BE (err != REG_NOERROR, 0)) { + re_node_set_free (&eclosure); return err; + } } /* Expand each epsilon destination nodes. */ @@ -1729,15 +1799,19 @@ if (dfa->eclosures[edest].nelem == 0) { err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0); - if (BE (err != REG_NOERROR, 0)) + if (BE (err != REG_NOERROR, 0)) { + re_node_set_free (&eclosure); return err; + } } else eclosure_elem = dfa->eclosures[edest]; /* Merge the epsilon closure of `edest'. */ err = re_node_set_merge (&eclosure, &eclosure_elem); - if (BE (err != REG_NOERROR, 0)) + if (BE (err != REG_NOERROR, 0)) { + re_node_set_free (&eclosure); return err; + } /* If the epsilon closure of `edest' is incomplete, the epsilon closure of this node is also incomplete. */ if (dfa->eclosures[edest].nelem == 0) @@ -2123,15 +2197,22 @@ if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; eor = create_tree (dfa, NULL, NULL, END_OF_RE); - if (tree != NULL) - root = create_tree (dfa, tree, eor, CONCAT); - else - root = eor; - if (BE (eor == NULL || root == NULL, 0)) + if (BE (eor == NULL, 0)) { + postorder (tree, free_tree, NULL); *err = REG_ESPACE; return NULL; } + if (tree != NULL) { + root = create_tree (dfa, tree, eor, CONCAT); + if (BE (root == NULL, 0)) + { + postorder (tree, free_tree, NULL); + *err = REG_ESPACE; + return NULL; + } + } else + root = eor; return root; } @@ -2149,7 +2230,7 @@ reg_syntax_t syntax, int nest, reg_errcode_t *err) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree, *branch = NULL; + bin_tree_t *tree, *newtree, *branch = NULL; tree = parse_branch (regexp, preg, token, syntax, nest, err); if (BE (*err != REG_NOERROR && tree == NULL, 0)) return NULL; @@ -2161,17 +2242,25 @@ && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) { branch = parse_branch (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && branch == NULL, 0)) + if (BE (*err != REG_NOERROR && branch == NULL, 0)) { + if (tree != NULL) + postorder (tree, free_tree, NULL); return NULL; + } } else branch = NULL; - tree = create_tree (dfa, tree, branch, OP_ALT); - if (BE (tree == NULL, 0)) + newtree = create_tree (dfa, tree, branch, OP_ALT); + if (BE (newtree == NULL, 0)) { + if (tree != NULL) + postorder (tree, free_tree, NULL); + if (branch != NULL) + postorder (branch, free_tree, NULL); *err = REG_ESPACE; return NULL; } + tree = newtree; } return tree; } @@ -2251,15 +2340,23 @@ while (!re_string_eoi (regexp) && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) { - bin_tree_t *mbc_remain; + bin_tree_t *mbc_remain, *newtree; fetch_token (token, regexp, syntax); mbc_remain = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree, mbc_remain, CONCAT); - if (BE (mbc_remain == NULL || tree == NULL, 0)) + if (BE (mbc_remain == NULL, 0)) { + postorder (tree, free_tree, NULL); *err = REG_ESPACE; return NULL; } + newtree = create_tree (dfa, tree, mbc_remain, CONCAT); + if (BE (newtree == NULL, 0)) + { + postorder (tree, free_tree, NULL); + *err = REG_ESPACE; + return NULL; + } + tree = newtree; } } #endif @@ -2346,17 +2443,32 @@ { token->opr.ctx_type = WORD_FIRST; tree_first = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree_first == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } token->opr.ctx_type = WORD_LAST; } else { token->opr.ctx_type = INSIDE_WORD; tree_first = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree_first == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } token->opr.ctx_type = INSIDE_NOTWORD; } tree_last = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree_last == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } tree = create_tree (dfa, tree_first, tree_last, OP_ALT); - if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0)) + if (BE (tree == NULL, 0)) { *err = REG_ESPACE; return NULL; @@ -2451,7 +2563,7 @@ reg_syntax_t syntax, int nest, reg_errcode_t *err) { re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree; + bin_tree_t *tree, *newtree; size_t cur_nsub; cur_nsub = preg->re_nsub++; @@ -2476,12 +2588,14 @@ if (cur_nsub <= '9' - '1') dfa->completed_bkref_map |= 1 << cur_nsub; - tree = create_tree (dfa, tree, NULL, SUBEXP); - if (BE (tree == NULL, 0)) + newtree = create_tree (dfa, tree, NULL, SUBEXP); + if (BE (newtree == NULL, 0)) { + postorder (tree, free_tree, NULL); *err = REG_ESPACE; return NULL; } + tree = newtree; tree->token.opr.idx = cur_nsub; return tree; } @@ -2492,7 +2606,7 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) { - bin_tree_t *tree = NULL, *old_tree = NULL; + bin_tree_t *tree = NULL, *old_tree = NULL, *newtree; int i, start, end, start_idx = re_string_cur_idx (regexp); re_token_t start_token = *token; @@ -2569,9 +2683,12 @@ for (i = 2; i <= start; ++i) { elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (BE (elem == NULL || tree == NULL, 0)) + if (BE (elem == NULL, 0)) goto parse_dup_op_espace; + newtree = create_tree (dfa, tree, elem, CONCAT); + if (BE (newtree == NULL, 0)) + goto parse_dup_op_espace; + tree = newtree; } if (start == end) @@ -2579,6 +2696,8 @@ /* Duplicate ELEM before it is marked optional. */ elem = duplicate_tree (elem, dfa); + if (BE (elem == NULL, 0)) + goto parse_dup_op_espace; old_tree = tree; } else @@ -2588,8 +2707,10 @@ postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx); tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT)); - if (BE (tree == NULL, 0)) + if (BE (tree == NULL, 0)) { + postorder (elem, free_tree, NULL); goto parse_dup_op_espace; + } /* This loop is actually executed only when end != -1, to rewrite {0,n} as ((...?)?)?... We have @@ -2597,21 +2718,33 @@ for (i = start + 2; i <= end; ++i) { elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (BE (elem == NULL || tree == NULL, 0)) + if (BE (elem == NULL, 0)) goto parse_dup_op_espace; + newtree = create_tree (dfa, tree, elem, CONCAT); + if (BE (newtree == NULL, 0)) + goto parse_dup_op_espace; + tree = newtree; - tree = create_tree (dfa, tree, NULL, OP_ALT); - if (BE (tree == NULL, 0)) + newtree = create_tree (dfa, tree, NULL, OP_ALT); + if (BE (newtree == NULL, 0)) goto parse_dup_op_espace; + tree = newtree; } - if (old_tree) - tree = create_tree (dfa, old_tree, tree, CONCAT); + if (old_tree) { + newtree = create_tree (dfa, old_tree, tree, CONCAT); + if (BE (newtree == NULL, 0)) + goto parse_dup_op_espace; + tree = newtree; + } return tree; parse_dup_op_espace: + if (tree) + postorder (tree, free_tree, NULL); + if (old_tree) + postorder (old_tree, free_tree, NULL); *err = REG_ESPACE; return NULL; } @@ -2697,14 +2830,17 @@ are NULL if *range_alloc == 0. */ new_array_start = re_realloc (mbcset->range_starts, wchar_t, new_nranges); + if (BE (new_array_start == NULL, 0)) + return REG_ESPACE; + mbcset->range_starts = new_array_start; + new_array_end = re_realloc (mbcset->range_ends, wchar_t, new_nranges); - if (BE (new_array_start == NULL || new_array_end == NULL, 0)) + if (BE (new_array_end == NULL, 0)) return REG_ESPACE; + mbcset->range_ends = new_array_end; - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; *range_alloc = new_nranges; } @@ -2948,14 +3084,16 @@ new_nranges = 2 * mbcset->nranges + 1; new_array_start = re_realloc (mbcset->range_starts, uint32_t, new_nranges); + if (BE (new_array_start == NULL, 0)) + return REG_ESPACE; + mbcset->range_starts = new_array_start; + new_array_end = re_realloc (mbcset->range_ends, uint32_t, new_nranges); - - if (BE (new_array_start == NULL || new_array_end == NULL, 0)) + if (BE (new_array_end == NULL, 0)) return REG_ESPACE; + mbcset->range_ends = new_array_end; - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; *range_alloc = new_nranges; } @@ -3290,7 +3428,7 @@ || mbcset->nranges || (dfa_mb_cur_max (dfa) > 1 && (mbcset->nchar_classes || mbcset->non_match))) { - bin_tree_t *mbc_tree; + bin_tree_t *mbc_tree, *newtree; int sbc_idx; /* Build a tree for complex bracket. */ dfa->has_mb_node = 1; @@ -3329,6 +3467,7 @@ { #ifdef RE_ENABLE_I18N free_charset (mbcset); + mbcset = NULL; #endif /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; @@ -3345,6 +3484,7 @@ re_free (sbcset); #ifdef RE_ENABLE_I18N free_charset (mbcset); + mbcset = NULL; #endif /* RE_ENABLE_I18N */ return NULL; } @@ -3644,6 +3784,10 @@ if (BE (sbcset == NULL, 0)) #endif /* not RE_ENABLE_I18N */ { + re_free (sbcset); +#ifdef RE_ENABLE_I18N + re_free (mbcset); +#endif *err = REG_ESPACE; return NULL; } @@ -3755,6 +3899,9 @@ static void free_charset (re_charset_t *cset) { + if (!cset) + return; + re_free (cset->mbchars); # ifdef _LIBC re_free (cset->coll_syms); @@ -3785,6 +3932,10 @@ const re_token_t *token) { bin_tree_t *tree; + + assert (!(left && left->parent)); + assert (!(right && right->parent)); + if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0)) { bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); Index: regex_internal.h =================================================================== --- regex_internal.h (revision 21387) +++ regex_internal.h (working copy) @@ -443,8 +443,10 @@ # endif #endif -#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) -#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) +void *xxmalloc(size_t size); +void *xxrealloc(void *ptr, size_t size); +#define re_malloc(t,n) ((t *) xxmalloc ((n) * sizeof (t))) +#define re_realloc(p,t,n) ((t *) xxrealloc (p, (n) * sizeof (t))) #define re_free(p) free (p) struct bin_tree_t