summaryrefslogtreecommitdiff
path: root/Src/pattern.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/pattern.c')
-rw-r--r--Src/pattern.c57
1 files changed, 44 insertions, 13 deletions
diff --git a/Src/pattern.c b/Src/pattern.c
index 4701522d1..c0bc11cc4 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -1818,10 +1818,9 @@ patmatch(Upat prog)
syncstrp->p = (unsigned char *)zshcalloc(patinlen);
while ((ret = patmatch(P_OPERAND(scan)))) {
unsigned char *syncpt;
- char savchar, *testptr;
- char *savpatinstart = patinstart;
+ char *savpatinstart, *origsave, *origpatinstart;
int savforce = forceerrs, savpatinlen = patinlen;
- int savpatflags = patflags;
+ int savpatflags = patflags, synclen;
forceerrs = -1;
savglobdots = globdots;
matchederrs = errsfound;
@@ -1837,16 +1836,38 @@ patmatch(Upat prog)
*/
for (syncpt = syncstrp->p; !*syncpt; syncpt++)
;
- testptr = patinstart + (syncpt - syncstrp->p);
- DPUTS(testptr > matchpt, "BUG: EXCSYNC failed");
- savchar = *testptr;
- /*
- * If this isn't really the end of the string,
- * remember this for the (#e) assertion.
- */
- if (savchar)
+ synclen = syncpt - syncstrp->p;
+ if (patinstart[synclen]) {
+ /*
+ * We need to truncate the string at
+ * this point. Copy a whole load of
+ * stuff to avoid modifying the string.
+ * This includes (at least) patinstart,
+ * patinput and save.
+ */
+ origsave = save;
+ origpatinstart = patinstart;
+
+ DPUTS(patinstart + synclen > matchpt,
+ "BUG: EXCSYNC failed");
+
+ savpatinstart = patinstart =
+ ztrduppfx(patinstart, synclen);
+ patinput = patinstart +
+ (patinput - origpatinstart);
+ save = patinstart + (save - origpatinstart);
+ /*
+ * If this isn't really the end of the string,
+ * remember this for the (#e) assertion.
+ */
patflags |= PAT_NOTEND;
- *testptr = '\0';
+ }
+ else
+ {
+ /* Don't need to copy, already right length */
+ origsave = origpatinstart = NULL;
+ savpatinstart = patinstart;
+ }
next = PATNEXT(scan);
while (next && P_ISEXCLUDE(next)) {
char *buf = NULL;
@@ -1893,7 +1914,17 @@ patmatch(Upat prog)
break;
next = PATNEXT(next);
}
- *testptr = savchar;
+ /*
+ * Free copied string and restore if
+ * we needed to truncate.
+ */
+ if (origpatinstart) {
+ patinput = origpatinstart +
+ (patinput - patinstart);
+ zfree(patinstart, synclen+1);
+ patinstart = origpatinstart;
+ save = origsave;
+ }
patflags = savpatflags;
globdots = savglobdots;
forceerrs = savforce;