1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 03:32:24 +00:00

Fix 'command -x' on macOS, Linux, Solaris

'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.
This commit is contained in:
Martijn Dekker 2020-08-16 09:08:07 +01:00
parent 35ad5e65af
commit acf84e9633
2 changed files with 12 additions and 3 deletions

6
NEWS
View file

@ -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

View file

@ -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--;
@ -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:
@ -1238,7 +1241,7 @@ retry:
{
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: