Skip to content

Commit

Permalink
Fix crash in backtick comsubs with job control on (rhbz#825520)
Browse files Browse the repository at this point in the history
This imports another fix from Red Hat/Fedora. Original patch:
https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-crash.patch

src/cmd/ksh93/include/jobs.h,
src/cmd/ksh93/sh/jobs.c,
src/cmd/ksh93/sh/subshell.c,
src/cmd/ksh93/sh/xec.c:
- Import the Red Hat fix with these differences:
  - Rename the 'hack1_waitall' variable to 'bktick_waitall' and add
    a comment describing what it's for.
  - Remove unused 'pipefail' variable.

src/cmd/ksh93/tests/basic.sh:
- Regression test from reproducer given in the Red Hat bug report.
- Add special handling to SIGKILL it, as it might freeze hard.
  • Loading branch information
McDutchie committed Sep 22, 2020
1 parent f7ffaab commit ce68e1b
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 3 deletions.
5 changes: 5 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ For full details, see the git log at: https://github.com/ksh93/ksh

Any uppercase BUG_* names are modernish shell bug IDs.

2020-09-23:

- Fixed a crash that could occur when running a pipeline containing
backtick-style command substitutions with job control enabled.

2020-09-21:

- A bug was fixed that caused command substitutions embedded in here-documents
Expand Down
1 change: 1 addition & 0 deletions src/cmd/ksh93/include/jobs.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ struct jobs
char jobcontrol; /* turned on for real job control */
char waitsafe; /* wait will not block */
char waitall; /* wait for all jobs in pipe */
char bktick_waitall; /* wait state for `backtick comsubs` */
char toclear; /* job table needs clearing */
unsigned char *freejobs; /* free jobs numbers */
};
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/include/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#define SH_RELEASE "93u+m 2020-09-21"
#define SH_RELEASE "93u+m 2020-09-23"
1 change: 1 addition & 0 deletions src/cmd/ksh93/sh/jobs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1803,6 +1803,7 @@ static int job_chksave(register pid_t pid)
{
count = bp->count;
jp = bp->list;
jpold = 0;
goto again;
}
if(jp)
Expand Down
4 changes: 4 additions & 0 deletions src/cmd/ksh93/sh/subshell.c
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,10 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
sp->comsub = shp->comsub;
shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE));
if(comsub)
{
shp->comsub = comsub;
job.bktick_waitall = (comsub==1);
}
if(!comsub || !shp->subshare)
{
struct subshell *xp;
Expand Down Expand Up @@ -655,6 +658,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
}
else
{
job.bktick_waitall = 0;
if(comsub!=1 && shp->spid)
{
job_wait(shp->spid);
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/sh/xec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1927,7 +1927,7 @@ int sh_exec(register const Shnode_t *t, int flags)
memset(exitval,0,job.waitall*sizeof(int));
}
else
job.waitall |= !pipejob && sh_isstate(SH_MONITOR);
job.waitall |= (job.bktick_waitall || !pipejob && sh_isstate(SH_MONITOR));
job_lock();
nlock++;
do
Expand Down
20 changes: 19 additions & 1 deletion src/cmd/ksh93/tests/basic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ integer Errors=0

bincat=$(whence -p cat)
binecho=$(whence -p echo)
binfalse=$(whence -p false)
# make an external 'sleep' command that supports fractional seconds
binsleep=$tmp/.sleep.sh # hide to exclude from simple wildcard expansion
cat >"$binsleep" <<EOF
Expand Down Expand Up @@ -418,7 +419,6 @@ expected=foreback
got=$(print -n fore; (sleep .2;print back)&)
[[ $got == $expected ]] || err_exit "command substitution background process output error -- got '$got', expected '$expected'"

binfalse=$(whence -p false)
for false in false $binfalse
do x=$($false) && err_exit "x=\$($false) should fail"
$($false) && err_exit "\$($false) should fail"
Expand Down Expand Up @@ -692,5 +692,23 @@ actual=$(exptest foo)
[[ $actual == "$expect" ]] || err_exit 'Corruption of multibyte char following expansion of single-char name' \
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
# ======
# Crash in job handling code when running backtick-style command substitutions (rhbz#825520)
# The regression sometimes doesn't just crash, but freezes hard, so requires special handling.
cat >$tmp/backtick_crash.ksh <<'EOF'
binfalse=$(whence -p false) || exit
for ((i=0; i<250; i++))
do test -z `"$binfalse" | "$binfalse" | /dev/null/nothing`
done
EOF
"$SHELL" -i "$tmp/backtick_crash.ksh" 2>/dev/null & # run test as bg job
test_pid=$!
(sleep 10; kill -s KILL "$test_pid" 2>/dev/null) & # another bg job to kill frozen test job
sleep_pid=$!
{ wait "$test_pid"; } 2>/dev/null # suppress any crash messages, which 'wait' would print
e=$? # get job's exit status from 'wait'
((!e)) || err_exit "backtick comsub crash/freeze (got status $e$( ((e>128)) && print -n / && kill -l "$e"))"
kill "$sleep_pid" 2>/dev/null
# ======
exit $((Errors<125?Errors:125))

0 comments on commit ce68e1b

Please sign in to comment.