Fix non-passing of mark values out of recursions.

This commit is contained in:
Philip.Hazel 2017-04-04 11:37:21 +00:00
parent fcd0c39b26
commit 0757041114
4 changed files with 24 additions and 13 deletions

View File

@ -34,6 +34,8 @@ bugs were never in fully released code, but are noted here for the record.
(d) Captures in negative assertions that were used as conditions were not (d) Captures in negative assertions that were used as conditions were not
happening if the assertion matched via (*ACCEPT). happening if the assertion matched via (*ACCEPT).
(e) Mark values were not being passed out of recursions.
2. Now that pcre2_match() no longer uses recursive function calls (see above), 2. Now that pcre2_match() no longer uses recursive function calls (see above),
the "match limit recursion" value seems misnamed. It still exists, and limits the "match limit recursion" value seems misnamed. It still exists, and limits
the depth of tree that is searched. To avoid future confusion, it has been the depth of tree that is searched. To avoid future confusion, it has been

View File

@ -725,7 +725,8 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
where we know the starting frame is at the top of the chained frames, in where we know the starting frame is at the top of the chained frames, in
this case we have to search back for the relevant frame in case other types this case we have to search back for the relevant frame in case other types
of group that use chained frames have intervened. Multiple OP_CLOSEs always of group that use chained frames have intervened. Multiple OP_CLOSEs always
come innermost first, which matches the chain order. */ come innermost first, which matches the chain order. We can ignore this in
a recursion, because captures are not passed out of recursions. */
case OP_CLOSE: case OP_CLOSE:
if (Fcurrent_recurse == RECURSE_UNSET) if (Fcurrent_recurse == RECURSE_UNSET)
@ -746,23 +747,21 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
Fovector[offset+1] = Feptr - mb->start_subject; Fovector[offset+1] = Feptr - mb->start_subject;
if (offset >= Foffset_top) Foffset_top = offset + 2; if (offset >= Foffset_top) Foffset_top = offset + 2;
} }
Fecode += PRIV(OP_lengths)[*Fecode]; Fecode += PRIV(OP_lengths)[*Fecode];
break; break;
/* ===================================================================== */ /* ===================================================================== */
/* End of the pattern, either real or forced. In an assertion ACCEPT, /* Real or forced end of the pattern, assertion, or recursion. In an
update the last used pointer and remember the current frame so that the assertion ACCEPT, update the last used pointer and remember the current
captures can be fished out of it. */ frame so that the captures can be fished out of it. */
case OP_ASSERT_ACCEPT: case OP_ASSERT_ACCEPT:
if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr; if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
assert_accept_frame = F; assert_accept_frame = F;
RRETURN(MATCH_ACCEPT); RRETURN(MATCH_ACCEPT);
/* The real end, or top-level (*ACCEPT). If recursing, we have to find the /* If recursing, we have to find the most recent recursion. */
most recent recursion. */
case OP_ACCEPT: case OP_ACCEPT:
case OP_END: case OP_END:
@ -782,10 +781,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
} }
/* N is now the frame of the recursion; the previous frame is at the /* N is now the frame of the recursion; the previous frame is at the
OP_RECURSE position. Go back there, copying the current subject position, OP_RECURSE position. Go back there, copying the current subject position
and move on past the OP_RECURSE. */ and mark, and move on past the OP_RECURSE. */
P->eptr = Feptr; P->eptr = Feptr;
P->mark = Fmark;
F = P; F = P;
Fecode += 1 + LINK_SIZE; Fecode += 1 + LINK_SIZE;
continue; continue;
@ -5078,10 +5078,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
} }
} }
/* Now run the recursion. If it successfully completes, it re-instates the /* Now run the recursion, branch by branch. */
previous values of the captures and continues, just like a non-capturing
bracket. We must leave Fecode unchanged so that the ending code can find
out where to continue. */
Lstart_branch = bracode; Lstart_branch = bracode;
Lframe_type = GF_RECURSE | number; Lframe_type = GF_RECURSE | number;

5
testdata/testinput2 vendored
View File

@ -5005,5 +5005,10 @@ a)"xI
/^ (?(DEFINE) (..(*ACCEPT)|...) ) (?1)$/x /^ (?(DEFINE) (..(*ACCEPT)|...) ) (?1)$/x
\= Expect no match \= Expect no match
abc abc
# Perl gives no match for this one
/(a(*MARK:m)(*ACCEPT)){0}(?1)/mark
abc
# End of testinput2 # End of testinput2

View File

@ -15529,6 +15529,13 @@ Callout 1: last capture = 1
\= Expect no match \= Expect no match
abc abc
No match No match
# Perl gives no match for this one
/(a(*MARK:m)(*ACCEPT)){0}(?1)/mark
abc
0: a
MK: m
# End of testinput2 # End of testinput2
Error -63: PCRE2_ERROR_BADDATA (unknown error number) Error -63: PCRE2_ERROR_BADDATA (unknown error number)