From 2c22ace1e6200e341c6dc018c92a2021bcb06ec2 Mon Sep 17 00:00:00 2001 From: Johnothan King Date: Thu, 22 Apr 2021 11:16:25 -0700 Subject: [PATCH] Fix LINENO after unsetting it a virtual subshell (#283) There is a TODO note in variables.sh that notes the value of LINENO is wrong after a virtual subshell. The following script should print '6', but the bug causes it to print '1' instead: $ cat /tmp/lineno #!/bin/ksh ( unset LINENO : ) echo $LINENO This bug started to occur after the bugfix applied in 7b994b6a. However, that commit is not where the cause of bug was (when that bugfix is applied to ksh versions 2008-07-25 through 2012-01-01, $LINENO works fine). Rather, the cause of this bug was introduced in 93u+ 2012-02-29. In that version, the mp->nvfun pointer was only copied from np->nvfun if the variable can be freed from memory. This is what caused 7b994b6a to break $LINENO in subshells, so to fix this bug the mp->nvfun and np->nvfun must point to the same object, even when the variable isn't freed from memory. src/cmd/ksh93/sh/subshell.c: nv_restore(): - Always copy the np->nvfun pointer to mp->nvfun. To prevent crashes, the value of np->nvfun->nofree is set to the value given by the nofree variable, which is set before _nv_unset. See also commit 7e7f1372, which fixed a crash that happened because _nv_unset discards the NV_NOFREE flag. src/cmd/ksh93/tests/variables.sh: - Remove the workaround for LINENO after a virtual subshell. - Add a regression test for the value of LINENO when unset in a virtual subshell, then used after the subshell. Note that before commit 997ad43b LINENO's value was corrupted after being unset in a subshell, so the test checks for corruption of the LINENO variable (in prior commits LINENO was set to '49' because of the previous bug). --- NEWS | 3 +++ src/cmd/ksh93/sh/subshell.c | 5 +++-- src/cmd/ksh93/tests/variables.sh | 14 +++++++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 4ba1ecdd2..6d8d2f712 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ Any uppercase BUG_* names are modernish shell bug IDs. - shcomp (the shell bytecode compiler) was fixed to correctly compile process substitutions used as the file name to a redirection, as in 'cmd < <(cmd)'. +- Fixed a bug introduced on 2020-07-13 that set LINENO to the wrong line + number after leaving a virtual subshell in which LINENO had been unset. + 2021-04-21: - Fixed a bug introduced on 2020-09-28 that caused an interactive ksh to exit diff --git a/src/cmd/ksh93/sh/subshell.c b/src/cmd/ksh93/sh/subshell.c index 2d555316c..a245523aa 100644 --- a/src/cmd/ksh93/sh/subshell.c +++ b/src/cmd/ksh93/sh/subshell.c @@ -381,8 +381,9 @@ static void nv_restore(struct subshell *sp) nv_setsize(mp,nv_size(np)); if(!(flags&NV_MINIMAL)) mp->nvenv = np->nvenv; - if(!nofree) - mp->nvfun = np->nvfun; + mp->nvfun = np->nvfun; + if(np->nvfun && nofree) + np->nvfun->nofree = nofree; if(nv_isattr(np,NV_IDENT)) { nv_offattr(np,NV_IDENT); diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh index 2797b97fb..c0079382e 100755 --- a/src/cmd/ksh93/tests/variables.sh +++ b/src/cmd/ksh93/tests/variables.sh @@ -720,7 +720,6 @@ set -- unset r v x ( - ulimit -t unlimited 2>/dev/null # TODO: this test messes up LINENO past the subshell unless we fork it x=foo for v in EDITOR VISUAL OPTIND CDPATH FPATH PATH ENV RANDOM SECONDS _ LINENO do nameref r=$v @@ -1272,5 +1271,18 @@ if ((nsecosec+0.1)) then err_exit "SECONDS corrupted after leaving virtual subshell (expected $osec, got $nsec)" fi +# Corruption of LINENO on leaving virtual subshell +lineno_subshell=$tmp/lineno_subshell.sh +cat >| "$lineno_subshell" << 'EOF' +( + unset LINENO + : +) +echo $LINENO +EOF +exp=5 +got=$($SHELL "$lineno_subshell") +[[ $exp == $got ]] || err_exit "LINENO corrupted after leaving virtual subshell (expected $exp, got $got)" + # ====== exit $((Errors<125?Errors:125))