[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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.