From bc6c5dbdd9d700c45246b198ad8b634db8cd3326 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Sat, 19 Feb 2022 21:45:01 +0100 Subject: [PATCH] path_pwd(): Fix use after free (re: 11177d44) Of course, we should not free the 'cp' pointer when we still need to use it. Resolves: https://github.com/ksh93/ksh/issues/467 Thanks to @atheik for the report. --- src/cmd/ksh93/sh/path.c | 8 ++++---- src/cmd/ksh93/tests/path.sh | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/cmd/ksh93/sh/path.c b/src/cmd/ksh93/sh/path.c index f106ffa20..9f7e1c17e 100644 --- a/src/cmd/ksh93/sh/path.c +++ b/src/cmd/ksh93/sh/path.c @@ -183,6 +183,7 @@ static pid_t command_xargs(const char *path, char *argv[],char *const envp[], in char *path_pwd(void) { register char *cp; + char tofree = 0; Namval_t *pwdnod; /* Don't bother if PWD already set */ if(sh.pwd) @@ -198,7 +199,6 @@ char *path_pwd(void) { /* Check if $HOME is a path to the PWD; this ensures $PWD == $HOME at login, even if $HOME is a path that contains symlinks */ - char tofree = 0; cp = nv_getval(sh_scoped(HOME)); if(!(cp && *cp=='/' && test_inode(cp,e_dot))) { @@ -214,8 +214,6 @@ char *path_pwd(void) pwdnod = sh_assignok(pwdnod,1); nv_putval(pwdnod,cp,NV_RDONLY); } - if(tofree) - free((void*)cp); } nv_onattr(pwdnod,NV_EXPORT); /* Neither obtained the pwd nor can fall back to sane-ish $PWD: fall back to "." */ @@ -224,7 +222,9 @@ char *path_pwd(void) if(!cp || *cp!='/') nv_putval(pwdnod,cp=(char*)e_dot,NV_RDONLY); /* Set shell PWD */ - sh.pwd = sh_strdup(cp); + if(!tofree) + cp = sh_strdup(cp); + sh.pwd = cp; return((char*)sh.pwd); } diff --git a/src/cmd/ksh93/tests/path.sh b/src/cmd/ksh93/tests/path.sh index 8da8358e3..638d5d9d4 100755 --- a/src/cmd/ksh93/tests/path.sh +++ b/src/cmd/ksh93/tests/path.sh @@ -944,6 +944,15 @@ cd "$tmp/testdir" wait "$!" 2>/dev/null ((!(e = $?))) || err_exit 'shell crashes on failure obtain the PWD on init' \ "(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))" +cd "$tmp" + +# ====== +# https://github.com/ksh93/ksh/issues/467 +[[ -d emptydir ]] || mkdir emptydir +got=$(unset PWD; "$SHELL" -c 'echo "$PWD"; pwd; cd emptydir' 2>&1) +exp=$PWD$'\n'$PWD +[[ $got == "$exp" ]] || err_exit "child shell failed to obtain PWD" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" # ====== exit $((Errors<125?Errors:125))