about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorPeter Stephenson <p.stephenson@samsung.com>2023-08-01 14:32:55 +0100
committerPeter Stephenson <p.stephenson@samsung.com>2023-08-01 14:32:55 +0100
commitaa8e4a02904b3a1c4b3064eb7502d887f7de958b (patch)
treeda94d9b9aa4aecc7b4573ea02f5b151d0802a05e /Src
parent95269147fcbd85961d652ab419bb168a8aafcd14 (diff)
downloadzsh-aa8e4a02904b3a1c4b3064eb7502d887f7de958b.tar.gz
zsh-aa8e4a02904b3a1c4b3064eb7502d887f7de958b.tar.xz
zsh-aa8e4a02904b3a1c4b3064eb7502d887f7de958b.zip
52008: Pattern bug with branches + exclusion
Add tests.
Diffstat (limited to 'Src')
-rw-r--r--Src/pattern.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/Src/pattern.c b/Src/pattern.c
index 3edda1772..2a1a514fb 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -2987,14 +2987,15 @@ patmatch(Upat prog)
 	case P_EXCSYNC:
 	    /* See the P_EXCLUDE code below for where syncptr comes from */
 	    {
-		unsigned char *syncptr;
+		unsigned char *syncstart, *syncptr, *ptr;
 		Upat after;
 		after = P_OPERAND(scan);
 		DPUTS(!P_ISEXCLUDE(after),
 		      "BUG: EXCSYNC not followed by EXCLUDE.");
 		DPUTS(!P_OPERAND(after)->p,
 		      "BUG: EXCSYNC not handled by EXCLUDE");
-		syncptr = P_OPERAND(after)->p + (patinput - patinstart);
+		syncstart = P_OPERAND(after)->p;
+		syncptr = syncstart + (patinput - patinstart);
 		/*
 		 * If we already matched from here, this time we fail.
 		 * See WBRANCH code for story about error count.
@@ -3009,6 +3010,23 @@ patmatch(Upat prog)
 		 * failed anyway.
 		 */
 		*syncptr = errsfound + 1;
+		/*
+		 * Because of backtracking, any match before this point
+		 * can't apply to the current branch we're on so is now
+		 * a failure --- this can happen if, on a previous
+		 * branch, we initially marked a success before failing
+		 * on a later part of the pattern after marking up the
+		 * P_EXCSYNC (even an end anchor will have this effect).
+		 * To make sure we record the current match point
+		 * correctly, mark those down now.
+		 *
+		 * This might have side effects on the efficiency of
+		 * pathological cases involving nested branches.  To
+		 * fix that we'd probably need to record matches on
+		 * different branches separately.
+		 */
+		for (ptr = syncstart; ptr < syncptr; ++ptr)
+		    *ptr = 0;
 	    }
 	    break;
 	case P_EXCEND: