aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-12-21 20:29:34 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-12-21 20:29:34 +0100
commit19eee8ed7cf32de37afa53ce56c62376c880a5a8 (patch)
tree7a7e952d4f28af8b9ab7361093d40ac3a935c3ba
parent5d57bc442dfebefdd7db37c04fe2c9f1343bd08d (diff)
downloadbusybox-w32-19eee8ed7cf32de37afa53ce56c62376c880a5a8.tar.gz
busybox-w32-19eee8ed7cf32de37afa53ce56c62376c880a5a8.tar.bz2
busybox-w32-19eee8ed7cf32de37afa53ce56c62376c880a5a8.zip
bc: fix for() to not leave data on stack
function old new delta zbc_parse_stmt_possibly_auto 1665 1697 +32 zbc_vm_process 672 701 +29 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 61/0) Total: 61 bytes text data bss dec hex filename 981656 485 7296 989437 f18fd busybox_old 981748 485 7296 989529 f1959 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--miscutils/bc.c48
-rwxr-xr-xtestsuite/bc.tests15
2 files changed, 38 insertions, 25 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c
index 50e5457b9..441cb0467 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -170,6 +170,8 @@
170#define DEBUG_LEXER 0 170#define DEBUG_LEXER 0
171#define DEBUG_COMPILE 0 171#define DEBUG_COMPILE 0
172#define DEBUG_EXEC 0 172#define DEBUG_EXEC 0
173// This can be left enabled for production as well:
174#define SANITY_CHECKS 1
173 175
174#if DEBUG_LEXER 176#if DEBUG_LEXER
175static uint8_t lex_indent; 177static uint8_t lex_indent;
@@ -1218,8 +1220,6 @@ static char** bc_program_const(size_t idx)
1218 IF_DC(return bc_vec_item(&G.prog.consts, idx);) 1220 IF_DC(return bc_vec_item(&G.prog.consts, idx);)
1219} 1221}
1220 1222
1221
1222
1223static int bc_id_cmp(const void *e1, const void *e2) 1223static int bc_id_cmp(const void *e1, const void *e2)
1224{ 1224{
1225 return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name); 1225 return strcmp(((const BcId *) e1)->name, ((const BcId *) e2)->name);
@@ -4227,12 +4227,15 @@ static BC_STATUS zbc_parse_for(BcParse *p)
4227 s = zbc_lex_next(&p->l); 4227 s = zbc_lex_next(&p->l);
4228 if (s) RETURN_STATUS(s); 4228 if (s) RETURN_STATUS(s);
4229 4229
4230 if (p->l.t.t != BC_LEX_SCOLON) 4230 if (p->l.t.t != BC_LEX_SCOLON) {
4231 s = zbc_parse_expr(p, 0); 4231 s = zbc_parse_expr(p, 0);
4232 else 4232 bc_parse_push(p, BC_INST_POP);
4233 if (s) RETURN_STATUS(s);
4234 } else {
4233 s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init"); 4235 s = bc_POSIX_does_not_allow_empty_X_expression_in_for("init");
4236 IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s);)
4237 }
4234 4238
4235 if (s) RETURN_STATUS(s);
4236 if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); 4239 if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token());
4237 s = zbc_lex_next(&p->l); 4240 s = zbc_lex_next(&p->l);
4238 if (s) RETURN_STATUS(s); 4241 if (s) RETURN_STATUS(s);
@@ -4254,8 +4257,8 @@ static BC_STATUS zbc_parse_for(BcParse *p)
4254 bc_parse_pushNUM(p); 4257 bc_parse_pushNUM(p);
4255 s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition"); 4258 s = bc_POSIX_does_not_allow_empty_X_expression_in_for("condition");
4256 } 4259 }
4257
4258 if (s) RETURN_STATUS(s); 4260 if (s) RETURN_STATUS(s);
4261
4259 if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token()); 4262 if (p->l.t.t != BC_LEX_SCOLON) RETURN_STATUS(bc_error_bad_token());
4260 4263
4261 s = zbc_lex_next(&p->l); 4264 s = zbc_lex_next(&p->l);
@@ -4267,12 +4270,14 @@ static BC_STATUS zbc_parse_for(BcParse *p)
4267 bc_vec_push(&p->conds, &update_idx); 4270 bc_vec_push(&p->conds, &update_idx);
4268 bc_vec_push(&p->func->labels, &p->func->code.len); 4271 bc_vec_push(&p->func->labels, &p->func->code.len);
4269 4272
4270 if (p->l.t.t != BC_LEX_RPAREN) 4273 if (p->l.t.t != BC_LEX_RPAREN) {
4271 s = zbc_parse_expr(p, 0); 4274 s = zbc_parse_expr(p, 0);
4272 else 4275 bc_parse_push(p, BC_INST_POP);
4276 if (s) RETURN_STATUS(s);
4277 } else {
4273 s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update"); 4278 s = bc_POSIX_does_not_allow_empty_X_expression_in_for("update");
4274 4279 IF_ERROR_RETURN_POSSIBLE(if (s) RETURN_STATUS(s);)
4275 if (s) RETURN_STATUS(s); 4280 }
4276 4281
4277 if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token()); 4282 if (p->l.t.t != BC_LEX_RPAREN) RETURN_STATUS(bc_error_bad_token());
4278 bc_parse_pushJUMP(p, cond_idx); 4283 bc_parse_pushJUMP(p, cond_idx);
@@ -6434,12 +6439,13 @@ static BC_STATUS zbc_program_exec(void)
6434 BcFunc *func = bc_program_func(ip->func); 6439 BcFunc *func = bc_program_func(ip->func);
6435 char *code = func->code.v; 6440 char *code = func->code.v;
6436 6441
6437 dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->idx); 6442 dbg_exec("func:%zd bytes:%zd ip:%zd results.len:%d",
6443 ip->func, func->code.len, ip->idx, G.prog.results.len);
6438 while (ip->idx < func->code.len) { 6444 while (ip->idx < func->code.len) {
6439 BcStatus s = BC_STATUS_SUCCESS; 6445 BcStatus s = BC_STATUS_SUCCESS;
6440 char inst = code[ip->idx++]; 6446 char inst = code[ip->idx++];
6441 6447
6442 dbg_exec("inst at %zd:%d", ip->idx - 1, inst); 6448 dbg_exec("inst at %zd:%d results.len:%d", ip->idx - 1, inst, G.prog.results.len);
6443 switch (inst) { 6449 switch (inst) {
6444#if ENABLE_BC 6450#if ENABLE_BC
6445 case BC_INST_JUMP_ZERO: { 6451 case BC_INST_JUMP_ZERO: {
@@ -6671,7 +6677,6 @@ static BC_STATUS zbc_program_exec(void)
6671 } 6677 }
6672 6678
6673 fflush_and_check(); 6679 fflush_and_check();
6674
6675 } 6680 }
6676 6681
6677 RETURN_STATUS(BC_STATUS_SUCCESS); 6682 RETURN_STATUS(BC_STATUS_SUCCESS);
@@ -6723,23 +6728,16 @@ static BC_STATUS zbc_vm_process(const char *text)
6723 // storage. 6728 // storage.
6724 if (IS_BC) { 6729 if (IS_BC) {
6725 BcFunc *f; 6730 BcFunc *f;
6726 BcInstPtr *ip; 6731 BcInstPtr *ip = (void*)G.prog.exestack.v;
6727
6728 //FIXME: this does not clear up the stack
6729 //for(i=1; i<3; i++) {
6730 // i
6731 // if(i==2) continue
6732 // 77
6733 //}
6734// if (G.prog.results.len != 0)
6735// bb_error_msg_and_die("data stack not empty: %d slots", G.prog.results.len);
6736 6732
6733#if SANITY_CHECKS
6734 if (G.prog.results.len != 0)
6735 bb_error_msg_and_die("data stack not empty: %d slots", G.prog.results.len);
6737 if (G.prog.exestack.len != 1) // should be empty 6736 if (G.prog.exestack.len != 1) // should be empty
6738 bb_error_msg_and_die("BUG:call stack"); 6737 bb_error_msg_and_die("BUG:call stack");
6739
6740 ip = (void*)G.prog.exestack.v;
6741 if (ip->func != BC_PROG_MAIN) 6738 if (ip->func != BC_PROG_MAIN)
6742 bb_error_msg_and_die("BUG:not MAIN"); 6739 bb_error_msg_and_die("BUG:not MAIN");
6740#endif
6743//bb_error_msg("ip->func:%d >idx:%d >len:%d", ip->func, ip->idx, ip->len); 6741//bb_error_msg("ip->func:%d >idx:%d >len:%d", ip->func, ip->idx, ip->len);
6744 f = bc_program_func_BC_PROG_MAIN(); 6742 f = bc_program_func_BC_PROG_MAIN();
6745//bb_error_msg("MAIN->code.len:%d >strs.len:%d >consts.len:%d", f->code.len, f->strs.len, f->consts.len); // labels, autos, nparams 6743//bb_error_msg("MAIN->code.len:%d >strs.len:%d >consts.len:%d", f->code.len, f->strs.len, f->consts.len); // labels, autos, nparams
diff --git a/testsuite/bc.tests b/testsuite/bc.tests
index edff209bb..b3ce894ee 100755
--- a/testsuite/bc.tests
+++ b/testsuite/bc.tests
@@ -56,6 +56,21 @@ testing "bc for(;;)" \
56 "2\n3\n2\n9\n" \ 56 "2\n3\n2\n9\n" \
57 "" "i=2; for (;;) { 2; if(--i==0) break; 3; }; 9" 57 "" "i=2; for (;;) { 2; if(--i==0) break; 3; }; 9"
58 58
59testing "bc for (;cond;)" \
60 "bc" \
61 "1\n2\n3\n9\n" \
62 "" "i=0; for(;i<3;)++i; 9"
63
64testing "bc for (;cond;upd)" \
65 "bc" \
66 "1\n2\n3\n9\n" \
67 "" "i=1; for(;i<4;i++)i; 9"
68
69testing "bc for (init;cond;upd)" \
70 "bc" \
71 "1\n2\n3\n9\n" \
72 "" "for(i=1;i<4;i++)i; 9"
73
59testing "bc define auto" \ 74testing "bc define auto" \
60 "bc" \ 75 "bc" \
61 "8\n9\n" \ 76 "8\n9\n" \