Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save LeSuisse/13fd9665087a4cc1725c685f85a6fff8 to your computer and use it in GitHub Desktop.
Save LeSuisse/13fd9665087a4cc1725c685f85a6fff8 to your computer and use it in GitHub Desktop.
Backport of 6e98a8184b52173cf961cc4052bdd81c33b04244 to gawk-5.1-stable
From e8195a4628f94592a6c9e64672c5f42648a7f090 Mon Sep 17 00:00:00 2001
Date: Mon, 27 Feb 2023 21:32:29 +0200
Subject: [PATCH] Fix memory leak when $a = $b appears in expressions.
(cherry picked from commit 6e98a8184b52173cf961cc4052bdd81c33b04244)
---
awk.h | 1 +
awkgram.c | 29 ++++++++++-------------------
awkgram.y | 29 ++++++++++-------------------
eval.c | 1 +
interpret.h | 5 +++++
profile.c | 19 ++++++++++++++++---
6 files changed, 43 insertions(+), 41 deletions(-)
diff --git a/awk.h b/awk.h
index ca648087..186e58ff 100644
--- a/awk.h
+++ b/awk.h
@@ -625,6 +625,7 @@ typedef enum opcodeval {
Op_store_var, /* simple variable assignment optimization */
Op_store_sub, /* array[subscript] assignment optimization */
Op_store_field, /* $n assignment optimization */
+ Op_store_field_exp, /* $n assignment optimization in an expression */
Op_assign_times,
Op_assign_quotient,
Op_assign_mod,
diff --git a/awkgram.c b/awkgram.c
index 117f338f..8483189f 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -8369,7 +8369,8 @@ mk_assignment(INSTRUCTION *lhs, INSTRUCTION *rhs, INSTRUCTION *op)
else
ip = lhs;
- (void) list_append(ip, op);
+ if (tp->opcode != Op_field_spec_lhs || op->opcode != Op_assign)
+ (void) list_append(ip, op);
if (tp->opcode == Op_push_lhs
&& tp->memory->type == Node_var
@@ -8381,9 +8382,14 @@ mk_assignment(INSTRUCTION *lhs, INSTRUCTION *rhs, INSTRUCTION *op)
(void) list_append(ip, instruction(Op_var_assign));
ip->lasti->assign_var = tp->memory->var_assign;
} else if (tp->opcode == Op_field_spec_lhs) {
- (void) list_append(ip, instruction(Op_field_assign));
- ip->lasti->field_assign = (Func_ptr) 0;
- tp->target_assign = ip->lasti;
+ if (op->opcode == Op_assign) {
+ bcfree(op);
+ tp->opcode = Op_store_field_exp;
+ } else {
+ (void) list_append(ip, instruction(Op_field_assign));
+ ip->lasti->field_assign = (Func_ptr) 0;
+ tp->target_assign = ip->lasti;
+ }
} else if (tp->opcode == Op_subscript_lhs) {
(void) list_append(ip, instruction(Op_subscript_assign));
}
@@ -8476,21 +8482,6 @@ optimize_assignment(INSTRUCTION *exp)
}
break;
- case Op_field_spec_lhs:
- if (i2->nexti->opcode == Op_assign
- && i2->nexti->nexti == i1
- && i1->opcode == Op_field_assign
- ) {
- /* $n = .. */
- i2->opcode = Op_store_field;
- bcfree(i2->nexti); /* Op_assign */
- i2->nexti = NULL;
- bcfree(i1); /* Op_field_assign */
- exp->lasti = i2; /* update Op_list */
- return exp;
- }
- break;
-
case Op_push_array:
if (i2->nexti->nexti->opcode == Op_subscript_lhs) {
i3 = i2->nexti->nexti;
diff --git a/awkgram.y b/awkgram.y
index d9dbaa71..a8aee3e1 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -5861,7 +5861,8 @@ mk_assignment(INSTRUCTION *lhs, INSTRUCTION *rhs, INSTRUCTION *op)
else
ip = lhs;
- (void) list_append(ip, op);
+ if (tp->opcode != Op_field_spec_lhs || op->opcode != Op_assign)
+ (void) list_append(ip, op);
if (tp->opcode == Op_push_lhs
&& tp->memory->type == Node_var
@@ -5873,9 +5874,14 @@ mk_assignment(INSTRUCTION *lhs, INSTRUCTION *rhs, INSTRUCTION *op)
(void) list_append(ip, instruction(Op_var_assign));
ip->lasti->assign_var = tp->memory->var_assign;
} else if (tp->opcode == Op_field_spec_lhs) {
- (void) list_append(ip, instruction(Op_field_assign));
- ip->lasti->field_assign = (Func_ptr) 0;
- tp->target_assign = ip->lasti;
+ if (op->opcode == Op_assign) {
+ bcfree(op);
+ tp->opcode = Op_store_field_exp;
+ } else {
+ (void) list_append(ip, instruction(Op_field_assign));
+ ip->lasti->field_assign = (Func_ptr) 0;
+ tp->target_assign = ip->lasti;
+ }
} else if (tp->opcode == Op_subscript_lhs) {
(void) list_append(ip, instruction(Op_subscript_assign));
}
@@ -5968,21 +5974,6 @@ optimize_assignment(INSTRUCTION *exp)
}
break;
- case Op_field_spec_lhs:
- if (i2->nexti->opcode == Op_assign
- && i2->nexti->nexti == i1
- && i1->opcode == Op_field_assign
- ) {
- /* $n = .. */
- i2->opcode = Op_store_field;
- bcfree(i2->nexti); /* Op_assign */
- i2->nexti = NULL;
- bcfree(i1); /* Op_field_assign */
- exp->lasti = i2; /* update Op_list */
- return exp;
- }
- break;
-
case Op_push_array:
if (i2->nexti->nexti->opcode == Op_subscript_lhs) {
i3 = i2->nexti->nexti;
diff --git a/eval.c b/eval.c
index 013ee062..3807a0aa 100644
--- a/eval.c
+++ b/eval.c
@@ -295,6 +295,7 @@ static struct optypetab {
{ "Op_store_var", " = " },
{ "Op_store_sub", " = " },
{ "Op_store_field", " = " },
+ { "Op_store_field_exp", " = " },
{ "Op_assign_times", " *= " },
{ "Op_assign_quotient", " /= " },
{ "Op_assign_mod", " %= " },
diff --git a/interpret.h b/interpret.h
index bda9a01e..444a1122 100644
--- a/interpret.h
+++ b/interpret.h
@@ -761,6 +761,7 @@ mod:
break;
case Op_store_field:
+ case Op_store_field_exp:
{
/* field assignment optimization,
* see awkgram.y (optimize_assignment)
@@ -783,6 +784,10 @@ mod:
UNFIELD(*lhs, r);
/* field variables need the string representation: */
force_string(*lhs);
+ if (op == Op_store_field_exp) {
+ UPREF(*lhs);
+ PUSH(*lhs);
+ }
}
break;
diff --git a/profile.c b/profile.c
index 13e13e6f..3b50ae26 100644
--- a/profile.c
+++ b/profile.c
@@ -544,15 +544,28 @@ cleanup:
break;
case Op_store_field:
+ case Op_store_field_exp:
+ {
+ char *assignment, *final;
+
t1 = pp_pop(); /* field num */
if (is_binary(t1->type))
pp_parenthesize(t1);
t2 = pp_pop(); /* r.h.s. */
- fprintf(prof_fp, "$%s%s%s", t1->pp_str, op2str(pc->opcode), t2->pp_str);
+ assignment = pp_group3(t1->pp_str, op2str(pc->opcode), t2->pp_str);
+ final = pp_group3("$", assignment, "");
+ efree(assignment);
pp_free(t2);
pp_free(t1);
- if ((flags & IN_FOR_HEADER) == 0)
- pc = end_line(pc);
+ if (pc->opcode == Op_store_field_exp)
+ pp_push(pc->opcode, final, CAN_FREE, NULL);
+ else {
+ fprintf(prof_fp, "%s", final);
+ efree(final);
+ if ((flags & IN_FOR_HEADER) == 0)
+ pc = end_line(pc);
+ }
+ }
break;
case Op_concat:
--
2.39.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment