From: Paul Eggert Date: Fri, 6 Jun 2025 01:52:33 +0000 (-0700) Subject: regex: fix some leaks when pattern compilation fails X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=20183123b0d4e0105ea92ac69fa4a8b4f1c69273;p=thirdparty%2Fgnulib.git regex: fix some leaks when pattern compilation fails Problem reported by Alec Brown in: https://lists.gnu.org/r/bug-gnulib/2025-06/msg00040.html * lib/regcomp.c (create_initial_state, calc_eclosure_iter): Fix some memory leaks when these functions fail. --- diff --git a/ChangeLog b/ChangeLog index 2fdc7fb4c0..e811cb496d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2025-06-05 Paul Eggert + + regex: fix some leaks when pattern compilation fails + Problem reported by Alec Brown in: + https://lists.gnu.org/r/bug-gnulib/2025-06/msg00040.html + * lib/regcomp.c (create_initial_state, calc_eclosure_iter): + Fix some memory leaks when these functions fail. + 2025-06-05 Bruno Haible unictype/base, uninorm/base, etc.: Support shared libraries on MSVC. diff --git a/lib/regcomp.c b/lib/regcomp.c index a23f289d7a..41157e5c3a 100644 --- a/lib/regcomp.c +++ b/lib/regcomp.c @@ -1001,21 +1001,25 @@ create_initial_state (re_dfa_t *dfa) Idx dest_idx = dfa->edests[node_idx].elems[0]; if (!re_node_set_contains (&init_nodes, dest_idx)) { - reg_errcode_t merge_err + err = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); - if (merge_err != REG_NOERROR) - return merge_err; + if (err != REG_NOERROR) + break; i = 0; } } } /* It must be the first time to invoke acquire_state. */ - dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); - /* We don't check ERR here, since the initial state must not be NULL. */ + dfa->init_state + = (err == REG_NOERROR + ? re_acquire_state_context (&err, dfa, &init_nodes, 0) + : NULL); if (__glibc_unlikely (dfa->init_state == NULL)) - return err; - if (dfa->init_state->has_constraint) + { + /* Don't check ERR here, as the initial state must not be null. */ + } + else if (dfa->init_state->has_constraint) { dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_WORD); @@ -1025,17 +1029,13 @@ create_initial_state (re_dfa_t *dfa) &init_nodes, CONTEXT_NEWLINE | CONTEXT_BEGBUF); - if (__glibc_unlikely (dfa->init_state_word == NULL - || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL)) - return err; } else dfa->init_state_word = dfa->init_state_nl = dfa->init_state_begbuf = dfa->init_state; re_node_set_free (&init_nodes); - return REG_NOERROR; + return err; } /* If it is possible to do searching in single byte encoding instead of UTF-8 @@ -1677,12 +1677,11 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) { err = duplicate_node_closure (dfa, node, node, node, dfa->nodes[node].constraint); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; } /* Expand each epsilon destination nodes. */ - if (IS_EPSILON_NODE(dfa->nodes[node].type)) + if (__glibc_likely (err == REG_NOERROR) + && IS_EPSILON_NODE (dfa->nodes[node].type)) for (i = 0; i < dfa->edests[node].nelem; ++i) { re_node_set eclosure_elem; @@ -1700,14 +1699,14 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) { err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false); if (__glibc_unlikely (err != REG_NOERROR)) - return err; + break; } else eclosure_elem = dfa->eclosures[edest]; /* Merge the epsilon closure of 'edest'. */ err = re_node_set_merge (&eclosure, &eclosure_elem); if (__glibc_unlikely (err != REG_NOERROR)) - return err; + break; /* If the epsilon closure of 'edest' is incomplete, the epsilon closure of this node is also incomplete. */ if (dfa->eclosures[edest].nelem == 0) @@ -1717,12 +1716,18 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) } } - if (incomplete && !root) - dfa->eclosures[node].nelem = 0; + if (err != REG_NOERROR) + re_node_set_free (&eclosure); else - dfa->eclosures[node] = eclosure; - *new_set = eclosure; - return REG_NOERROR; + { + if (incomplete && !root) + dfa->eclosures[node].nelem = 0; + else + dfa->eclosures[node] = eclosure; + *new_set = eclosure; + } + + return err; } /* Functions for token which are used in the parser. */