aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-01-07 01:19:08 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-01-07 01:19:08 +0100
commit6f4a785bd1bd0e6973b5c27b34b86655b1d7a602 (patch)
treef7c5acf0f2f844883e5e183b45d85ba0ee5471df
parent7367a949a6a81d71d524f0635a212371120df4e0 (diff)
downloadbusybox-w32-6f4a785bd1bd0e6973b5c27b34b86655b1d7a602.tar.gz
busybox-w32-6f4a785bd1bd0e6973b5c27b34b86655b1d7a602.tar.bz2
busybox-w32-6f4a785bd1bd0e6973b5c27b34b86655b1d7a602.zip
awk: fix 'delete array[var--]' decrementing var twice
function old new delta evaluate 3395 3390 -5 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--editors/awk.c54
-rwxr-xr-xtestsuite/awk.tests19
2 files changed, 50 insertions, 23 deletions
diff --git a/editors/awk.c b/editors/awk.c
index d40c7816a..8f523ea28 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -2514,6 +2514,32 @@ static var *evaluate(node *op, var *res)
2514 op1 = op->l.n; 2514 op1 = op->l.n;
2515 debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn); 2515 debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn);
2516 2516
2517 /* "delete" is special:
2518 * "delete array[var--]" must evaluate index expr only once,
2519 * must not evaluate it in "execute inevitable things" part.
2520 */
2521 if (XC(opinfo & OPCLSMASK) == XC(OC_DELETE)) {
2522 uint32_t info = op1->info & OPCLSMASK;
2523 var *v;
2524
2525 debug_printf_eval("DELETE\n");
2526 if (info == OC_VAR) {
2527 v = op1->l.v;
2528 } else if (info == OC_FNARG) {
2529 v = &fnargs[op1->l.aidx];
2530 } else {
2531 syntax_error(EMSG_NOT_ARRAY);
2532 }
2533 if (op1->r.n) { /* array ref? */
2534 const char *s;
2535 s = getvar_s(evaluate(op1->r.n, v1));
2536 hash_remove(iamarray(v), s);
2537 } else {
2538 clear_array(iamarray(v));
2539 }
2540 goto next;
2541 }
2542
2517 /* execute inevitable things */ 2543 /* execute inevitable things */
2518 if (opinfo & OF_RES1) 2544 if (opinfo & OF_RES1)
2519 L.v = evaluate(op1, v1); 2545 L.v = evaluate(op1, v1);
@@ -2621,28 +2647,7 @@ static var *evaluate(node *op, var *res)
2621 break; 2647 break;
2622 } 2648 }
2623 2649
2624 case XC( OC_DELETE ): { 2650 /* case XC( OC_DELETE ): - moved to happen before arg evaluation */
2625 uint32_t info = op1->info & OPCLSMASK;
2626 var *v;
2627
2628 if (info == OC_VAR) {
2629 v = op1->l.v;
2630 } else if (info == OC_FNARG) {
2631 v = &fnargs[op1->l.aidx];
2632 } else {
2633 syntax_error(EMSG_NOT_ARRAY);
2634 }
2635
2636 if (op1->r.n) {
2637 const char *s;
2638 clrvar(L.v);
2639 s = getvar_s(evaluate(op1->r.n, v1));
2640 hash_remove(iamarray(v), s);
2641 } else {
2642 clear_array(iamarray(v));
2643 }
2644 break;
2645 }
2646 2651
2647 case XC( OC_NEWSOURCE ): 2652 case XC( OC_NEWSOURCE ):
2648 g_progname = op->l.new_progname; 2653 g_progname = op->l.new_progname;
@@ -2666,12 +2671,14 @@ static var *evaluate(node *op, var *res)
2666 /* -- recursive node type -- */ 2671 /* -- recursive node type -- */
2667 2672
2668 case XC( OC_VAR ): 2673 case XC( OC_VAR ):
2674 debug_printf_eval("VAR\n");
2669 L.v = op->l.v; 2675 L.v = op->l.v;
2670 if (L.v == intvar[NF]) 2676 if (L.v == intvar[NF])
2671 split_f0(); 2677 split_f0();
2672 goto v_cont; 2678 goto v_cont;
2673 2679
2674 case XC( OC_FNARG ): 2680 case XC( OC_FNARG ):
2681 debug_printf_eval("FNARG[%d]\n", op->l.aidx);
2675 L.v = &fnargs[op->l.aidx]; 2682 L.v = &fnargs[op->l.aidx];
2676 v_cont: 2683 v_cont:
2677 res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v; 2684 res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v;
@@ -3035,7 +3042,8 @@ static var *evaluate(node *op, var *res)
3035 3042
3036 default: 3043 default:
3037 syntax_error(EMSG_POSSIBLE_ERROR); 3044 syntax_error(EMSG_POSSIBLE_ERROR);
3038 } 3045 } /* switch */
3046 next:
3039 if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS) 3047 if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS)
3040 op = op->a.n; 3048 op = op->a.n;
3041 if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS) 3049 if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS)
diff --git a/testsuite/awk.tests b/testsuite/awk.tests
index 82937bc10..ad0583afb 100755
--- a/testsuite/awk.tests
+++ b/testsuite/awk.tests
@@ -261,6 +261,25 @@ end d
261" \ 261" \
262 "" "" 262 "" ""
263 263
264prg='
265BEGIN{
266cnt = 0
267a[cnt] = "zeroth"
268a[++cnt] = "first"
269delete a[cnt--]
270print cnt
271print "[0]:" a[0]
272print "[1]:" a[1]
273}'
274testing "awk 'delete a[v--]' evaluates v-- once" \
275 "awk '$prg'" \
276 "\
2770
278[0]:zeroth
279[1]:
280" \
281 "" ""
282
264testing "awk handles empty ()" \ 283testing "awk handles empty ()" \
265 "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" "" 284 "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" ""
266 285