diff --git a/NEWS b/NEWS index ad0b6ec15..03426fa0e 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,9 @@ Any uppercase BUG_* names are modernish shell bug IDs. - Fixed a bug that caused the -b/--notify option to only notify on one job if more than one background job completed at the same time. +- Fixed a bug in the 'command -x' feature introduced on 2021-01-30; it is meant + to always run an external command, but failed to bypass path-bound builtins. + 2022-07-21: - Fixed a bug where a reproducible $RANDOM sequence (after assigning a diff --git a/src/cmd/ksh93/sh/path.c b/src/cmd/ksh93/sh/path.c index 50d6ad864..4eeee6a35 100644 --- a/src/cmd/ksh93/sh/path.c +++ b/src/cmd/ksh93/sh/path.c @@ -757,7 +757,7 @@ Pathcomp_t *path_absolute(register const char *name, Pathcomp_t *pp, int flag) int n; #endif /* Handle default path-bound builtins */ - if(*stakptr(PATH_OFFSET)=='/' && nv_search(stakptr(PATH_OFFSET),sh.bltin_tree,0)) + if(!sh_isstate(SH_XARG) && *stakptr(PATH_OFFSET)=='/' && nv_search(stakptr(PATH_OFFSET),sh.bltin_tree,0)) return(oldpp); #if SHOPT_DYNAMIC /* Load builtins from dynamic libraries */ @@ -1054,7 +1054,7 @@ pid_t path_spawn(const char *opath,register char **argv, char **envp, Pathcomp_t char *s, *v; int r, n, pidsize; pid_t pid= -1; - if(nv_search(opath,sh.bltin_tree,0)) + if(!sh_isstate(SH_XARG) && nv_search(opath,sh.bltin_tree,0)) { /* Found a path-bound built-in. Since this was not caught earlier in sh_exec(), it must have been found on a temporarily assigned PATH, as with 'PATH=/opt/ast/bin:$PATH cat'. diff --git a/src/cmd/ksh93/tests/path.sh b/src/cmd/ksh93/tests/path.sh index 35f7624d2..d4263213f 100755 --- a/src/cmd/ksh93/tests/path.sh +++ b/src/cmd/ksh93/tests/path.sh @@ -518,6 +518,15 @@ then "(expected $(printf %q "$exp"), got $(printf %q "$got"))" fi +# Check that adding '-x' runs an external command, also bypassing path-bound builtins +if ! test -x /opt/ast/bin/cat # a physical external utility here would invalidate these tests +then + got=$( PATH=/opt/ast/bin; command -x cat --about 2>&1 ) + [[ $got == *version*'cat ('* ]] && err_exit 'command -x fails to bypass path-bound built-in found in PATH search' + got=$( command -x /opt/ast/bin/cat --about 2>&1 ) + [[ $got == *version*'cat ('* ]] && err_exit 'command -x fails to bypass path-bound built-in by direct pathname' +fi + # ====== # 'command -x' used to hang in an endless E2BIG loop on Linux and macOS ofile=$tmp/command_x_chunks.sh