Author: jilles
Date: Sun Jan 10 16:31:28 2016
New Revision: 293635
URL: https://svnweb.freebsd.org/changeset/base/293635

Log:
  sh: Update associated state when restoring locals while leaving a function.
  
  Some variables like PATH call a function when modified. Make sure to call
  this also when leaving a function where such a variable was made local.
  
  Make sure to restore local variables before shellparam, so getopts state is
  not clobbered.

Added:
  head/bin/sh/tests/builtins/local5.0   (contents, props changed)
Modified:
  head/bin/sh/eval.c
  head/bin/sh/tests/builtins/Makefile
  head/bin/sh/var.c

Modified: head/bin/sh/eval.c
==============================================================================
--- head/bin/sh/eval.c  Sun Jan 10 13:53:57 2016        (r293634)
+++ head/bin/sh/eval.c  Sun Jan 10 16:31:28 2016        (r293635)
@@ -1039,12 +1039,12 @@ evalcommand(union node *cmd, int flags, 
                reffunc(cmdentry.u.func);
                savehandler = handler;
                if (setjmp(jmploc.loc)) {
-                       freeparam(&shellparam);
-                       shellparam = saveparam;
                        popredir();
                        unreffunc(cmdentry.u.func);
                        poplocalvars();
                        localvars = savelocalvars;
+                       freeparam(&shellparam);
+                       shellparam = saveparam;
                        funcnest--;
                        handler = savehandler;
                        longjmp(handler->loc, 1);

Modified: head/bin/sh/tests/builtins/Makefile
==============================================================================
--- head/bin/sh/tests/builtins/Makefile Sun Jan 10 13:53:57 2016        
(r293634)
+++ head/bin/sh/tests/builtins/Makefile Sun Jan 10 16:31:28 2016        
(r293635)
@@ -111,6 +111,7 @@ FILES+=             local1.0
 FILES+=                local2.0
 FILES+=                local3.0
 FILES+=                local4.0
+FILES+=                local5.0
 .if ${MK_NLS} != "no"
 FILES+=                locale1.0
 .endif

Added: head/bin/sh/tests/builtins/local5.0
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/bin/sh/tests/builtins/local5.0 Sun Jan 10 16:31:28 2016        
(r293635)
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+f() {
+       local PATH IFS elem
+       IFS=:
+       for elem in ''$PATH''; do
+               PATH=/var/empty/$elem:$PATH
+       done
+       ls -d / >/dev/null
+}
+
+p1=$(command -v ls)
+f
+p2=$(command -v ls)
+[ "$p1" = "$p2" ]

Modified: head/bin/sh/var.c
==============================================================================
--- head/bin/sh/var.c   Sun Jan 10 13:53:57 2016        (r293634)
+++ head/bin/sh/var.c   Sun Jan 10 16:31:28 2016        (r293635)
@@ -791,6 +791,7 @@ poplocalvars(void)
 {
        struct localvar *lvp;
        struct var *vp;
+       int islocalevar;
 
        INTOFF;
        while ((lvp = localvars) != NULL) {
@@ -803,10 +804,20 @@ poplocalvars(void)
                } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
                        (void)unsetvar(vp->text);
                } else {
+                       islocalevar = (vp->flags | lvp->flags) & VEXPORT &&
+                           localevar(lvp->text);
                        if ((vp->flags & VTEXTFIXED) == 0)
                                ckfree(vp->text);
                        vp->flags = lvp->flags;
                        vp->text = lvp->text;
+                       if (vp->func)
+                               (*vp->func)(vp->text + vp->name_len + 1);
+                       if (islocalevar) {
+                               change_env(vp->text, vp->flags & VEXPORT &&
+                                   (vp->flags & VUNSET) == 0);
+                               setlocale(LC_ALL, "");
+                               updatecharset();
+                       }
                }
                ckfree(lvp);
        }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to