Skip to content

Commit

Permalink
Fix 'command -x' on macOS, Linux, Solaris
Browse files Browse the repository at this point in the history
'command -x' (basically builtin xargs for 'command') worked for
long argument lists on *BSD and HP-UX, but not on macOS and Linux,
where it reliably entered into an infinite loop.

The problem was that it assumed that every byte of the environment
space can be used for arguments, without accounting for alignment
that some OSs do. MacOS seems to be the most wasteful one: it
aligns on 16-byte boundaries and requires some extra bytes per
argument as well.

src/cmd/ksh93/sh/path.c:
- path_xargs(): When calculating how much space to subtract per
  argument, add 16 extra bytes to the length of each argument, then
  align the result on 16-byte boundaries. The extra 16 bytes is
  more than even macOS needs, but hopefully it is future-proof.
- path_spawn(): If path_xargs() does fail, do not enter a retry
  loop (which always becomes an infinite loop if the argument list
  exceeds OS limitations), but abort with an error message.
  • Loading branch information
McDutchie committed Aug 16, 2020
1 parent 35ad5e6 commit acf84e9
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 3 deletions.
6 changes: 6 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ For full details, see the git log at: https://github.com/ksh93/ksh

Any uppercase BUG_* names are modernish shell bug IDs.

2020-08-16:

- Fixed 'command -x' on macOS, Linux and Solaris by accounting for a 16-byte
argument alignment. If execution does fail, it now aborts with an internal
error message instead of entering an infinite retry loop.

2020-08-13:

- Fixed memory leaks and a crashing bug that occurred when defining and
Expand Down
9 changes: 6 additions & 3 deletions src/cmd/ksh93/sh/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,12 @@ static pid_t path_xargs(Shell_t *shp,const char *path, char *argv[],char *const
shp->exitval = 0;
while(av<avlast)
{
/* for each argument, account for terminating zero and 16-byte alignment */
for(xv=av,left=size; left>0 && av<avlast;)
left -= strlen(*av++)+1;
{
n = strlen(*av++) + 1 + 16;
left -= n + n % 16;
}
/* leave at least two for last */
if(left<0 && (avlast-av)<2)
av--;
Expand Down Expand Up @@ -1178,7 +1182,6 @@ pid_t path_spawn(Shell_t *shp,const char *opath,register char **argv, char **env
#endif /* SHELLMAGIC */
if(pid>0)
return(pid);
retry:
switch(shp->path_err = errno)
{
case ENOEXEC:
Expand Down Expand Up @@ -1238,7 +1241,7 @@ pid_t path_spawn(Shell_t *shp,const char *opath,register char **argv, char **env
{
pid = path_xargs(shp,opath, &argv[0] ,envp,spawn);
if(pid<0)
goto retry;
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),"%s: 'command -x' failed",path);
return(pid);
}
default:
Expand Down

0 comments on commit acf84e9

Please sign in to comment.