[git commit] ash: eval: Do not cache value of eflag in evaltree

Denys Vlasenko vda.linux at googlemail.com
Tue Sep 7 00:01:03 UTC 2021


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

Upsteam commit:

    Date: Mon, 17 May 2021 15:19:23 +0800
    eval: Do not cache value of eflag in evaltree

    Patrick Brünn <P.Bruenn at beckhoff.com> wrote:
    > Since we are migrating to Debian bullseye, we discovered a new behavior
    > with our scripts, which look like this:
    >>cleanup() {
    >>        set +e
    >>        rmdir ""
    >>}
    >>set -eu
    >>trap 'cleanup' EXIT INT TERM
    >>echo 'Hello world!'
    >
    > With old dash v0.5.10.2 this script would return 0 as we expected it.
    > But since commit 62cf6955f8abe875752d7163f6f3adbc7e49ebae it returns
    > the last exit code of our cleanup function.
    ...
    Thanks for the report.  This is actually a fairly old bug with
    set -e that's just been exposed by the exit status change.  What's
    really happening is that cleanup itself is triggering a set -e
    exit incorrectly because evaltree cached the value of eflag prior
    to the function call.

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/ash.c                                  | 15 +++++++--------
 shell/ash_test/ash-misc/exitcode_trap7.right |  2 ++
 shell/ash_test/ash-misc/exitcode_trap7.tests |  7 +++++++
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/shell/ash.c b/shell/ash.c
index 2d2c09ba5..c65f09782 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -9336,8 +9336,7 @@ evaltree(union node *n, int flags)
 	case NCMD:
 		evalfn = evalcommand;
  checkexit:
-		if (!(flags & EV_TESTED))
-			checkexit = ~0;
+		checkexit = ~flags & EV_TESTED;
 		goto calleval;
 	case NFOR:
 		evalfn = evalfor;
@@ -9359,7 +9358,6 @@ evaltree(union node *n, int flags)
 	case NAND:
 	case NOR:
 	case NSEMI: {
-
 #if NAND + 1 != NOR
 #error NAND + 1 != NOR
 #endif
@@ -9387,8 +9385,7 @@ evaltree(union node *n, int flags)
 		if (!status) {
 			n = n->nif.ifpart;
 			goto evaln;
-		}
-		if (n->nif.elsepart) {
+		} else if (n->nif.elsepart) {
 			n = n->nif.elsepart;
 			goto evaln;
 		}
@@ -9410,7 +9407,7 @@ evaltree(union node *n, int flags)
 	 */
 	dotrap();
 
-	if (checkexit & status) {
+	if (checkexit && status) {
 		if (trap[NTRAP_ERR] && !in_trap_ERR) {
 			int err;
 			struct jmploc *volatile savehandler = exception_handler;
@@ -9434,10 +9431,12 @@ evaltree(union node *n, int flags)
 			exitstatus = savestatus;
 		}
 		if (eflag)
-			raise_exception(EXEND);
+			goto exexit;
 	}
-	if (flags & EV_EXIT)
+	if (flags & EV_EXIT) {
+ exexit:
 		raise_exception(EXEND);
+	}
 
 	popstackmark(&smark);
 	TRACE(("leaving evaltree (no interrupts)\n"));
diff --git a/shell/ash_test/ash-misc/exitcode_trap7.right b/shell/ash_test/ash-misc/exitcode_trap7.right
new file mode 100644
index 000000000..07d66e9d9
--- /dev/null
+++ b/shell/ash_test/ash-misc/exitcode_trap7.right
@@ -0,0 +1,2 @@
+Start
+Ok:0
diff --git a/shell/ash_test/ash-misc/exitcode_trap7.tests b/shell/ash_test/ash-misc/exitcode_trap7.tests
new file mode 100755
index 000000000..9772a7b8c
--- /dev/null
+++ b/shell/ash_test/ash-misc/exitcode_trap7.tests
@@ -0,0 +1,7 @@
+$THIS_SH -c '
+cleanup() { set +e; false; }
+set -eu
+trap cleanup EXIT
+echo Start
+'
+echo Ok:$?


More information about the busybox-cvs mailing list