about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2000-05-31 08:56:23 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2000-05-31 08:56:23 +0000
commit7bf294f2b8329673ffd0ee55fa2cca872e5448df (patch)
tree0ab313d514fd5dfbeede7a34876df8e921dc2519
parentd5b6d1f40c7dcbc1510e4335924889b55fb648db (diff)
downloadzsh-7bf294f2b8329673ffd0ee55fa2cca872e5448df.tar.gz
zsh-7bf294f2b8329673ffd0ee55fa2cca872e5448df.tar.xz
zsh-7bf294f2b8329673ffd0ee55fa2cca872e5448df.zip
Wayne: pattern.c unitialised var
Zero-length arrays now possible with $array[1,0]
-rw-r--r--ChangeLog13
-rw-r--r--Src/Modules/mapfile.c70
-rw-r--r--Src/Modules/parameter.c20
-rw-r--r--Src/Zle/complete.c4
-rw-r--r--Src/glob.c25
-rw-r--r--Src/params.c218
-rw-r--r--Src/pattern.c3
-rw-r--r--Src/subst.c8
-rw-r--r--Src/zsh.h4
-rw-r--r--Test/07cond.ztst1
10 files changed, 193 insertions, 173 deletions
diff --git a/ChangeLog b/ChangeLog
index 3b75dcb66..7ee2f1ec6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2000-05-31  Peter Stephenson  <pws@cambridgesiliconradio.com>
+
+	* Wayne Davison: 11680: Src/params.c: subscript too small/big
+	error messages.
+
+	* Wayne Davison: 11677, 11681: Src/glob.c, Src/params.c, Src/subst.c,
+	Src/zsh.h, Src/Modules/mapfile.c, Src/Modules/parameter.c,
+	Src/Zle/complete.c: make $array[1,0] return a zero-length array.
+
+	* Wayne Davison: 11676: Src/pattern.c: uninitialised variable.
+
+	* Wayne Davison: 11675: Test/07cond.ztst: apparent race condition.
+
 2000-05-31  Sven Wischnowsky  <wischnow@zsh.org>
 
 	* 11682: Src/Zle/compresult.c: move to last cursor after not
diff --git a/Src/Modules/mapfile.c b/Src/Modules/mapfile.c
index e98da7889..05071bd35 100644
--- a/Src/Modules/mapfile.c
+++ b/Src/Modules/mapfile.c
@@ -86,7 +86,8 @@ createmapfilehash()
     unsetparam(mapfile_nam);
     mapfile_pm = NULL;
 
-    if (!(pm = createparam(mapfile_nam, PM_SPECIAL|PM_REMOVABLE|PM_HASHED)))
+    if (!(pm = createparam(mapfile_nam,
+			   PM_SPECIAL|PM_HIDE|PM_REMOVABLE|PM_HASHED)))
 	return NULL;
 
     pm->level = pm->old ? locallevel : 0;
@@ -143,12 +144,16 @@ setpmmapfile(Param pm, char *value)
 	 */
 	ftruncate(fd, len);
 	memcpy(mmptr, value, len);
+#ifndef MS_SYNC
+#define MS_SYNC 0
+#endif
 	msync(mmptr, len, MS_SYNC);
 	/*
 	 * Then we need to truncate again, since mmap() always maps complete
 	 * pages.  Honestly, I tried it without, and you need both.
 	 */
 	ftruncate(fd, len);
+	munmap(mmptr, len);
     }
 #else /* don't USE_MMAP */
     /* can't be bothered to do anything too clever here */
@@ -197,8 +202,8 @@ setpmmapfiles(Param pm, HashTable ht)
 	    for (hn = ht->nodes[i]; hn; hn = hn->next) {
 		struct value v;
 
-		v.isarr = v.inv = v.a = 0;
-		v.b = -1;
+		v.isarr = v.inv = v.start = 0;
+		v.len = -1;
 		v.arr = NULL;
 		v.pm = (Param) hn;
 
@@ -243,7 +248,7 @@ get_contents(char *fname)
     val = NULL;
     if ((fd = open(fname, O_RDONLY | O_NOCTTY)) >= 0) {
 	LinkList ll;
-	MUSTUSEHEAP("mapfile:get_contents");
+
 	if ((ll = readoutput(fd, 1)))
 	    val = peekfirst(ll);
     }
@@ -259,30 +264,27 @@ getpmmapfile(HashTable ht, char *name)
     char *contents;
     Param pm = NULL;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR;
-	pm->sets.cfn = setpmmapfile;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = unsetpmmapfile;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-
-	pm->flags |= (mapfile_pm->flags & PM_READONLY);
-
-	/* Set u.str to contents of file given by name */
-	if ((contents = get_contents(pm->nam)))
-	    pm->u.str = contents;
-	else {
-	    pm->u.str = "";
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR;
+    pm->sets.cfn = setpmmapfile;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = unsetpmmapfile;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+
+    pm->flags |= (mapfile_pm->flags & PM_READONLY);
+
+    /* Set u.str to contents of file given by name */
+    if ((contents = get_contents(pm->nam)))
+	pm->u.str = contents;
+    else {
+	pm->u.str = "";
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -324,14 +326,14 @@ scanpmmapfile(HashTable ht, ScanFunc func, int flags)
 
 /**/
 int
-setup_mapfile(Module m)
+setup_(Module m)
 {
     return 0;
 }
 
 /**/
 int
-boot_mapfile(Module m)
+boot_(Module m)
 {
     /* Create the special associative array. */
 
@@ -341,11 +343,9 @@ boot_mapfile(Module m)
     return 0;
 }
 
-#ifdef MODULE
-
 /**/
 int
-cleanup_mapfile(Module m)
+cleanup_(Module m)
 {
     Param pm;
 
@@ -361,9 +361,7 @@ cleanup_mapfile(Module m)
 
 /**/
 int
-finish_mapfile(Module m)
+finish_(Module m)
 {
     return 0;
 }
-
-#endif
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 55fca09ac..23afc0f77 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -229,8 +229,8 @@ setpmcommands(Param pm, HashTable ht)
 	    Cmdnam cn = zcalloc(sizeof(*cn));
 	    struct value v;
 
-	    v.isarr = v.inv = v.a = 0;
-	    v.b = -1;
+	    v.isarr = v.inv = v.start = 0;
+	    v.len = -1;
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
@@ -400,8 +400,8 @@ setfunctions(Param pm, HashTable ht, int dis)
 	for (hn = ht->nodes[i]; hn; hn = hn->next) {
 	    struct value v;
 
-	    v.isarr = v.inv = v.a = 0;
-	    v.b = -1;
+	    v.isarr = v.inv = v.start = 0;
+	    v.len = -1;
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
@@ -754,8 +754,8 @@ setpmoptions(Param pm, HashTable ht)
 	    struct value v;
 	    char *val;
 
-	    v.isarr = v.inv = v.a = 0;
-	    v.b = -1;
+	    v.isarr = v.inv = v.start = 0;
+	    v.len = -1;
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
@@ -1433,8 +1433,8 @@ setpmnameddirs(Param pm, HashTable ht)
 	    struct value v;
 	    char *val;
 
-	    v.isarr = v.inv = v.a = 0;
-	    v.b = -1;
+	    v.isarr = v.inv = v.start = 0;
+	    v.len = -1;
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
@@ -1659,8 +1659,8 @@ setaliases(Param pm, HashTable ht, int global, int dis)
 	    struct value v;
 	    char *val;
 
-	    v.isarr = v.inv = v.a = 0;
-	    v.b = -1;
+	    v.isarr = v.inv = v.start = 0;
+	    v.len = -1;
 	    v.arr = NULL;
 	    v.pm = (Param) hn;
 
diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c
index c87aac596..2b73ea33e 100644
--- a/Src/Zle/complete.c
+++ b/Src/Zle/complete.c
@@ -1033,8 +1033,8 @@ set_compstate(Param pm, HashTable ht)
 	    for (cp = compkparams,
 		 pp = compkpms; cp->name; cp++, pp++)
 		if (!strcmp(hn->nam, cp->name)) {
-		    v.isarr = v.inv = v.a = 0;
-		    v.b = -1;
+		    v.isarr = v.inv = v.start = 0;
+		    v.len = -1;
 		    v.arr = NULL;
 		    v.pm = (Param) hn;
 		    if (cp->type == PM_INTEGER)
diff --git a/Src/glob.c b/Src/glob.c
index 3e8740fd9..e8e6e4fdf 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -921,8 +921,8 @@ glob(LinkList list, LinkNode np, int nountok)
     Complist q;				/* pattern after parsing         */
     char *ostr = (char *)getdata(np);	/* the pattern before the parser */
 					/* chops it up                   */
-    int first = 0, last = -1;		/* index of first/last match to  */
-				        /* return */
+    int first = 0, count = -1;		/* index of first match to return */
+					/* plus number of items		 */
     struct globdata saved;		/* saved glob state              */
 
     if (unset(GLOBOPT) || !haswilds(ostr)) {
@@ -1334,15 +1334,15 @@ glob(LinkList list, LinkNode np, int nountok)
 
 			    v.isarr = SCANPM_WANTVALS;
 			    v.pm = NULL;
-			    v.b = -1;
+			    v.len = -1;
 			    v.inv = 0;
 			    if (getindex(&s, &v) || s == os) {
 				zerr("invalid subscript", NULL, 0);
 				restore_globstate(saved);
 				return;
 			    }
-			    first = v.a;
-			    last = v.b;
+			    first = v.start;
+			    count = v.len;
 			    break;
 			}
 		    default:
@@ -1428,16 +1428,15 @@ glob(LinkList list, LinkNode np, int nountok)
 
     if (first < 0)
 	first += matchct;
-    if (last < 0)
-	last += matchct;
+    if (count < 0)
+	count += matchct + 1;
     if (first < 0)
 	first = 0;
-    if (last >= matchct)
-	last = matchct - 1;
-    if (first <= last) {
-	matchptr = matchbuf + matchct - 1 - last;
-	last -= first;
-	while (last-- >= 0) {		/* insert matches in the arg list */
+    if (count > matchct - first)
+	count = matchct - first;
+    if (count > 0) {
+	matchptr = matchbuf + matchct - first - count;
+	while (count-- > 0) {		/* insert matches in the arg list */
 	    insertlinknode(list, node, matchptr->name);
 	    matchptr++;
 	}
diff --git a/Src/params.c b/Src/params.c
index aa20e79f4..e28dc6d3b 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -394,8 +394,8 @@ scanparamvals(HashNode hn, int flags)
     }
     v.isarr = (PM_TYPE(v.pm->flags) & (PM_ARRAY|PM_HASHED));
     v.inv = 0;
-    v.a = 0;
-    v.b = -1;
+    v.start = 0;
+    v.len = -1;
     paramvals[numparamvals] = getstrvalue(&v);
     if (flags & SCANPM_MATCHVAL) {
 	if (pattry(scanprog, paramvals[numparamvals])) {
@@ -437,8 +437,8 @@ getvaluearr(Value v)
     else if (PM_TYPE(v->pm->flags) == PM_HASHED) {
 	v->arr = paramvalarr(v->pm->gets.hfn(v->pm), v->isarr);
 	/* Can't take numeric slices of associative arrays */
-	v->a = 0;
-	v->b = numparamvals;
+	v->start = 0;
+	v->len = numparamvals + 1;
 	return v->arr;
     } else
 	return NULL;
@@ -932,13 +932,15 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
 		paramtab = tht;
 	    }
 	    v->isarr = (*inv ? SCANPM_WANTINDEX : 0);
-	    v->a = 0;
+	    v->start = 0;
 	    *inv = 0;	/* We've already obtained the "index" (key) */
-	    *w = v->b = -1;
+	    *w = v->len = -1;
 	    r = isset(KSHARRAYS) ? 1 : 0;
-	} else
-	if (!(r = mathevalarg(s, &s)) || (isset(KSHARRAYS) && r >= 0))
-	    r++;
+	} else {
+	    r = mathevalarg(s, &s);
+	    if ((!r && !a2) || (isset(KSHARRAYS) && r >= 0))
+		r++;
+	}
 	if (word && !v->isarr) {
 	    s = t = getstrvalue(v);
 	    i = wordcount(s, sep, 0);
@@ -955,7 +957,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
 		return 0;
 
 	    if (!a2 && *tt != ',')
-		*w = (zlong)(s - t) - 1;
+		*w = (zlong)(s - d) - 1;
 
 	    return (a2 ? s : d + 1) - t;
 	} else if (!v->isarr && !word) {
@@ -1014,7 +1016,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
 				 (v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL |
 					      SCANPM_KEYMATCH))))) {
 			*inv = v->inv;
-			*w = v->b;
+			*w = v->len;
 			return 1;
 		    }
 		} else
@@ -1065,7 +1067,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
 		    if (!--r) {
 			r = (zlong)(t - s + (a2 ? -1 : 1));
 			if (!a2 && *tt != ',')
-			    *w = r + strlen(ta[i]) - 2;
+			    *w = strlen(ta[i]) - 1;
 			return r;
 		    }
 		return a2 ? -1 : 0;
@@ -1129,7 +1131,7 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
 int
 getindex(char **pptr, Value v)
 {
-    int a, b, inv = 0;
+    int start, len, inv = 0;
     char *s = *pptr, *tbrack;
 
     *s++ = '[';
@@ -1141,31 +1143,32 @@ getindex(char **pptr, Value v)
     if ((s[0] == '*' || s[0] == '@') && s[1] == ']') {
 	if ((v->isarr || IS_UNSET_VALUE(v)) && s[0] == '@')
 	    v->isarr |= SCANPM_ISVAR_AT;
-	v->a = 0;
-	v->b = -1;
+	v->start = 0;
+	v->len = -1;
 	s += 2;
     } else {
-	zlong we = 0, dummy;
+	zlong wlen = 0, dummy;
 
-	a = getarg(&s, &inv, v, 0, &we);
+	start = getarg(&s, &inv, v, 0, &wlen);
 
 	if (inv) {
-	    if (!v->isarr && a != 0) {
+	    if (!v->isarr && start != 0) {
 		char *t, *p;
 		t = getstrvalue(v);
-		if (a > 0) {
-		    for (p = t + a - 1; p-- > t; )
+		if (start > 0) {
+		    for (p = t + start - 1; p-- > t; )
 			if (*p == Meta)
-			    a--;
+			    start--;
 		} else
-		    a = -ztrlen(t + a + strlen(t));
+		    start = -ztrlen(t + start + strlen(t));
 	    }
-	    if (a > 0 && (isset(KSHARRAYS) || (v->pm->flags & PM_HASHED)))
-		a--;
+	    if (start > 0 && (isset(KSHARRAYS) || (v->pm->flags & PM_HASHED)))
+		start--;
 	    if (v->isarr != SCANPM_WANTINDEX) {
 		v->inv = 1;
 		v->isarr = 0;
-		v->a = v->b = a;
+		v->start = start;
+		v->len = 1;
 	    }
 	    if (*s == ',') {
 		zerr("invalid subscript", NULL, 0);
@@ -1179,25 +1182,28 @@ getindex(char **pptr, Value v)
 	} else {
 	    int com;
 
-	    if (a > 0)
-		a--;
+	    if (start > 0)
+		start--;
 	    if ((com = (*s == ','))) {
 		s++;
-		b = getarg(&s, &inv, v, 1, &dummy);
-		if (b > 0)
-		    b--;
+		len = getarg(&s, &inv, v, 1, &dummy);
+		if (len > 0) {
+		    len -= start;
+		    if (len < 0)
+			len = 0;
+		}
 	    } else {
-		b = we ? we : a;
+		len = wlen ? wlen : 1;
 	    }
 	    if (*s == ']' || *s == Outbrack) {
 		s++;
-		if (v->isarr && a == b && !com &&
+		if (v->isarr && len == 1 && !com &&
 		    (!(v->isarr & SCANPM_MATCHMANY) ||
 		     !(v->isarr & (SCANPM_MATCHKEY | SCANPM_MATCHVAL |
 				   SCANPM_KEYMATCH))))
 		    v->isarr = 0;
-		v->a = a;
-		v->b = b;
+		v->start = start;
+		v->len = len;
 	    } else
 		s = *pptr;
 	}
@@ -1258,7 +1264,8 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
 	    v = (Value) hcalloc(sizeof *v);
 	v->pm = argvparam;
 	v->inv = 0;
-	v->a = v->b = ppar - 1;
+	v->start = ppar - 1;
+	v->len = 1;
 	if (sav)
 	    *s = sav;
     } else {
@@ -1288,8 +1295,8 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
 	}
 	v->pm = pm;
 	v->inv = 0;
-	v->a = 0;
-	v->b = -1;
+	v->start = 0;
+	v->len = -1;
 	if (bracks > 0 && (*s == '[' || *s == Inbrack)) {
 	    if (getindex(&s, v)) {
 		*pptr = s;
@@ -1297,19 +1304,21 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
 	    }
 	} else if (!(flags & SCANPM_ASSIGNING) && v->isarr &&
 		   iident(*t) && isset(KSHARRAYS))
-	    v->b = 0, v->isarr = 0;
+	    v->len = 1, v->isarr = 0;
     }
     if (!bracks && *s)
 	return NULL;
     *pptr = s;
-    if (v->a > MAX_ARRLEN ||
-	v->a < -MAX_ARRLEN) {
-	zerr("subscript too %s: %d", (v->a < 0) ? "small" : "big", v->a);
+    if (v->start > MAX_ARRLEN ||
+	v->start < -MAX_ARRLEN) {
+	zerr("subscript too %s: %d", (v->start < 0) ? "small" : "big",
+	     v->start + !isset(KSHARRAYS));
 	return NULL;
     }
-    if (v->b > MAX_ARRLEN ||
-	v->b < -MAX_ARRLEN) {
-	zerr("subscript too %s: %d", (v->b < 0) ? "small" : "big", v->b);
+    if (v->start + v->len > MAX_ARRLEN ||
+	v->start + v->len < -MAX_ARRLEN) {
+	zerr("subscript too %s: %d", (v->len < 0) ? "small" : "big",
+	     v->start + v->len - !!isset(KSHARRAYS));
 	return NULL;
     }
     return v;
@@ -1326,7 +1335,7 @@ getstrvalue(Value v)
 	return hcalloc(1);
 
     if (v->inv && !(v->pm->flags & PM_HASHED)) {
-	sprintf(buf, "%d", v->a);
+	sprintf(buf, "%d", v->start);
 	s = dupstring(buf);
 	return s;
     }
@@ -1345,9 +1354,10 @@ getstrvalue(Value v)
 	if (v->isarr)
 	    s = sepjoin(ss, NULL, 1);
 	else {
-	    if (v->a < 0)
-		v->a += arrlen(ss);
-	    s = (v->a >= arrlen(ss) || v->a < 0) ? (char *) hcalloc(1) : ss[v->a];
+	    if (v->start < 0)
+		v->start += arrlen(ss);
+	    s = (v->start >= arrlen(ss) || v->start < 0) ?
+		(char *) hcalloc(1) : ss[v->start];
 	}
 	return s;
     case PM_INTEGER:
@@ -1367,18 +1377,18 @@ getstrvalue(Value v)
 	break;
     }
 
-    if (v->a == 0 && v->b == -1)
+    if (v->start == 0 && v->len == -1)
 	return s;
 
-    if (v->a < 0)
-	v->a += strlen(s);
-    if (v->b < 0)
-	v->b += strlen(s);
-    s = (v->a > (int)strlen(s)) ? dupstring("") : dupstring(s + v->a);
-    if (v->b < v->a)
+    if (v->start < 0)
+	v->start += strlen(s);
+    if (v->len < 0)
+	v->len += strlen(s) - v->start + 1;
+    s = (v->start > (int)strlen(s)) ? dupstring("") : dupstring(s + v->start);
+    if (v->len <= 0)
 	s[0] = '\0';
-    else if (v->b - v->a < (int)strlen(s))
-	s[v->b - v->a + 1 + (s[v->b - v->a] == Meta)] = '\0';
+    else if (v->len <= (int)strlen(s))
+	s[v->len + (s[v->len - 1] == Meta)] = '\0';
 
     return s;
 }
@@ -1399,25 +1409,25 @@ getarrvalue(Value v)
 	char buf[DIGBUFSIZE];
 
 	s = arrdup(nular);
-	sprintf(buf, "%d", v->a);
+	sprintf(buf, "%d", v->start);
 	s[0] = dupstring(buf);
 	return s;
     }
     s = getvaluearr(v);
-    if (v->a == 0 && v->b == -1)
+    if (v->start == 0 && v->len == -1)
 	return s;
-    if (v->a < 0)
-	v->a += arrlen(s);
-    if (v->b < 0)
-	v->b += arrlen(s);
-    if (v->a > arrlen(s) || v->a < 0)
+    if (v->start < 0)
+	v->start += arrlen(s);
+    if (v->len < 0)
+	v->len += arrlen(s) - v->start + 1;
+    if (v->start > arrlen(s) || v->start < 0)
 	s = arrdup(nular);
     else
-	s = arrdup(s + v->a);
-    if (v->b < v->a)
+	s = arrdup(s + v->start);
+    if (v->len <= 0)
 	s[0] = NULL;
-    else if (v->b - v->a < arrlen(s))
-	s[v->b - v->a + 1] = NULL;
+    else if (v->len <= arrlen(s))
+	s[v->len] = NULL;
     return s;
 }
 
@@ -1428,7 +1438,7 @@ getintvalue(Value v)
     if (!v || v->isarr)
 	return 0;
     if (v->inv)
-	return v->a;
+	return v->start;
     if (PM_TYPE(v->pm->flags) == PM_INTEGER)
 	return v->pm->gets.ifn(v->pm);
     if (v->pm->flags & (PM_EFLOAT|PM_FFLOAT))
@@ -1446,7 +1456,7 @@ getnumvalue(Value v)
     if (!v || v->isarr) {
 	mn.u.l = 0;
     } else if (v->inv) {
-	mn.u.l = v->a;
+	mn.u.l = v->start;
     } else if (PM_TYPE(v->pm->flags) == PM_INTEGER) {
 	mn.u.l = v->pm->gets.ifn(v->pm);
     } else if (v->pm->flags & (PM_EFLOAT|PM_FFLOAT)) {
@@ -1495,7 +1505,7 @@ setstrvalue(Value v, char *val)
     v->pm->flags &= ~PM_UNSET;
     switch (PM_TYPE(v->pm->flags)) {
     case PM_SCALAR:
-	if (v->a == 0 && v->b == -1) {
+	if (v->start == 0 && v->len == -1) {
 	    (v->pm->sets.cfn) (v->pm, val);
 	    if (v->pm->flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z) && !v->pm->ct)
 		v->pm->ct = strlen(val);
@@ -1506,22 +1516,22 @@ setstrvalue(Value v, char *val)
 	    z = dupstring((v->pm->gets.cfn) (v->pm));
 	    zlen = strlen(z);
 	    if (v->inv && unset(KSHARRAYS))
-		v->a--, v->b--;
-	    if (v->a < 0) {
-		v->a += zlen;
-		if (v->a < 0)
-		    v->a = 0;
+		v->start--;
+	    if (v->start < 0) {
+		v->start += zlen;
+		if (v->start < 0)
+		    v->start = 0;
 	    }
-	    if (v->a > zlen)
-		v->a = zlen;
-	    if (v->b < 0)
-		v->b += zlen;
-	    if (v->b > zlen - 1)
-		v->b = zlen - 1;
-	    x = (char *) zalloc(v->a + strlen(val) + zlen - v->b);
-	    strncpy(x, z, v->a);
-	    strcpy(x + v->a, val);
-	    strcat(x + v->a, z + v->b + 1);
+	    if (v->start > zlen)
+		v->start = zlen;
+	    if (v->len < 0)
+		v->len += zlen - v->start + 1;
+	    if (v->len > zlen - v->start)
+		v->len = zlen - v->start;
+	    x = (char *) zalloc(strlen(val) + zlen - v->len + 1);
+	    strncpy(x, z, v->start);
+	    strcpy(x + v->start, val);
+	    strcat(x + v->start, z + v->start + v->len);
 	    (v->pm->sets.cfn) (v->pm, x);
 	    zsfree(val);
 	}
@@ -1618,7 +1628,7 @@ setarrvalue(Value v, char **val)
 	zerr("attempt to assign array value to non-array", NULL, 0);
 	return;
     }
-    if (v->a == 0 && v->b == -1) {
+    if (v->start == 0 && v->len == -1) {
 	if (PM_TYPE(v->pm->flags) == PM_HASHED)
 	    arrhashsetfn(v->pm, val);
 	else
@@ -1633,30 +1643,30 @@ setarrvalue(Value v, char **val)
 	    return;
 	}
 	if (v->inv && unset(KSHARRAYS))
-	    v->a--, v->b--;
+	    v->start--;
 	q = old = v->pm->gets.afn(v->pm);
 	n = arrlen(old);
-	if (v->a < 0)
-	    v->a += n;
-	if (v->b < 0)
-	    v->b += n;
-	if (v->a < 0)
-	    v->a = 0;
-	if (v->b < 0)
-	    v->b = 0;
-
-	ll = v->a + arrlen(val);
-	if (v->b < n)
-	    ll += n - v->b;
+	if (v->start < 0)
+	    v->start += n;
+	if (v->len < 0)
+	    v->len += n - v->start + 1;
+	if (v->start < 0)
+	    v->start = 0;
+	if (v->len < 0)
+	    v->len = 0;
+
+	ll = v->start + arrlen(val);
+	if (v->start + v->len - 1 < n)
+	    ll += n - (v->start + v->len - 1);
 
 	p = new = (char **) zcalloc(sizeof(char *) * (ll + 1));
 
-	for (i = 0; i < v->a; i++)
+	for (i = 0; i < v->start; i++)
 	    *p++ = i < n ? ztrdup(*q++) : ztrdup("");
 	for (r = val; *r;)
 	    *p++ = ztrdup(*r++);
-	if (v->b + 1 < n)
-	    for (q = old + v->b + 1; *q;)
+	if (v->start + v->len < n)
+	    for (q = old + v->start + v->len; *q;)
 		*p++ = ztrdup(*q++);
 	*p = NULL;
 
@@ -2151,7 +2161,7 @@ arrhashsetfn(Param pm, char **val)
     HashTable opmtab = paramtab, ht = 0;
     char **aptr = val;
     Value v = (Value) hcalloc(sizeof *v);
-    v->b = -1;
+    v->len = -1;
 
     if (alen % 2) {
 	freearray(val);
diff --git a/Src/pattern.c b/Src/pattern.c
index 1ebcfd401..deb094d5f 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -807,7 +807,7 @@ patgetglobflags(char **strp, long *assertp)
 static long
 patcomppiece(int *flagp)
 {
-    long starter, next, pound, op;
+    long starter = 0, next, pound, op;
     int flags, flags2, kshchar, len, ch, patch;
     union upat up;
     char *nptr, *str0, cbuf[2];
@@ -1025,7 +1025,6 @@ patcomppiece(int *flagp)
 	    if (*patparse != Outang)
 		return 0;
 	    patparse++;
-	    starter = 0;	/* shut compiler up */
 	    switch(len) {
 	    case 3:
 		starter = patnode(P_NUMRNG);
diff --git a/Src/subst.c b/Src/subst.c
index beb99b5ee..c404f794d 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1138,7 +1138,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    v = (Value) hcalloc(sizeof *v);
 	    v->isarr = isarr;
 	    v->pm = pm;
-	    v->b = -1;
+	    v->len = -1;
 	    if (getindex(&s, v) || s == os)
 		break;
 	}
@@ -1154,9 +1154,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 	    if (v->pm->flags & PM_ARRAY) {
 		int tmplen = arrlen(v->pm->gets.afn(v->pm));
 
-		if (v->a < 0)
-		    v->a += tmplen + v->inv;
-		if (!v->inv && (v->a >= tmplen || v->a < 0))
+		if (v->start < 0)
+		    v->start += tmplen + v->inv;
+		if (!v->inv && (v->start >= tmplen || v->start < 0))
 		    vunset = 1;
 	    }
 	    if (!vunset) {
diff --git a/Src/zsh.h b/Src/zsh.h
index 007a84acc..9ac1e8646 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -467,8 +467,8 @@ struct value {
     int isarr;
     Param pm;		/* parameter node                      */
     int inv;		/* should we return the index ?        */
-    int a;		/* first element of array slice, or -1 */
-    int b;		/* last element of array slice, or -1  */
+    int start;		/* first element of array slice, or -1 */
+    int len;		/* length of array slice, or -1        */
     char **arr;		/* cache for hash turned into array */
 };
 
diff --git a/Test/07cond.ztst b/Test/07cond.ztst
index 827f2744e..ee502d303 100644
--- a/Test/07cond.ztst
+++ b/Test/07cond.ztst
@@ -99,6 +99,7 @@
 
 # can't be bothered with -S
 
+  sleep 1
   cat unmodified
   touch newnewnew
   [[ -N newnewnew && ! -N unmodified ]]