From 0dd115e4b43d35d8d56e5d579dacc2fbc682be6b Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Wed, 19 May 2021 06:53:56 +0200 Subject: [PATCH] Fix shell exit on function call redirection error (re: 23f2e23) This regression also exists on ksh 93v- and ksh2020, from which it was backported. Reproducer: $ (fn() { true; }; fn >/dev/null/ne; true) 2>/dev/null; echo $? 1 Expected output: 0 (as on ksh 93u+). FreeBSD sh and NetBSD sh are the only other known shells that share this behaviour. POSIX currently allows both behaviours, but may require the ksh 93u+ behaviour in future. In any case, this causes an incompatibility with established ksh behaviour that could easily break existing ksh scripts. src/cmd/ksh93/sh/xec.c: sh_exec(): - Commit 23f2e23 introduced a check for jmpval > SH_JMPIO (5). When a function call pushes context for a redirection, this is done with the jmpval exit value of SH_JMPCMD (6). Change that to SH_JMPIO to avoid triggering that check. src/cmd/ksh93/tests/exit.sh: - Add regression tests for exit behaviour on various kinds of shell errors as listed in the POSIX standard, including an error in a redirection of a function call. Fixes: https://github.com/ksh93/ksh/issues/310 --- NEWS | 3 +++ src/cmd/ksh93/sh/xec.c | 2 +- src/cmd/ksh93/tests/exit.sh | 52 +++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index e0d06810e..3fea6662b 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,9 @@ Any uppercase BUG_* names are modernish shell bug IDs. - Fixed SHLVL so that replacing ksh by itself (exec ksh) will not increase it. +- Fixed a regression introduced on 2020-08-05 that caused a non-interactive + shell to exit if an I/O redirection of a function call encountered an error. + 2021-05-13: - Fixed a bug with 'test -t 1' that was introduced on 2021-04-26: diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index 898f414c8..71b753676 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -1550,7 +1550,7 @@ int sh_exec(register const Shnode_t *t, int flags) if(io) { indx = shp->topfd; - sh_pushcontext(shp,buffp,SH_JMPCMD); + sh_pushcontext(shp,buffp,SH_JMPIO); jmpval = sigsetjmp(buffp->buff,0); } if(jmpval == 0) diff --git a/src/cmd/ksh93/tests/exit.sh b/src/cmd/ksh93/tests/exit.sh index 882808500..1dbd07461 100755 --- a/src/cmd/ksh93/tests/exit.sh +++ b/src/cmd/ksh93/tests/exit.sh @@ -127,5 +127,57 @@ exp=1 [[ $exp == $status ]] || err_exit 'bare exit after false' \ "(expected '$exp', got '$status')" +# ====== +# Exit behaviour for commands, expansions and assignments +# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_01 + +builtin -s | while read cmd +do + [[ $cmd == : ]] && continue # ':' never errors out + ("$cmd" --badoption; true) 2>/dev/null \ + && err_exit "Special built-in utility error does not cause shell to exit ($cmd)" + (command "$cmd" --badoption; true) 2>/dev/null \ + || err_exit "Error in special built-in utility prefixed by 'command' causes shell to exit ($cmd)" +done + +(command shift 10; true) 2>/dev/null \ +|| err_exit "Regular built-in utility error causes shell to exit" + +(readonly foo=bar; foo=baz; true) 2>/dev/null \ +&& err_exit "Variable assignment error does not cause shell to exit" + +(command true ${foo@bar}; true) 2>/dev/null \ +&& err_exit "Expansion error does not cause shell to exit" + +(/dev/null/nonexistent; true) 2>/dev/null \ +|| err_exit "Command not found causes shell to exit" + +# Exit behaviour for redirections + +(>/dev/null/nonexistent; true) 2>/dev/null \ +|| err_exit 'Error in lone redirection causes shell to exit' + +(: >/dev/null/nonexistent; true) 2>/dev/null \ +&& err_exit 'Redirection error with special built-in utility does not cause shell to exit' + +(false >/dev/null/nonexistent; true) 2>/dev/null \ +|| err_exit 'Redirection error with regular built-in utility causes shell to exit' + +("$(whence -p false)" >/dev/null/nonexistent; true) 2>/dev/null \ +|| err_exit 'Redirection error with external command causes shell to exit' + +(/dev/null/nonexistent >/dev/null/nonexistent; true) 2>/dev/null \ +|| err_exit 'Redirection error with nonexistent command causes shell to exit' + +(foo=bar >/dev/null/nonexistent; true) 2>/dev/null \ +|| err_exit 'Redirection error with variable assignment causes shell to exit' + +({ false; }; >/dev/null/nonexistent; true) 2>/dev/null \ +|| err_exit 'Redirection error with compound command causes shell to exit' + +# https://github.com/ksh93/ksh/issues/310 +(fn() { false; }; fn >/dev/null/nonexistent; true) 2>/dev/null \ +|| err_exit 'Redirection error with function execution causes shell to exit' + # ====== exit $((Errors<125?Errors:125))