[git commit] hush: fix ELIF cmd1; cmd2 THEN ... not executing cmd2, closes 15571

Denys Vlasenko vda.linux at googlemail.com
Thu May 25 12:22:10 UTC 2023


commit: https://git.busybox.net/busybox/commit/?id=6824298ab4d3da40763af4d2d466a72745b8b593
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
run_list                                            1012    1024     +12

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/ash_test/ash-misc/elif1.right   |  4 ++++
 shell/ash_test/ash-misc/elif1.tests   |  6 ++++++
 shell/ash_test/ash-misc/elif2.right   |  2 ++
 shell/ash_test/ash-misc/elif2.tests   |  8 ++++++++
 shell/hush.c                          | 24 ++++++++++++++++--------
 shell/hush_test/hush-misc/elif1.right |  4 ++++
 shell/hush_test/hush-misc/elif1.tests |  6 ++++++
 shell/hush_test/hush-misc/elif2.right |  2 ++
 shell/hush_test/hush-misc/elif2.tests |  8 ++++++++
 9 files changed, 56 insertions(+), 8 deletions(-)

diff --git a/shell/ash_test/ash-misc/elif1.right b/shell/ash_test/ash-misc/elif1.right
new file mode 100644
index 000000000..36dc59fed
--- /dev/null
+++ b/shell/ash_test/ash-misc/elif1.right
@@ -0,0 +1,4 @@
+ELIF1
+ELIF2
+ELIF THEN
+Ok:0
diff --git a/shell/ash_test/ash-misc/elif1.tests b/shell/ash_test/ash-misc/elif1.tests
new file mode 100755
index 000000000..77b8a25ea
--- /dev/null
+++ b/shell/ash_test/ash-misc/elif1.tests
@@ -0,0 +1,6 @@
+if false; then
+    :
+elif echo 'ELIF1'; echo 'ELIF2'; then
+    echo "ELIF THEN"
+fi
+echo "Ok:$?"
diff --git a/shell/ash_test/ash-misc/elif2.right b/shell/ash_test/ash-misc/elif2.right
new file mode 100644
index 000000000..8f2851f91
--- /dev/null
+++ b/shell/ash_test/ash-misc/elif2.right
@@ -0,0 +1,2 @@
+THEN
+Ok:0
diff --git a/shell/ash_test/ash-misc/elif2.tests b/shell/ash_test/ash-misc/elif2.tests
new file mode 100755
index 000000000..3e5876f05
--- /dev/null
+++ b/shell/ash_test/ash-misc/elif2.tests
@@ -0,0 +1,8 @@
+if true; then
+    echo "THEN"
+elif echo "ELIF false"; false; then
+    echo "ELIF THEN"
+else
+    echo "ELSE"
+fi
+echo "Ok:$?"
diff --git a/shell/hush.c b/shell/hush.c
index 810dafd35..1f7b58d4f 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -9758,7 +9758,7 @@ static int run_list(struct pipe *pi)
 	smallint last_rword; /* ditto */
 #endif
 
-	debug_printf_exec("run_list start lvl %d\n", G.run_list_level);
+	debug_printf_exec("run_list lvl %d start\n", G.run_list_level);
 	debug_enter();
 
 #if ENABLE_HUSH_LOOPS
@@ -9817,7 +9817,7 @@ static int run_list(struct pipe *pi)
 			break;
 
 		IF_HAS_KEYWORDS(rword = pi->res_word;)
-		debug_printf_exec(": rword=%d cond_code=%d last_rword=%d\n",
+		debug_printf_exec(": rword:%d cond_code:%d last_rword:%d\n",
 				rword, cond_code, last_rword);
 
 		sv_errexit_depth = G.errexit_depth;
@@ -9851,23 +9851,29 @@ static int run_list(struct pipe *pi)
 			}
 		}
 		last_followup = pi->followup;
-		IF_HAS_KEYWORDS(last_rword = rword;)
 #if ENABLE_HUSH_IF
-		if (cond_code) {
+		if (cond_code != 0) {
 			if (rword == RES_THEN) {
 				/* if false; then ... fi has exitcode 0! */
 				G.last_exitcode = rcode = EXIT_SUCCESS;
 				/* "if <false> THEN cmd": skip cmd */
+				debug_printf_exec("skipped THEN cmd because IF condition was false\n");
+				last_rword = rword;
 				continue;
 			}
 		} else {
-			if (rword == RES_ELSE || rword == RES_ELIF) {
+			if (rword == RES_ELSE
+			 || (rword == RES_ELIF && last_rword != RES_ELIF)
+			) {
 				/* "if <true> then ... ELSE/ELIF cmd":
 				 * skip cmd and all following ones */
+				debug_printf_exec("skipped ELSE/ELIF branch because IF condition was true\n");
 				break;
 			}
+			//if (rword == RES_THEN): "if <true> THEN cmd", run cmd (fall through)
 		}
 #endif
+		IF_HAS_KEYWORDS(last_rword = rword;)
 #if ENABLE_HUSH_LOOPS
 		if (rword == RES_FOR) { /* && pi->num_cmds - always == 1 */
 			if (!for_lcur) {
@@ -9943,7 +9949,7 @@ static int run_list(struct pipe *pi)
 				);
 				/* TODO: which FNM_xxx flags to use? */
 				cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
-				debug_printf_exec("fnmatch(pattern:'%s',str:'%s'):%d\n",
+				debug_printf_exec("cond_code=fnmatch(pattern:'%s',str:'%s'):%d\n",
 						pattern, case_word, cond_code);
 				free(pattern);
 				if (cond_code == 0) {
@@ -10069,8 +10075,10 @@ static int run_list(struct pipe *pi)
 
 		/* Analyze how result affects subsequent commands */
 #if ENABLE_HUSH_IF
-		if (rword == RES_IF || rword == RES_ELIF)
+		if (rword == RES_IF || rword == RES_ELIF) {
+			debug_printf_exec("cond_code=rcode:%d\n", rcode);
 			cond_code = rcode;
+		}
 #endif
  check_jobs_and_continue:
 		checkjobs(NULL, 0 /*(no pid to wait for)*/);
@@ -10111,7 +10119,7 @@ static int run_list(struct pipe *pi)
 	free(case_word);
 #endif
 	debug_leave();
-	debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level + 1, rcode);
+	debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level, rcode);
 	return rcode;
 }
 
diff --git a/shell/hush_test/hush-misc/elif1.right b/shell/hush_test/hush-misc/elif1.right
new file mode 100644
index 000000000..36dc59fed
--- /dev/null
+++ b/shell/hush_test/hush-misc/elif1.right
@@ -0,0 +1,4 @@
+ELIF1
+ELIF2
+ELIF THEN
+Ok:0
diff --git a/shell/hush_test/hush-misc/elif1.tests b/shell/hush_test/hush-misc/elif1.tests
new file mode 100755
index 000000000..77b8a25ea
--- /dev/null
+++ b/shell/hush_test/hush-misc/elif1.tests
@@ -0,0 +1,6 @@
+if false; then
+    :
+elif echo 'ELIF1'; echo 'ELIF2'; then
+    echo "ELIF THEN"
+fi
+echo "Ok:$?"
diff --git a/shell/hush_test/hush-misc/elif2.right b/shell/hush_test/hush-misc/elif2.right
new file mode 100644
index 000000000..8f2851f91
--- /dev/null
+++ b/shell/hush_test/hush-misc/elif2.right
@@ -0,0 +1,2 @@
+THEN
+Ok:0
diff --git a/shell/hush_test/hush-misc/elif2.tests b/shell/hush_test/hush-misc/elif2.tests
new file mode 100755
index 000000000..3e5876f05
--- /dev/null
+++ b/shell/hush_test/hush-misc/elif2.tests
@@ -0,0 +1,8 @@
+if true; then
+    echo "THEN"
+elif echo "ELIF false"; false; then
+    echo "ELIF THEN"
+else
+    echo "ELSE"
+fi
+echo "Ok:$?"


More information about the busybox-cvs mailing list