Fix zero-repeated subroutine call at start of pattern bug, which recorded an

incorrect first code unit.
This commit is contained in:
Philip.Hazel 2018-10-20 09:28:02 +00:00
parent 8a0dd8955a
commit 996892434f
4 changed files with 49 additions and 3 deletions

View File

@ -43,6 +43,11 @@ path. Also, when a match fails, set the subject field in the match data to NULL
for tidiness - none of the substring extractors should reference this after for tidiness - none of the substring extractors should reference this after
match failure. match failure.
11. If a pattern started with a subroutine call that had a quantifier with a
minimum of zero, an incorrect "match must start with this character" could be
recorded. Example: /(?&xxx)*ABC(?<xxx>XYZ)/ would (incorrectly) expect 'A' to
be the first character of a match.
Version 10.32 10-September-2018 Version 10.32 10-September-2018
------------------------------- -------------------------------

View File

@ -6095,7 +6095,7 @@ for (;; pptr++)
} }
goto GROUP_PROCESS_NOTE_EMPTY; goto GROUP_PROCESS_NOTE_EMPTY;
/* The DEFINE condition is always false. It's internal groups may never /* The DEFINE condition is always false. Its internal groups may never
be called, so matched_char must remain false, hence the jump to be called, so matched_char must remain false, hence the jump to
GROUP_PROCESS rather than GROUP_PROCESS_NOTE_EMPTY. */ GROUP_PROCESS rather than GROUP_PROCESS_NOTE_EMPTY. */
@ -6435,8 +6435,8 @@ for (;; pptr++)
groupnumber = ng->number; groupnumber = ng->number;
/* For a recursion, that's all that is needed. We can now go to /* For a recursion, that's all that is needed. We can now go to
the code above that handles numerical recursion, applying it to the code that handles numerical recursion, applying it to the first
the first group with the given name. */ group with the given name. */
if (meta == META_RECURSE_BYNAME) if (meta == META_RECURSE_BYNAME)
{ {
@ -7486,6 +7486,8 @@ for (;; pptr++)
groupsetfirstcu = FALSE; groupsetfirstcu = FALSE;
cb->had_recurse = TRUE; cb->had_recurse = TRUE;
if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE; if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
zerofirstcu = firstcu;
zerofirstcuflags = firstcuflags;
break; break;

15
testdata/testinput1 vendored
View File

@ -6328,4 +6328,19 @@ ef) x/x,mark
\= Expect no match \= Expect no match
aaaa aaaa
/ (?<word> \w+ )* \. /xi
pokus.
/(?(DEFINE) (?<word> \w+ ) ) (?&word)* \./xi
pokus.
/(?(DEFINE) (?<word> \w+ ) ) ( (?&word)* ) \./xi
pokus.
/(?&word)* (?(DEFINE) (?<word> \w+ ) ) \./xi
pokus.
/(?&word)* \. (?<word> \w+ )/xi
pokus.hokus
# End of testinput1 # End of testinput1

24
testdata/testoutput1 vendored
View File

@ -10025,4 +10025,28 @@ No match
aaaa aaaa
No match No match
/ (?<word> \w+ )* \. /xi
pokus.
0: pokus.
1: pokus
/(?(DEFINE) (?<word> \w+ ) ) (?&word)* \./xi
pokus.
0: pokus.
/(?(DEFINE) (?<word> \w+ ) ) ( (?&word)* ) \./xi
pokus.
0: pokus.
1: <unset>
2: pokus
/(?&word)* (?(DEFINE) (?<word> \w+ ) ) \./xi
pokus.
0: pokus.
/(?&word)* \. (?<word> \w+ )/xi
pokus.hokus
0: pokus.hokus
1: hokus
# End of testinput1 # End of testinput1