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

cd - shouldn't ignore $OLDPWD when in a new scope (#249)

This bug was first reported at <https://github.com/att/ast/issues/8>.
The 'cd' command currently takes the value of $OLDPWD from the
wrong scope. In the following example 'cd -' will change the
directory to /bin instead of /tmp:

    $ OLDPWD=/bin ksh93 -c 'OLDPWD=/tmp cd -'
    /bin

src/cmd/ksh93/bltins/cd_pwd.c:
- Use sh_scoped() to obtain the correct value of $OLDPWD.
- Fix a use-after-free bug. Make the 'oldpwd' variable a static
  char that points to freeable memory. Each time cd is used, this
  variable is freed if it points to a freeable memory address and
  isn't also a pointer to shp->pwd.

src/cmd/ksh93/sh/path.c: path_pwd():
- Simplify and add comments.
- Scope $PWD properly.

src/cmd/ksh93/tests/builtins.sh,
src/cmd/ksh93/tests/leaks.sh:
- Backport the ksh2020 regression tests for 'cd -' when $OLDPWD is
  set.
- Add test for $OLDPWD and $PWD after subshare.
- Add test for $PWD after 'cd'.
- Add test for possible memory leak.
- Add testing for 'unset' on OLDPWD and PWD.

src/cmd/ksh93/COMPATIBILITY:
- Add compatibility note about changes to $PWD and $OLDPWD.

Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
Johnothan King 2021-04-01 17:19:19 -07:00 committed by GitHub
parent ed478ab7e3
commit ca2443b58c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 148 additions and 41 deletions

View file

@ -1059,5 +1059,85 @@ got=$?
exp=1
[[ $got == $exp ]] || err_exit "'kill %' has the wrong exit status (expected '$exp'; got '$got')"
# ======
# 'cd -' should recognize the value of an overriden $OLDPWD variable
# https://github.com/ksh93/ksh/pull/249
# https://github.com/att/ast/issues/8
mkdir "$tmp/oldpwd" "$tmp/otherpwd"
exp=$tmp/oldpwd
OLDPWD=$exp
cd - > /dev/null
got=$PWD
[[ $got == "$exp" ]] || err_exit "cd - doesn't recognize overridden OLDPWD variable" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
cd "$tmp"
OLDPWD=$tmp/otherpwd
got=$(OLDPWD=$tmp/oldpwd cd -)
[[ $got == "$exp" ]] ||
err_exit "cd - doesn't recognize overridden OLDPWD variable if it is overridden in new scope" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
function fn
{
typeset OLDPWD=/tmp
cd -
}
exp='/tmp'
got=$(OLDPWD=/bin fn)
[[ $got == "$exp" ]] ||
err_exit "cd - doesn't recognize overridden OLDPWD variable if it is overridden in function scope" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
function fn
{
typeset PWD=bug
cd /tmp
echo "$PWD"
}
exp='/tmp'
got=$(fn)
[[ $got == "$exp" ]] ||
err_exit "PWD isn't set after cd if already set in function scope" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
# $PWD should be set correctly after cd
exp="$PWD
$PWD"
got=$(echo $PWD; PWD=/tmp cd /home; echo $PWD)
[[ $got == "$exp" ]] ||
err_exit "PWD is incorrect after cd" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
# Test for $OLDPWD and/or $PWD leaking out of subshell
exp='/tmp /dev'
got=$(
PWD=/dev
OLDPWD=/tmp
(
cd /usr; cd /bin
cd - > /dev/null
)
echo $OLDPWD $PWD
)
[[ $got == "$exp" ]] ||
err_exit "OLDPWD and/or PWD leak out of subshell" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
# $OLDPWD and $PWD should survive after being set in a subshare
exp='/usr /bin'
got=$(
PWD=/dev
OLDPWD=/tmp
foo=${
cd /usr; cd /bin
}
echo $OLDPWD $PWD
)
[[ $got == "$exp" ]] ||
err_exit "OLDPWD and/or PWD fail to survive subshare" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
# ======
exit $((Errors<125?Errors:125))

View file

@ -417,5 +417,27 @@ after=$(getmem)
err_exit_if_leak 'unset PATH in subshell'
disabled
# ======
# Test for a memory leak after 'cd' (in relation to $PWD and $OLDPWD)
original_pwd=$PWD
before=$(getmem)
for ((i=0; i < N; i++))
do cd /tmp
cd - > /dev/null
PWD=/foo
OLDPWD=/bar
cd /bin
cd /usr
cd /home
cd /home
cd - > /dev/null
unset OLDPWD PWD
cd /bin
cd /tmp
done
after=$(getmem)
err_exit_if_leak 'PWD and/or OLDPWD changed by cd'
cd $original_pwd
# ======
exit $((Errors<125?Errors:125))