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

Fix handling of skipped directories when autoloading functions

Fix a bug in autoloading functions. Directories in the path search
list which should be skipped (e.g. because they don't exist) did
not interact correctly with autoloaded functions, so that a
function to autoload was not always found.

Details:
https://github.com/att/ast/issues/1454

Fix backported (and cleaned up) from:
3bc58164

src/cmd/ksh93/sh/path.c:
- path_opentype(): Fix the path search loop so that entries marked
  with PATH_SKIP are handled correctly.

src/cmd/ksh93/tests/functions.sh:
- Add regression test verifying an autoloaded function with a PATH
  that triggered the bug.
  The bug in path_opentype() fixed by this commit may affect other
  scenarios but we know it affects autoloaded functions. Hence the
  test for that scenario.

(cherry picked from commit a27903165775309f4f032de5d42ec1785f14cfbc)
This commit is contained in:
Martijn Dekker 2020-05-31 15:29:15 +02:00
parent 482d1c3dd6
commit eee47df423
4 changed files with 49 additions and 7 deletions

8
NEWS
View file

@ -4,6 +4,14 @@ For full details, see the git log at:
Any uppercase BUG_* names are modernish shell bug IDs. Any uppercase BUG_* names are modernish shell bug IDs.
2020-05-31:
- Fix a bug in autoloading functions. Directories in the path search list
which should be skipped (e.g. because they don't exist) did not interact
correctly with autoloaded functions, so that a function to autoload was
not always found correctly.
Details: https://github.com/att/ast/issues/1454
2020-05-30: 2020-05-30:
- Fix POSIX compliance of 'test'/'[' exit status on error. The command now - Fix POSIX compliance of 'test'/'[' exit status on error. The command now

View file

@ -17,4 +17,4 @@
* David Korn <dgk@research.att.com> * * David Korn <dgk@research.att.com> *
* * * *
***********************************************************************/ ***********************************************************************/
#define SH_RELEASE "93u+m 2020-05-30" #define SH_RELEASE "93u+m 2020-05-31"

View file

@ -508,7 +508,8 @@ static int path_opentype(Shell_t *shp,const char *name, register Pathcomp_t *pp,
{ {
register int fd= -1; register int fd= -1;
struct stat statb; struct stat statb;
Pathcomp_t *oldpp; Pathcomp_t *nextpp;
if(!pp && !shp->pathlist) if(!pp && !shp->pathlist)
path_init(shp); path_init(shp);
if(!fun && strchr(name,'/')) if(!fun && strchr(name,'/'))
@ -516,12 +517,15 @@ static int path_opentype(Shell_t *shp,const char *name, register Pathcomp_t *pp,
if(sh_isoption(SH_RESTRICTED)) if(sh_isoption(SH_RESTRICTED))
errormsg(SH_DICT,ERROR_exit(1),e_restricted,name); errormsg(SH_DICT,ERROR_exit(1),e_restricted,name);
} }
nextpp = pp;
do do
{ {
pp = path_nextcomp(shp,oldpp=pp,name,0); pp = nextpp;
while(oldpp && (oldpp->flags&PATH_SKIP)) nextpp = path_nextcomp(shp,pp,name,0);
oldpp = oldpp->next; if(pp && (pp->flags&PATH_SKIP))
if(fun && (!oldpp || !(oldpp->flags&PATH_FPATH))) continue;
if(fun && (!pp || !(pp->flags&PATH_FPATH)))
continue; continue;
if((fd = sh_open(path_relative(shp,stakptr(PATH_OFFSET)),O_RDONLY,0)) >= 0) if((fd = sh_open(path_relative(shp,stakptr(PATH_OFFSET)),O_RDONLY,0)) >= 0)
{ {
@ -533,7 +537,8 @@ static int path_opentype(Shell_t *shp,const char *name, register Pathcomp_t *pp,
} }
} }
} }
while( fd<0 && pp); while(fd<0 && nextpp);
if(fd>=0 && (fd = sh_iomovefd(fd)) > 0) if(fd>=0 && (fd = sh_iomovefd(fd)) > 0)
{ {
fcntl(fd,F_SETFD,FD_CLOEXEC); fcntl(fd,F_SETFD,FD_CLOEXEC);

View file

@ -1213,4 +1213,33 @@ rc=$?
exp=$((256+$(kill -l TERM) )) exp=$((256+$(kill -l TERM) ))
[[ $rc == "$exp" ]] || err_exit "expected exitval $exp got $rc" [[ $rc == "$exp" ]] || err_exit "expected exitval $exp got $rc"
# ======
# Verify that directories in the path search list which should be skipped
# (e.g. because they don't exist) interact correctly with autoloaded functions.
# See https://github.com/att/ast/issues/1454
expect="Func cd called with |$tmp/usr|
$tmp/usr"
actual=$(
set -- wrong args passed
mkdir -p "$tmp/usr/bin"
print 'echo "wrong file executed ($*)"' >"$tmp/usr/bin/cd"
prefix=$tmp/ksh.$$
FPATH=$prefix/bad:$prefix/functions
mkdir -p "$prefix/functions"
print 'function cd { echo "Func cd called with |$*|"; command cd "$@"; }' >"$prefix/functions/cd"
typeset -fu cd
PATH=$tmp/arglebargle:$PATH:$tmp/usr/bin:$tmp/bin
cd "$tmp/usr"
pwd
)
actual_status=$?
expect_status=0
[[ $actual_status == "$expect_status" ]] ||
err_exit "autoload function skipped dir test wrong status (expected $expect_status, got $actual_status)"
[[ $actual == "$expect" ]] ||
err_exit "autoload function skipped dir test wrong output (expected $(printf %q "$expect"), got $(printf %q "$actual"))"
# ======
exit $((Errors<125?Errors:125)) exit $((Errors<125?Errors:125))