Skip to content

Commit ab98ec6

Browse files
committed
Replace safe FD fix with Solaris/ksh2020 version (re: 045fe6a)
This pulls a new version of sh_iosafefd() from: https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/285-30771135.patch It was written by Kurtis Rader for ksh2020: att#198 att#199 It is presumably better than the Red Hat version and also comes with more regression test cases (although it still doesn't fix modernish BUG_CSUBSTDO, which remains in the TODO file). This commit does not go along with other peripheral changes from that patch, i.e. a different name and location of this function. src/cmd/ksh93/sh/io.c: - Replace sh_iosafefd() as above. src/cmd/ksh93/tests/subshell.sh: - Add and tweak tests from the patch.
1 parent 17ebfbf commit ab98ec6

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

src/cmd/ksh93/sh/io.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -436,22 +436,28 @@ int sh_iovalidfd(Shell_t *shp, int fd)
436436
return(1);
437437
}
438438

439-
int sh_iosafefd(Shell_t* shp, int sfd)
439+
/*
440+
* Return the lowest numbered fd that is equal to or greater than
441+
* the requested 'min_fd' and which is not currently in use.
442+
*/
443+
int sh_iosafefd(Shell_t* shp, int min_fd)
440444
{
441445
register int fd;
442446
while(1)
443447
{
444-
for(fd=0; fd < shp->topfd; fd++)
448+
if(fcntl(min_fd, F_GETFD) == -1)
445449
{
446-
if (filemap[fd].save_fd==sfd || filemap[fd].orig_fd==sfd || (fcntl(sfd, F_GETFD) != -1 || errno != EBADF))
450+
for(fd = 0; fd < shp->topfd; fd++)
447451
{
448-
sfd++;
449-
continue;
452+
if (filemap[fd].save_fd == min_fd || filemap[fd].orig_fd == min_fd)
453+
break;
450454
}
455+
if(fd == shp->topfd)
456+
break;
451457
}
452-
break;
458+
min_fd++;
453459
}
454-
return(sfd);
460+
return(min_fd);
455461
}
456462

457463
int sh_inuse(Shell_t *shp, int fd)

src/cmd/ksh93/tests/subshell.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,32 @@ actual=${ get_value; }
854854
actual=`get_value`
855855
[[ $actual == "$expect" ]] || err_exit "\`Comsub\` failed to return output (expected '$expect', got '$actual')"
856856

857+
# more tests from https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/285-30771135.patch
858+
tmpfile=$tmp/1116072.dummy
859+
touch "$tmpfile"
860+
exp='return value'
861+
function get_value
862+
{
863+
case=$1
864+
(( case >= 1 )) && exec 3< $tmpfile
865+
(( case >= 2 )) && exec 4< $tmpfile
866+
(( case >= 3 )) && exec 6< $tmpfile
867+
# To trigger the bug we have to spawn an external command.
868+
$(whence -p true)
869+
(( case >= 1 )) && exec 3<&-
870+
(( case >= 2 )) && exec 4<&-
871+
(( case >= 3 )) && exec 6<&-
872+
print "$exp"
873+
}
874+
got=$(get_value 0)
875+
[[ $got == "$exp" ]] || err_exit "failed to capture subshell output when closing fd: case 0"
876+
got=$(get_value 1)
877+
[[ $got == "$exp" ]] || err_exit "failed to capture subshell output when closing fd: case 1"
878+
got=$(get_value 2)
879+
[[ $got == "$exp" ]] || err_exit "failed to capture subshell output when closing fd: case 2"
880+
got=$(get_value 3)
881+
[[ $got == "$exp" ]] || err_exit "failed to capture subshell output when closing fd: case 3"
882+
857883
# ======
858884
# https://bugzilla.redhat.com/1117404
859885

0 commit comments

Comments
 (0)