1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Fix crash in backtick comsubs with job control on (rhbz#825520)

This imports another fix from Red Hat/Fedora. Original patch:
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.
This commit is contained in:
Martijn Dekker 2020-09-23 01:56:09 +02:00
parent f7ffaaba17
commit ce68e1be37
7 changed files with 32 additions and 3 deletions

5
NEWS
View file

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

View file

@ -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 */
};

View file

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

View file

@ -1803,6 +1803,7 @@ again:
{
count = bp->count;
jp = bp->list;
jpold = 0;
goto again;
}
if(jp)

View file

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

View file

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

View file

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