Created
March 6, 2023 21:03
-
-
Save LeSuisse/13fd9665087a4cc1725c685f85a6fff8 to your computer and use it in GitHub Desktop.
Backport of 6e98a8184b52173cf961cc4052bdd81c33b04244 to gawk-5.1-stable
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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