mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-15 04:32:24 +00:00
There were still problems left after the previous commit. On at least one system (QNX i386), the following regression test crashed: src/cmd/ksh93/test/subshell.c 900 got=$( { "$SHELL" -c '(cd /; (cd /)); print -r -- "PWD=$PWD"'; } 2>&1 ) A backtrace done on the core dunp pointed to the free() call here: src/cmd/ksh93/bltins/cd_pwd.c 90 if(oldpwd && oldpwd!=shp->pwd && oldpwd!=e_dot) 91 free(oldpwd); Analysis: The interaction between $PWD, sh.pwd aka shp->pwd, and the path_pwd() function is a mess. path_pwd() usually returns a freeable value, but not always. sh.pwd is sometimes a pointer to the value of $PWD, but not always (e.g. when you unset PWD or assign to it). Instead of debugging the exact cause of the crash, I think it is better to make this work in a more consistent way. As of this commit: 1. sh.pwd keeps its own copy of the PWD, independently of the PWD variable. The old value must always be freed immediately before assigning a new one. This is simple and consistent, reducing the chance of bugs at negligible cost. 2. The PWD variable is no longer given the NV_NOFREE attribute because its value no longer points to sh.pwd. It is now a variable like any other. src/cmd/ksh93/sh/path.c: path_pwd(): - Do not give PWDNOD the NV_NOFREE attribute. - Give sh.pwd its own copy of the PWD by strdup'ing PWDNOD's value. src/cmd/ksh93/bltins/cd_pwd.c: b_cd(): - Since sh.pwd is now consistently freed before giving it a new value and at no other time, oldpwd must not be freed any longer and can become a regular non-static variable. - If the PWD needs reinitialising, call path_pwd() to do it. src/cmd/ksh93/sh/subshell.c: sh_subshell(): - Systems with fchdir(2): Always restore the PWD upon exiting a non-subshare subshell. The check to decide whether or not to restore it was unsafe: it was not restored if the current PWD pointer and value was identical to the saved one, but a directory can be deleted and recreated under the same name. - Systems without fchdir(2) (if any exist): . Entry: Fork if the PWD is nonexistent or has no x permission. . Restore: Only chdir back if the subshell PWD was changed. That's probably the best we can do. It remains inherently unsafe. We should probably just require fchdir(2) at some point. |
||
---|---|---|
.. | ||
builtin | ||
INIT | ||
ksh93 | ||
Mamfile |