[05/17] Regex: Avoid memory leaks.

Message ID 201712080916.vB89Gx7D005499@skeeve.com
State New, archived
Headers

Commit Message

Arnold Robbins Dec. 8, 2017, 9:16 a.m. UTC
  This patch avoids possible memory leaks if errors are encountered
while compiling a regular expression.

2017-11-27         Arnold D. Robbins     <arnold@skeeve.com>

	* posix/regex_internal.c (re_dfa_add_node): Avoid memory leaks.
	* posix/regcomp.c (build_range_exp): Ditto.
	(build_charclass_op): Ditto.
  

Comments

Paul Eggert Dec. 19, 2017, 10:37 p.m. UTC | #1
On 12/08/2017 01:16 AM, Arnold Robbins wrote:
> +                 if (new_array_start != NULL)
> +                     re_free(new_array_start);

For this rarely-used code, it's better to omit the first line and simply 
call re_free unconditionally, as this is simpler and likely will make 
for fewer instructions in the executable. re_free will do the right 
thing if new_array_start is NULL.

Aside from that, this patch is essentially the same as:

https://git.savannah.gnu.org/cgit/gnulib.git/commit/?id=9e849a708308b73064cd965de022d357e3abda80

which is already installed in Gnulib.
  

Patch

diff --git a/posix/regcomp.c b/posix/regcomp.c
index 5bb1d11..c1fd23b 100644
--- a/posix/regcomp.c
+++ b/posix/regcomp.c
@@ -2699,7 +2699,14 @@  build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
 					new_nranges);
 
 	    if (BE (new_array_start == NULL || new_array_end == NULL, 0))
+              {
+                 /* if one is not NULL, free it to avoid leaks */
+                 if (new_array_start != NULL)
+                     re_free(new_array_start);
+                 if (new_array_end != NULL)
+                     re_free(new_array_end);
 	      return REG_ESPACE;
+	      }
 
 	    mbcset->range_starts = new_array_start;
 	    mbcset->range_ends = new_array_end;
@@ -3604,6 +3611,13 @@  build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
   if (BE (sbcset == NULL, 0))
 #endif /* not RE_ENABLE_I18N */
     {
+      /* if one is not NULL, free it to avoid leaks */
+      if (sbcset != NULL)
+         free(sbcset);
+#ifdef RE_ENABLE_I18N
+      if (mbcset != NULL)
+         free(mbcset);
+#endif
       *err = REG_ESPACE;
       return NULL;
     }
diff --git a/posix/regex_internal.c b/posix/regex_internal.c
index 705d6a4..506ccad 100644
--- a/posix/regex_internal.c
+++ b/posix/regex_internal.c
@@ -1423,7 +1423,18 @@  re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
       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))
+        {
+	   /* if any are not NULL, free them, avoid leaks */
+	   if (new_nexts != NULL)
+              re_free(new_nexts);
+	   if (new_indices != NULL)
+              re_free(new_indices);
+	   if (new_edests != NULL)
+              re_free(new_edests);
+	   if (new_eclosures != NULL)
+              re_free(new_eclosures);
 	return -1;
+	}
       dfa->nexts = new_nexts;
       dfa->org_indices = new_indices;
       dfa->edests = new_edests;