with this patch the hotfix from r45471 is replaced.

compile and runtested with ar71xx / r45568

the file 'shell/ash_test/ash-heredoc/heredoc1.right' is
not included, because it does not apply on our busybox.
when upgrading to next busybox-release, this patch can be dropped.

Signed-off-by: Bastian Bittorf <bitt...@bluebottle.com>
---
 ...-a-regression-in-handling-local-variables.patch |   75 -------
 .../290-ash-fix-handling-of-duplicate-local.patch  |  204 ++++++++++++++++++++
 2 files changed, 204 insertions(+), 75 deletions(-)
 delete mode 100644 
package/utils/busybox/patches/290-ash-fix-a-regression-in-handling-local-variables.patch
 create mode 100644 
package/utils/busybox/patches/290-ash-fix-handling-of-duplicate-local.patch

diff --git 
a/package/utils/busybox/patches/290-ash-fix-a-regression-in-handling-local-variables.patch
 
b/package/utils/busybox/patches/290-ash-fix-a-regression-in-handling-local-variables.patch
deleted file mode 100644
index 0ac1925..0000000
--- 
a/package/utils/busybox/patches/290-ash-fix-a-regression-in-handling-local-variables.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From: Felix Fietkau <n...@openwrt.org>
-Date: Fri, 17 Apr 2015 01:54:51 +0200
-Subject: [PATCH] ash: fix a regression in handling local variables
-
-commit 109ee5d33694a03cda3424b4846584250832ba8e
-"ash: make "locak VAR" unset VAR (bash does that)"
-
-This commit introduced a regression where calling local on an already
-local variable unsets it. This does not match bash behavior.
-
-Update test case to check for this behavior
-
-Signed-off-by: Felix Fietkau <n...@openwrt.org>
----
-
---- a/shell/ash.c
-+++ b/shell/ash.c
-@@ -8961,6 +8961,21 @@ parse_command_args(char **argv, const ch
- }
- #endif
- 
-+static bool
-+findlocal(struct var *vp)
-+{
-+      struct localvar *lvp = localvars;
-+
-+      while (lvp) {
-+              if (lvp->vp == vp)
-+                      return true;
-+
-+              lvp = lvp->next;
-+      }
-+
-+      return false;
-+}
-+
- /*
-  * Make a variable a local variable.  When a variable is made local, it's
-  * value and flags are saved in a localvar structure.  The saved values
-@@ -9000,7 +9015,7 @@ mklocal(char *name)
-                       vp->flags |= VSTRFIXED|VTEXTFIXED;
-                       if (eq)
-                               setvareq(name, 0);
--                      else
-+                      else if (!findlocal(vp))
-                               /* "local VAR" unsets VAR: */
-                               setvar(name, NULL, 0);
-               }
---- a/shell/ash_test/ash-misc/local1.right
-+++ b/shell/ash_test/ash-misc/local1.right
-@@ -1,4 +1,5 @@
- A1:'A'
- A2:''
--A3:''
--A4:'A'
-+A3:'B'
-+A4:''
-+A5:'A'
---- a/shell/ash_test/ash-misc/local1.tests
-+++ b/shell/ash_test/ash-misc/local1.tests
-@@ -3,9 +3,12 @@ f() {
-       local a
-       # the above line unsets $a
-       echo "A2:'$a'"
--      unset a
-+      a=B
-+      local a
-       echo "A3:'$a'"
-+      unset a
-+      echo "A4:'$a'"
- }
- echo "A1:'$a'"
- f
--echo "A4:'$a'"
-+echo "A5:'$a'"
diff --git 
a/package/utils/busybox/patches/290-ash-fix-handling-of-duplicate-local.patch 
b/package/utils/busybox/patches/290-ash-fix-handling-of-duplicate-local.patch
new file mode 100644
index 0000000..71c2162
--- /dev/null
+++ 
b/package/utils/busybox/patches/290-ash-fix-handling-of-duplicate-local.patch
@@ -0,0 +1,204 @@
+From 0a0acb55db8d7c4dec445573f1b0528d126b9e1f Mon Sep 17 00:00:00 2001
+From: Denys Vlasenko <vda.li...@googlemail.com>
+Date: Sat, 18 Apr 2015 19:36:38 +0200
+Subject: [PATCH] ash: fix handling of duplicate "local"
+
+Signed-off-by: Denys Vlasenko <vda.li...@googlemail.com>
+---
+ shell/ash.c                               | 51 +++++++++++++++++++++----------
+ shell/ash_test/ash-vars/var3.right        |  5 +++
+ shell/ash_test/ash-vars/var3.tests        |  1 +
+ 4 files changed, 42 insertions(+), 17 deletions(-)
+ create mode 100644 shell/ash_test/ash-vars/var3.right
+ create mode 100755 shell/ash_test/ash-vars/var3.tests
+
+diff --git a/shell/ash.c b/shell/ash.c
+index b568013..697a64f 100644
+--- a/shell/ash.c
++++ b/shell/ash.c
+@@ -2030,7 +2030,7 @@ varcmp(const char *p, const char *q)
+       int c, d;
+ 
+       while ((c = *p) == (d = *q)) {
+-              if (!c || c == '=')
++              if (c == '\0' || c == '=')
+                       goto out;
+               p++;
+               q++;
+@@ -2247,7 +2247,7 @@ setvar(const char *name, const char *val, int flags)
+ }
+ 
+ static void FAST_FUNC
+-setvar2(const char *name, const char *val)
++setvar0(const char *name, const char *val)
+ {
+       setvar(name, val, 0);
+ }
+@@ -2310,7 +2310,7 @@ unsetvar(const char *s)
+                       free(vp);
+                       INT_ON;
+               } else {
+-                      setvar2(s, 0);
++                      setvar0(s, NULL);
+                       vp->flags &= ~VEXPORT;
+               }
+  ok:
+@@ -5505,7 +5505,7 @@ ash_arith(const char *s)
+       arith_t result;
+ 
+       math_state.lookupvar = lookupvar;
+-      math_state.setvar    = setvar2;
++      math_state.setvar    = setvar0;
+       //math_state.endofname = endofname;
+ 
+       INT_OFF;
+@@ -6360,7 +6360,7 @@ subevalvar(char *p, char *varname, int strloc, int 
subtype,
+ 
+       switch (subtype) {
+       case VSASSIGN:
+-              setvar2(varname, startp);
++              setvar0(varname, startp);
+               amount = startp - expdest;
+               STADJUST(amount, expdest);
+               return startp;
+@@ -8591,7 +8591,7 @@ evalfor(union node *n, int flags)
+       loopnest++;
+       flags &= EV_TESTED;
+       for (sp = arglist.list; sp; sp = sp->next) {
+-              setvar2(n->nfor.var, sp->text);
++              setvar0(n->nfor.var, sp->text);
+               evaltree(n->nfor.body, flags);
+               if (evalskip) {
+                       if (evalskip == SKIPCONT && --skipcount <= 0) {
+@@ -8970,21 +8970,37 @@ mklocal(char *name)
+       struct localvar *lvp;
+       struct var **vpp;
+       struct var *vp;
++      char *eq = strchr(name, '=');
+ 
+       INT_OFF;
+-      lvp = ckzalloc(sizeof(struct localvar));
++      /* Cater for duplicate "local". Examples:
++       * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
++       * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
++       */
++      lvp = localvars;
++      while (lvp) {
++              if (varcmp(lvp->vp->var_text, name) == 0) {
++                      if (eq)
++                              setvareq(name, 0);
++                      /* else:
++                       * it's a duplicate "local VAR" declaration, do nothing
++                       */
++                      return;
++              }
++              lvp = lvp->next;
++      }
++
++      lvp = ckzalloc(sizeof(*lvp));
+       if (LONE_DASH(name)) {
+               char *p;
+               p = ckmalloc(sizeof(optlist));
+               lvp->text = memcpy(p, optlist, sizeof(optlist));
+               vp = NULL;
+       } else {
+-              char *eq;
+-
+               vpp = hashvar(name);
+               vp = *findvar(vpp, name);
+-              eq = strchr(name, '=');
+               if (vp == NULL) {
++                      /* variable did not exist yet */
+                       if (eq)
+                               setvareq(name, VSTRFIXED);
+                       else
+@@ -8994,12 +9010,15 @@ mklocal(char *name)
+               } else {
+                       lvp->text = vp->var_text;
+                       lvp->flags = vp->flags;
++                      /* make sure neither "struct var" nor string gets freed
++                       * during (un)setting:
++                       */
+                       vp->flags |= VSTRFIXED|VTEXTFIXED;
+                       if (eq)
+                               setvareq(name, 0);
+                       else
+                               /* "local VAR" unsets VAR: */
+-                              setvar(name, NULL, 0);
++                              setvar0(name, NULL);
+               }
+       }
+       lvp->vp = vp;
+@@ -9491,7 +9510,7 @@ evalcommand(union node *cmd, int flags)
+                * '_' in 'vi' command mode during line editing...
+                * However I implemented that within libedit itself.
+                */
+-              setvar2("_", lastarg);
++              setvar0("_", lastarg);
+       }
+       popstackmark(&smark);
+ }
+@@ -12885,7 +12904,7 @@ readcmd(int argc UNUSED_PARAM, char **argv 
UNUSED_PARAM)
+        * to jump out of it.
+        */
+       INT_OFF;
+-      r = shell_builtin_read(setvar2,
++      r = shell_builtin_read(setvar0,
+               argptr,
+               bltinlookup("IFS"), /* can be NULL */
+               read_flags,
+@@ -13046,14 +13065,14 @@ init(void)
+                       }
+               }
+ 
+-              setvar2("PPID", utoa(getppid()));
++              setvar0("PPID", utoa(getppid()));
+ #if ENABLE_ASH_BASH_COMPAT
+               p = lookupvar("SHLVL");
+               setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
+               if (!lookupvar("HOSTNAME")) {
+                       struct utsname uts;
+                       uname(&uts);
+-                      setvar2("HOSTNAME", uts.nodename);
++                      setvar0("HOSTNAME", uts.nodename);
+               }
+ #endif
+               p = lookupvar("PWD");
+@@ -13309,7 +13328,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
+                               hp = lookupvar("HOME");
+                               if (hp) {
+                                       hp = concat_path_file(hp, 
".ash_history");
+-                                      setvar2("HISTFILE", hp);
++                                      setvar0("HISTFILE", hp);
+                                       free((char*)hp);
+                                       hp = lookupvar("HISTFILE");
+                               }
+diff --git a/shell/ash_test/ash-vars/var3.tests 
b/shell/ash_test/ash-vars/var3.tests
+new file mode 100755
+index 0000000..97b102c
+--- /dev/null
++++ b/shell/ash_test/ash-vars/var3.tests
+@@ -0,0 +1 @@
++x=0; f() { local x=1; echo $x; local x; echo $x; unset x; echo $x; local x; 
echo $x; }; f; echo $x
+-- 
+1.8.1.2
+
-- 
1.7.10.4
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to