mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
parse.c: fix use-after-free probs related to funstaks()
When the funstaks() function deletes a stack, other code could
still reference that stack's pointer, at least if a script's DEBUG
trap changed the function context by assigning to ${.sh.level}.
This crashed @ormaaj's funcname.ksh script in certain contexts, at
least when run as a dot script or in a virtual subshell.
This allows that script to run in all contexts by making
funstaks(s) set the stack pointer to NULL after deleting the stack
and making various other points in the code check for a null
pointer before dereferencing it.
This may not be the most elegant fix but (in my testing) it does
work, even when compiling ksh with AddressSanitiser.
Thanks to @JohnoKing for help researching this problem.
Resolves: https://github.com/ksh93/ksh/issues/212
This commit is contained in:
parent
4b22fd5d0f
commit
69d37d5eae
4 changed files with 125 additions and 9 deletions
|
|
@ -1400,5 +1400,100 @@ else
|
|||
unset exp
|
||||
fi
|
||||
|
||||
# ======
|
||||
# funcname.ksh crashed
|
||||
# https://github.com/ksh93/ksh/issues/212
|
||||
cat >$tmp/funcname.ksh <<-'EOF'
|
||||
# tweaked version of funname.ksh by Daniel Douglas
|
||||
# https://gist.github.com/ormaaj/12874b68acd06ee98b59
|
||||
# Used by permission: "Consider all my gists MIT / do whatever."
|
||||
# https://github.com/ksh93/ksh/issues/212#issuecomment-807915937
|
||||
|
||||
# run in subshell for additional regression testing
|
||||
(
|
||||
IFS='-' # element separator for "$*" etc., incl. "${FUNCNAME[*]}"
|
||||
typeset -a FUNCNAME
|
||||
|
||||
function FUNCNAME.get {
|
||||
nameref self=${.sh.name}
|
||||
if (( .sh.subscript < .sh.level )); then
|
||||
trap "(( .sh.level -= .sh.subscript + 1 )); eval '(( .sh.level = ${.sh.level} ))' \; _=\${.sh.fun}" DEBUG
|
||||
trap - DEBUG;
|
||||
fi
|
||||
|
||||
(( .sh.subscript < .sh.level - 2 )) && self[.sh.subscript + 1]=
|
||||
}
|
||||
|
||||
function f {
|
||||
if (($1 < 10)); then
|
||||
print -r -- "${FUNCNAME[*]}"
|
||||
g $(($1 + 1))
|
||||
fi
|
||||
print -r -- "${FUNCNAME[*]}"
|
||||
}
|
||||
|
||||
function g {
|
||||
if (($1 < 10)); then
|
||||
print -r -- "${FUNCNAME[*]}"
|
||||
f $(($1 + 1))
|
||||
fi
|
||||
print -r -- "${FUNCNAME[*]}"
|
||||
}
|
||||
|
||||
#typeset -ft FUNCNAME.get f g
|
||||
f 0
|
||||
)
|
||||
: do not optimize out the subshell
|
||||
EOF
|
||||
exp='f
|
||||
g-f
|
||||
f-g-f
|
||||
g-f-g-f
|
||||
f-g-f-g-f
|
||||
g-f-g-f-g-f
|
||||
f-g-f-g-f-g-f
|
||||
g-f-g-f-g-f-g-f
|
||||
f-g-f-g-f-g-f-g-f
|
||||
g-f-g-f-g-f-g-f-g-f
|
||||
f-g-f-g-f-g-f-g-f-g-f
|
||||
g-f-g-f-g-f-g-f-g-f-
|
||||
f-g-f-g-f-g-f-g-f--
|
||||
g-f-g-f-g-f-g-f---
|
||||
f-g-f-g-f-g-f----
|
||||
g-f-g-f-g-f-----
|
||||
f-g-f-g-f------
|
||||
g-f-g-f-------
|
||||
f-g-f--------
|
||||
g-f---------
|
||||
f----------'
|
||||
got=$(set +x; { "$SHELL" funcname.ksh ;} 2>&1)
|
||||
[[ $got == "$exp" ]] || err_exit 'funcname.ksh crash (direct run)' \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
# dotting it slightly changes the output
|
||||
exp='f-
|
||||
g-f-
|
||||
f-g-f-
|
||||
g-f-g-f-
|
||||
f-g-f-g-f-
|
||||
g-f-g-f-g-f-
|
||||
f-g-f-g-f-g-f-
|
||||
g-f-g-f-g-f-g-f-
|
||||
f-g-f-g-f-g-f-g-f-
|
||||
g-f-g-f-g-f-g-f-g-f-
|
||||
f-g-f-g-f-g-f-g-f-g-f-
|
||||
g-f-g-f-g-f-g-f-g-f--
|
||||
f-g-f-g-f-g-f-g-f---
|
||||
g-f-g-f-g-f-g-f----
|
||||
f-g-f-g-f-g-f-----
|
||||
g-f-g-f-g-f------
|
||||
f-g-f-g-f-------
|
||||
g-f-g-f--------
|
||||
f-g-f---------
|
||||
g-f----------
|
||||
f-----------'
|
||||
got=$(set +x; { "$SHELL" -c '. ./funcname.ksh' ;} 2>&1)
|
||||
[[ $got == "$exp" ]] || err_exit 'funcname.ksh crash (dot)' \
|
||||
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue