1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Fix $LINENO corruption when autoloading functions

Autoloading a function caused the calling script's $LINENO to be
off by the number of lines in the function definition file. In
addition, while running autoloaded functions, errors/warnings were
reported with wrong line numbers.

src/cmd/ksh93/sh/path.c:
- Save $LINENO (shp->inlineno) before autoloading a function, reset
  it to 1 so that the correct line number offset is remembered for
  the function definition, and restore it after.

src/cmd/ksh93/tests/variables.sh:
- Add regression test for $LINENO, directly and in error messages,
  within and outside a non-autoloaded and an autoloaded function.

Fixes: https://github.com/ksh93/ksh/issues/116
This commit is contained in:
Martijn Dekker 2020-10-01 06:13:00 +02:00
parent be22f3759e
commit d89ef0fafa
3 changed files with 54 additions and 1 deletions

4
NEWS
View file

@ -14,6 +14,10 @@ Any uppercase BUG_* names are modernish shell bug IDs.
nonzero exit status. Similarly, if both the 'errexit' and 'pipefail' options nonzero exit status. Similarly, if both the 'errexit' and 'pipefail' options
are active, ksh now correctly exits if any pipeline element returns nonzero. are active, ksh now correctly exits if any pipeline element returns nonzero.
- Autoloading a function no longer causes the calling script's $LINENO to be
off by the number of lines in the function definition file that was loaded.
This also corrects line numbers in warnings and error messages.
2020-09-28: 2020-09-28:
- While executing a ksh-style function, ksh 93u+ ignored all signals for which - While executing a ksh-style function, ksh 93u+ ignored all signals for which

View file

@ -582,7 +582,7 @@ static void funload(Shell_t *shp,int fno, const char *name)
char *pname,*oldname=shp->st.filename, buff[IOBSIZE+1]; char *pname,*oldname=shp->st.filename, buff[IOBSIZE+1];
Namval_t *np; Namval_t *np;
struct Ufunction *rp,*rpfirst; struct Ufunction *rp,*rpfirst;
int savestates = sh_getstate(), oldload=shp->funload; int savestates = sh_getstate(), oldload=shp->funload, savelineno = shp->inlineno;
pname = path_fullname(shp,stakptr(PATH_OFFSET)); pname = path_fullname(shp,stakptr(PATH_OFFSET));
if(shp->fpathdict && (rp = dtmatch(shp->fpathdict,(void*)pname))) if(shp->fpathdict && (rp = dtmatch(shp->fpathdict,(void*)pname)))
{ {
@ -615,6 +615,7 @@ static void funload(Shell_t *shp,int fno, const char *name)
shp->readscript = (char*)name; shp->readscript = (char*)name;
shp->st.filename = pname; shp->st.filename = pname;
shp->funload = 1; shp->funload = 1;
shp->inlineno = 1;
error_info.line = 0; error_info.line = 0;
sh_eval(sfnew(NIL(Sfio_t*),buff,IOBSIZE,fno,SF_READ),SH_FUNEVAL); sh_eval(sfnew(NIL(Sfio_t*),buff,IOBSIZE,fno,SF_READ),SH_FUNEVAL);
sh_close(fno); sh_close(fno);
@ -631,6 +632,7 @@ static void funload(Shell_t *shp,int fno, const char *name)
pname = 0; pname = 0;
free((void*)shp->st.filename); free((void*)shp->st.filename);
shp->funload = oldload; shp->funload = oldload;
shp->inlineno = savelineno;
shp->st.filename = oldname; shp->st.filename = oldname;
sh_setstate(savestates); sh_setstate(savestates);
if(pname) if(pname)

View file

@ -1130,5 +1130,52 @@ case $'\n'$(env 'BASH_FUNC_a%%=() { echo test; }' "$SHELL" -c set) in
err_exit 'ksh imports environment variables with invalid names' ;; err_exit 'ksh imports environment variables with invalid names' ;;
esac esac
# ======
# Autoloading a function caused $LINENO to be off by the # of lines in the function definition file.
# https://github.com/ksh93/ksh/issues/116
cd "$tmp" || exit 128
cat >lineno_autoload <<'EOF'
echo "begin: main script \$LINENO == $LINENO"
function main_script_fn
{
lineno_autoload_fn
(: ${bad\subst\in\main_script_fn\on\line\5})
}
main_script_fn
(eval 'syntax error(')
(: ${bad\subst\in\main\script\on\line\9})
echo "end: main script \$LINENO == $LINENO"
EOF
cat >lineno_autoload_fn <<'EOF'
function lineno_autoload_fn
{
echo "Hi, I'm a function! On line 3, my \$LINENO is $LINENO"
(: ${bad\subst\in\function\on\line\4})
(eval 'syntax error(')
echo "Hi, I'm still a function! On line 6, my \$LINENO is $LINENO"
}
echo "In definition file, outside function: \$LINENO on line 8 is $LINENO"
: ${bad\subst\in\def\file\on\line\9}
EOF
exp="begin: main script \$LINENO == 1
In definition file, outside function: \$LINENO on line 8 is 8
./lineno_autoload[7]: main_script_fn: line 9: \${bad\subst\in\def\file\on\line\9}: bad substitution
Hi, I'm a function! On line 3, my \$LINENO is 3
./lineno_autoload[7]: main_script_fn[4]: lineno_autoload_fn: line 4: \${bad\subst\in\function\on\line\4}: bad substitution
./lineno_autoload[7]: main_script_fn[4]: lineno_autoload_fn[5]: eval: syntax error at line 1: \`(' unexpected
Hi, I'm still a function! On line 6, my \$LINENO is 6
./lineno_autoload[7]: main_script_fn: line 5: \${bad\subst\in\main_script_fn\on\line\5}: bad substitution
./lineno_autoload[8]: eval: syntax error at line 1: \`(' unexpected
./lineno_autoload: line 9: \${bad\subst\in\main\script\on\line\9}: bad substitution
end: main script \$LINENO == 10"
got=$(FPATH=$tmp "$SHELL" ./lineno_autoload 2>&1)
[[ $got == "$exp" ]] || err_exit 'Regression in \$LINENO and/or error messages.' \
$'Diff follows:\n'"$(diff -u <(print -r -- "$exp") <(print -r -- "$got") | sed $'s/^/\t| /')"
# ====== # ======
exit $((Errors<125?Errors:125)) exit $((Errors<125?Errors:125))