about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBarton E. Schaefer <schaefer@zsh.org>2016-02-08 20:50:07 -0800
committerBarton E. Schaefer <schaefer@zsh.org>2016-02-08 20:52:11 -0800
commit95663e936596933d529a648ed3d6c707d1a1dffe (patch)
tree1722c6eba2d19384956f6c8ac8a3557b503eedcf
parent8a59aed6967b5283cbf0c7d32559b11d3a841a37 (diff)
downloadzsh-95663e936596933d529a648ed3d6c707d1a1dffe.tar.gz
zsh-95663e936596933d529a648ed3d6c707d1a1dffe.tar.xz
zsh-95663e936596933d529a648ed3d6c707d1a1dffe.zip
37914: reparse associative array subscripts in "unset" so keys with "[" or "]" may be backslash-escaped
Also fix erroneous test case this revealed.
-rw-r--r--ChangeLog6
-rw-r--r--Src/builtin.c30
-rw-r--r--Test/E01options.ztst2
3 files changed, 25 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 76add9f27..7faa5ecaf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,12 @@
 	* unposted: ChangeLog: Move the 37678 entry to the correct
 	location (and author).
 
+2016-02-08  Barton E. Schaefer  <schaefer@zsh.org>
+
+	* 37914: Src/builtin.c, Test/E01options.ztst: reparse associative
+	array subscripts in "unset" so keys with "[" or "]" may be
+	backslash-escaped.  Fix erroneous test case this revealed.
+
 2016-02-07  Dominik Ritter  <dritter03@googlemail.com>
 
 	* unposted: Doc/Zsh/mod_complist.yo: complist module docs:
diff --git a/Src/builtin.c b/Src/builtin.c
index 63f964d3d..4c8fbcdb1 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -3350,15 +3350,24 @@ bin_unset(char *name, char **argv, Options ops, int func)
     /* do not glob -- unset the given parameter */
     queue_signals();
     while ((s = *argv++)) {
-	char *ss = strchr(s, '[');
-	char *sse = ss;
+	char *ss = strchr(s, '['), *subscript = 0;
 	if (ss) {
-	    if (skipparens('[', ']', &sse) || *sse) {
-		zerrnam(name, "%s: invalid parameter name", s);
-		returnval = 1;
-		continue;
-	    }
+	    char *sse;
 	    *ss = 0;
+	    if ((sse = parse_subscript(ss+1, 1, ']'))) {
+		*sse = 0;
+		subscript = dupstring(ss+1);
+		*sse = ']';
+		remnulargs(subscript);
+		untokenize(subscript);
+	    }
+	}
+	if ((ss && !subscript) || !isident(s)) {
+	    if (ss)
+		*ss = '[';
+	    zerrnam(name, "%s: invalid parameter name", s);
+	    returnval = 1;
+	    continue;
 	}
 	pm = (Param) (paramtab == realparamtab ?
 		      /* getnode2() to avoid autoloading */
@@ -3376,11 +3385,8 @@ bin_unset(char *name, char **argv, Options ops, int func)
 	} else if (ss) {
 	    if (PM_TYPE(pm->node.flags) == PM_HASHED) {
 		HashTable tht = paramtab;
-		if ((paramtab = pm->gsu.h->getfn(pm))) {
-		    *--sse = 0;
-		    unsetparam(ss+1);
-		    *sse = ']';
-		}
+		if ((paramtab = pm->gsu.h->getfn(pm)))
+		    unsetparam(subscript);
 		paramtab = tht;
 	    } else if (PM_TYPE(pm->node.flags) == PM_SCALAR ||
 		       PM_TYPE(pm->node.flags) == PM_ARRAY) {
diff --git a/Test/E01options.ztst b/Test/E01options.ztst
index f27076765..40e96afc9 100644
--- a/Test/E01options.ztst
+++ b/Test/E01options.ztst
@@ -776,7 +776,7 @@
   unsetopt pathdirs
   pathtestdir/findme
   path=($oldpath)
-  unset $oldpath
+  unset oldpath
   rm -rf pdt_topdir pathtestdir
 0:PATH_DIRS option
 >File in upper dir