From ab98ec65e4ce0efb06de4b07dae7a359895c4ef9 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Fri, 8 Jan 2021 16:35:26 +0000 Subject: [PATCH] Replace safe FD fix with Solaris/ksh2020 version (re: 045fe6a1) 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: https://github.com/att/ast/issues/198 https://github.com/att/ast/pull/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. --- src/cmd/ksh93/sh/io.c | 20 +++++++++++++------- src/cmd/ksh93/tests/subshell.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/cmd/ksh93/sh/io.c b/src/cmd/ksh93/sh/io.c index a433fff5177d..8104c9614f43 100644 --- a/src/cmd/ksh93/sh/io.c +++ b/src/cmd/ksh93/sh/io.c @@ -436,22 +436,28 @@ int sh_iovalidfd(Shell_t *shp, int fd) return(1); } -int sh_iosafefd(Shell_t* shp, int sfd) +/* + * Return the lowest numbered fd that is equal to or greater than + * the requested 'min_fd' and which is not currently in use. + */ +int sh_iosafefd(Shell_t* shp, int min_fd) { register int fd; while(1) { - for(fd=0; fd < shp->topfd; fd++) + if(fcntl(min_fd, F_GETFD) == -1) { - if (filemap[fd].save_fd==sfd || filemap[fd].orig_fd==sfd || (fcntl(sfd, F_GETFD) != -1 || errno != EBADF)) + for(fd = 0; fd < shp->topfd; fd++) { - sfd++; - continue; + if (filemap[fd].save_fd == min_fd || filemap[fd].orig_fd == min_fd) + break; } + if(fd == shp->topfd) + break; } - break; + min_fd++; } - return(sfd); + return(min_fd); } int sh_inuse(Shell_t *shp, int fd) diff --git a/src/cmd/ksh93/tests/subshell.sh b/src/cmd/ksh93/tests/subshell.sh index 9489a78c2a3e..7837a06cf3fe 100755 --- a/src/cmd/ksh93/tests/subshell.sh +++ b/src/cmd/ksh93/tests/subshell.sh @@ -854,6 +854,32 @@ actual=${ get_value; } actual=`get_value` [[ $actual == "$expect" ]] || err_exit "\`Comsub\` failed to return output (expected '$expect', got '$actual')" +# more tests from https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/285-30771135.patch +tmpfile=$tmp/1116072.dummy +touch "$tmpfile" +exp='return value' +function get_value +{ + case=$1 + (( case >= 1 )) && exec 3< $tmpfile + (( case >= 2 )) && exec 4< $tmpfile + (( case >= 3 )) && exec 6< $tmpfile + # To trigger the bug we have to spawn an external command. + $(whence -p true) + (( case >= 1 )) && exec 3<&- + (( case >= 2 )) && exec 4<&- + (( case >= 3 )) && exec 6<&- + print "$exp" +} +got=$(get_value 0) +[[ $got == "$exp" ]] || err_exit "failed to capture subshell output when closing fd: case 0" +got=$(get_value 1) +[[ $got == "$exp" ]] || err_exit "failed to capture subshell output when closing fd: case 1" +got=$(get_value 2) +[[ $got == "$exp" ]] || err_exit "failed to capture subshell output when closing fd: case 2" +got=$(get_value 3) +[[ $got == "$exp" ]] || err_exit "failed to capture subshell output when closing fd: case 3" + # ====== # https://bugzilla.redhat.com/1117404