[PATCH] Don't perform dereferencing when looking up certain special parameters
Philippe Altherr <[email protected]>
| Newsgroups | gmane.comp.shells.zsh.devel |
|---|---|
| Message-ID | <CAGdYchtgyKgyixgaV0Z=oUiqXUY7dLD92UtVmoYt0LEpCee9hA@mail.gmail.com> |
The code managing a number of special parameters performs dereferencing while looking up the parameter. This often leads to bogus behavior. Here is an example: % typeset -n PWD=pwd % cd / % typeset -p PWD pwd typeset -n PWD=pwd export pwd=/ % printenv | grep -i ^PWD= pwd=/ In this case, the wrong parameter is exported. In many cases, the fix is to simply not perform any dereferencing, which is what the following patch does for a number of special parameters. - Don't perform dereferencing when looking up certain special parameters <https://github.com/paltherr/zsh/compare/no-deref-start...paltherr:zsh:no-deref> Philippe
no-deref.txt
(text/plain, 6.6 KB)
diff --git a/Src/Modules/watch.c b/Src/Modules/watch.c
index f23819b25..8704795e6 100644
--- a/Src/Modules/watch.c
+++ b/Src/Modules/watch.c
@@ -746,9 +746,9 @@ boot_(UNUSED(Module m))
/* These two parameters are only set to defaults if not set.
* So setting them in .zshrc will not be enough to load the
* module. It's useless until the watch array is set anyway. */
- if (!paramtab->getnode(paramtab, "WATCHFMT"))
+ if (!realparamtab->getnode2(realparamtab, "WATCHFMT"))
setsparam("WATCHFMT", ztrdup_metafy(default_watchfmt));
- if (!paramtab->getnode(paramtab, "LOGCHECK"))
+ if (!realparamtab->getnode2(realparamtab, "LOGCHECK"))
setiparam("LOGCHECK", 60);
addprepromptfn(&checksched);
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index 230ad86f6..18dcf5519 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -496,7 +496,7 @@ zfsetparam(char *name, void *val, int flags)
Param pm = NULL;
int type = (flags & ZFPM_INTEGER) ? PM_INTEGER : PM_SCALAR;
- if (!(pm = (Param) paramtab->getnode(paramtab, name))
+ if (!(pm = (Param) realparamtab->getnode2(realparamtab, name))
|| (pm->node.flags & PM_UNSET)) {
/*
* just make it readonly when creating, in case user
@@ -530,7 +530,7 @@ zfunsetparam(char *name)
{
Param pm;
- if ((pm = (Param) paramtab->getnode(paramtab, name))) {
+ if ((pm = (Param) realparamtab->getnode2(realparamtab, name))) {
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
}
diff --git a/Src/builtin.c b/Src/builtin.c
index ff9cf57f9..7f9c49f8a 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -803,13 +803,13 @@ set_pwd_env(void)
/* update the PWD and OLDPWD shell parameters */
- pm = (Param) paramtab->getnode(paramtab, "PWD");
+ pm = (Param) realparamtab->getnode2(realparamtab, "PWD");
if (pm && PM_TYPE(pm->node.flags) != PM_SCALAR) {
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
}
- pm = (Param) paramtab->getnode(paramtab, "OLDPWD");
+ pm = (Param) realparamtab->getnode2(realparamtab, "OLDPWD");
if (pm && PM_TYPE(pm->node.flags) != PM_SCALAR) {
pm->node.flags &= ~PM_READONLY;
unsetparam_pm(pm, 0, 1);
@@ -818,10 +818,10 @@ set_pwd_env(void)
assignsparam("PWD", ztrdup(pwd), 0);
assignsparam("OLDPWD", ztrdup(oldpwd), 0);
- pm = (Param) paramtab->getnode(paramtab, "PWD");
+ pm = (Param) realparamtab->getnode2(realparamtab, "PWD");
if (!(pm->node.flags & PM_EXPORTED))
addenv(pm, pwd);
- pm = (Param) paramtab->getnode(paramtab, "OLDPWD");
+ pm = (Param) realparamtab->getnode2(realparamtab, "OLDPWD");
if (!(pm->node.flags & PM_EXPORTED))
addenv(pm, oldpwd);
}
diff --git a/Src/init.c b/Src/init.c
index 7c3b82461..b9aef93da 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -179,7 +179,7 @@ loop(int toplevel, int justonce)
non_empty = 1;
if (toplevel &&
(getshfunc("preexec") ||
- paramtab->getnode(paramtab, "preexec" HOOK_SUFFIX))) {
+ realparamtab->getnode2(realparamtab, "preexec" HOOK_SUFFIX))) {
LinkList args;
char *cmdstr;
diff --git a/Src/module.c b/Src/module.c
index 0b5cd5649..049394a5b 100644
--- a/Src/module.c
+++ b/Src/module.c
@@ -1027,7 +1027,7 @@ checkaddparam(const char *nam, int opt_i)
{
Param pm;
- if (!(pm = (Param) gethashnode2(paramtab, nam)))
+ if (!(pm = (Param) realparamtab->getnode2(realparamtab, nam)))
return 0;
if (pm->level || !(pm->node.flags & PM_AUTOLOAD)) {
@@ -1071,7 +1071,7 @@ addparamdef(Paramdef d)
return 1;
}
else if (!(pm = createparam(d->name, d->flags)) &&
- !(pm = (Param) paramtab->getnode(paramtab, d->name)))
+ !(pm = (Param) realparamtab->getnode2(realparamtab, d->name)))
return 1;
d->pm = pm;
@@ -1128,7 +1128,7 @@ addparamdef(Paramdef d)
int
deleteparamdef(Paramdef d)
{
- Param pm = (Param) paramtab->getnode(paramtab, d->name);
+ Param pm = (Param) realparamtab->getnode2(realparamtab, d->name);
if (!pm)
return 1;
@@ -1147,10 +1147,10 @@ deleteparamdef(Paramdef d)
if (!searchpm)
return 1;
- paramtab->removenode(paramtab, pm->node.nam);
+ realparamtab->removenode(realparamtab, pm->node.nam);
prevpm->old = searchpm->old;
searchpm->old = pm;
- paramtab->addnode(paramtab, searchpm->node.nam, searchpm);
+ realparamtab->addnode(realparamtab, searchpm->node.nam, searchpm);
pm = searchpm;
}
@@ -1239,7 +1239,7 @@ add_autoparam(const char *module, const char *pnam, int flags)
static int
del_autoparam(UNUSED(const char *modnam), const char *pnam, int flags)
{
- Param pm = (Param) gethashnode2(paramtab, pnam);
+ Param pm = (Param) realparamtab->getnode2(realparamtab, pnam);
if (!pm) {
if (!(flags & FEAT_IGNORE))
@@ -2760,7 +2760,7 @@ bin_zmodload_auto(char *nam, char **args, Options ops)
} else if (OPT_ISSET(ops,'p')) {
if (!*args) {
/* list autoloaded parameters */
- scanhashtable(paramtab, 1, 0, 0, printautoparams,
+ scanhashtable(realparamtab, 1, 0, 0, printautoparams,
OPT_ISSET(ops,'L'));
return 0;
}
diff --git a/Src/params.c b/Src/params.c
index d9722bea2..4f999f518 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -945,7 +945,7 @@ createparamtable(void)
* For native emulation we always set the variable home
* (see setupvals()).
*/
- pm = (Param) paramtab->getnode(paramtab, "HOME");
+ pm = (Param) realparamtab->getnode2(realparamtab, "HOME");
if (EMULATION(EMULATE_ZSH))
{
pm->node.flags &= ~PM_UNSET;
@@ -953,10 +953,10 @@ createparamtable(void)
addenv(pm, home);
} else if (!home)
pm->node.flags |= PM_UNSET;
- pm = (Param) paramtab->getnode(paramtab, "LOGNAME");
+ pm = (Param) realparamtab->getnode2(realparamtab, "LOGNAME");
if (!(pm->node.flags & PM_EXPORTED))
addenv(pm, pm->u.str);
- pm = (Param) paramtab->getnode(paramtab, "SHLVL");
+ pm = (Param) realparamtab->getnode2(realparamtab, "SHLVL");
sprintf(buf, "%d", (int)++shlvl);
/* shlvl value in environment needs updating unconditionally */
addenv(pm, buf);
diff --git a/Src/utils.c b/Src/utils.c
index a1d7c8cc2..f5c51e5df 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1257,7 +1257,7 @@ getnameddir(char *name)
/* Check if there is a scalar parameter with this name whose value *
* begins with a `/'. If there is, add it to the hash table and *
* return the new value. */
- if ((pm = (Param) paramtab->getnode(paramtab, name)) &&
+ if ((pm = (Param) realparamtab->getnode2(realparamtab, name)) &&
(PM_TYPE(pm->node.flags) == PM_SCALAR) &&
(str = getsparam(name)) && *str == '/') {
pm->node.flags |= PM_NAMEDDIR;