summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2020-01-08 20:40:45 +0200
committerArnold D. Robbins <arnold@skeeve.com>2020-01-08 20:40:45 +0200
commit660a55b365e4ee22f3f0efe69c887e2fd1f71303 (patch)
tree5c56f2d517b145627e1d637676d2b6177e6ad168
parentd0b68138521e670178068999dc308ce5beace7ef (diff)
downloadgawk-660a55b365e4ee22f3f0efe69c887e2fd1f71303.tar.gz
Fix a number of memory leaks.
-rw-r--r--ChangeLog16
-rw-r--r--builtin.c46
-rw-r--r--debug.c3
-rw-r--r--field.c7
-rw-r--r--interpret.h5
-rw-r--r--test/ChangeLog5
-rw-r--r--test/indirectbuiltin.awk4
-rw-r--r--test/numrange.awk4
-rw-r--r--test/numrange.ok4
9 files changed, 78 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 290ae9b9..32aa228d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2020-01-08 Arnold D. Robbins <arnold@skeeve.com>
+
+ Fix a number of subtle memory leaks. Thanks to the
+ combination of MEMDEBUG and valgrind for finding them.
+
+ * builtin.c (do_print): Unref tmp if force_string_ofmt
+ returned something different.
+ (call_sub, call_match, call_split_func): Free any
+ created regexp.
+ * debug.c (do_eval): Free the node holding the @eval function
+ when done with it.
+ * field.c (init_fields): Create fields_arr[0] and Nnull_field
+ in a rational fashion.
+ * interpret.h (Op_assign_concat): Handle newly created node
+ better.
+
2019-12-22 Arnold D. Robbins <arnold@skeeve.com>
* config.guess: Updated from GNULIB.
diff --git a/builtin.c b/builtin.c
index 0bd94bf9..e09a48bd 100644
--- a/builtin.c
+++ b/builtin.c
@@ -2270,6 +2270,8 @@ do_print(int nargs, int redirtype)
// Let force_string_ofmt handle checking if things
// are already valid.
args_array[i] = force_string_ofmt(tmp);
+ if (args_array[i] != tmp)
+ DEREF(tmp);
}
if (redir_exp != NULL) {
@@ -3236,6 +3238,7 @@ call_sub(const char *name, int nargs)
flags = GSUB;
}
+ bool need_free = false;
if (flags == 0 || flags == GSUB) {
/* sub or gsub */
if (nargs != 2)
@@ -3250,8 +3253,10 @@ call_sub(const char *name, int nargs)
*/
if ((regex->flags & REGEX) != 0)
regex = regex->typed_re;
- else
+ else {
regex = make_regnode(Node_regex, regex);
+ need_free = true;
+ }
PUSH(regex);
PUSH(replace);
lhs = r_get_field(zero, (Func_ptr *) 0, true);
@@ -3277,8 +3282,10 @@ call_sub(const char *name, int nargs)
*/
if ((regex->flags & REGEX) != 0)
regex = regex->typed_re;
- else
+ else {
regex = make_regnode(Node_regex, regex);
+ need_free = true;
+ }
PUSH(regex);
PUSH(replace);
PUSH(glob_flag);
@@ -3295,6 +3302,14 @@ call_sub(const char *name, int nargs)
unref(zero);
result = do_sub(nargs, flags);
+
+ if (need_free) {
+ refree(regex->re_reg[0]);
+ if (regex->re_reg[1] != NULL)
+ refree(regex->re_reg[1]);
+ freenode(regex);
+ }
+
if (flags != GENSUB)
reset_record();
return result;
@@ -3315,10 +3330,13 @@ call_match(int nargs)
/* Don't need to pop the string just to push it back ... */
+ bool need_free = false;
if ((regex->flags & REGEX) != 0)
regex = regex->typed_re;
- else
+ else {
regex = make_regnode(Node_regex, regex);
+ need_free = true;
+ }
PUSH(regex);
@@ -3326,6 +3344,14 @@ call_match(int nargs)
PUSH(array);
result = do_match(nargs);
+
+ if (need_free) {
+ refree(regex->re_reg[0]);
+ if (regex->re_reg[1] != NULL)
+ refree(regex->re_reg[1]);
+ freenode(regex);
+ }
+
return result;
}
@@ -3345,18 +3371,23 @@ call_split_func(const char *name, int nargs)
if (nargs == 4)
seps = POP();
+ bool need_free = false;
if (nargs >= 3) {
regex = POP_STRING();
if ((regex->flags & REGEX) != 0)
regex = regex->typed_re;
- else
+ else {
regex = make_regnode(Node_regex, regex);
+ need_free = true;
+ }
} else {
if (name[0] == 's') {
regex = make_regnode(Node_regex, FS_node->var_value);
regex->re_flags |= FS_DFLT;
} else
regex = make_regnode(Node_regex, FPAT_node->var_value);
+
+ need_free = true;
nargs++;
}
@@ -3369,6 +3400,13 @@ call_split_func(const char *name, int nargs)
result = (name[0] == 's') ? do_split(nargs) : do_patsplit(nargs);
+ if (need_free) {
+ refree(regex->re_reg[0]);
+ if (regex->re_reg[1] != NULL)
+ refree(regex->re_reg[1]);
+ freenode(regex);
+ }
+
return result;
}
diff --git a/debug.c b/debug.c
index 19874284..632d025e 100644
--- a/debug.c
+++ b/debug.c
@@ -5718,6 +5718,9 @@ do_eval(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
unref(s);
}
+ free(f->vname);
+ freenode(f);
+
free_srcfile(the_source);
return false;
diff --git a/field.c b/field.c
index 28891c85..9eee2948 100644
--- a/field.c
+++ b/field.c
@@ -94,16 +94,13 @@ init_fields()
{
emalloc(fields_arr, NODE **, sizeof(NODE *), "init_fields");
- getnode(fields_arr[0]);
- *fields_arr[0] = *Nnull_string;
+ fields_arr[0] = make_string("", 0);
fields_arr[0]->flags |= NULL_FIELD;
parse_extent = fields_arr[0]->stptr;
save_FS = dupnode(FS_node->var_value);
- getnode(Null_field);
- *Null_field = *Nnull_string;
- Null_field->valref = 1;
+ Null_field = make_string("", 0);
Null_field->flags = (STRCUR|STRING|NULL_FIELD); /* do not set MALLOC */
field0_valid = true;
diff --git a/interpret.h b/interpret.h
index 6cfff3a6..4a7979bd 100644
--- a/interpret.h
+++ b/interpret.h
@@ -741,7 +741,10 @@ mod:
if (t1 != *lhs) {
unref(*lhs);
- *lhs = dupnode(t1);
+ if (t1->valref == 1)
+ *lhs = t1;
+ else
+ *lhs = dupnode(t1);
}
if (t1 != t2 && t1->valref == 1 && (t1->flags & (MALLOC|MPFN|MPZN)) == MALLOC) {
diff --git a/test/ChangeLog b/test/ChangeLog
index 9ff97b2e..f0eac9bd 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,8 @@
+2020-01-08 Arnold D. Robbins <arnold@skeeve.com>
+
+ * indirectbuiltin.awk, numrange.awk, numrange.ok: Changes
+ after code changes.
+
2019-11-09 Alexey Pawlow <alexey.pawlow@gmail.com>
* Makefile.am (mbprintf5): Add check for MSYS.
diff --git a/test/indirectbuiltin.awk b/test/indirectbuiltin.awk
index c9e75217..8ca8f6c6 100644
--- a/test/indirectbuiltin.awk
+++ b/test/indirectbuiltin.awk
@@ -198,10 +198,10 @@ BEGIN {
# regexp functions
fun = "match"
- b1 = match("o+", "fooob")
+ b1 = match("fooob", "o+")
rstart = RSTART
rlength = RLENGTH
- i1 = @fun("o+", "fooob")
+ i1 = @fun("fooob", "o+")
print_result("regexp", fun, b1, i1)
if (rstart != RSTART) {
printf("match: failure: biRSTART (%d) != iRSTART (%d)\n",
diff --git a/test/numrange.awk b/test/numrange.awk
index 3ad2cab5..4cb62602 100644
--- a/test/numrange.awk
+++ b/test/numrange.awk
@@ -1,5 +1,5 @@
BEGIN {
n = split("-1.2e+931 1.2e+931", a)
- for (i=1; i<=n; ++i)
- print a[i], +a[i]
+ for (i = 1; i <= n; ++i)
+ print a[i], +a[i], -a[i]
}
diff --git a/test/numrange.ok b/test/numrange.ok
index 73210bd3..1d747530 100644
--- a/test/numrange.ok
+++ b/test/numrange.ok
@@ -1,2 +1,2 @@
--1.2e+931 -inf
-1.2e+931 +inf
+-1.2e+931 -inf +inf
+1.2e+931 +inf -inf