summaryrefslogtreecommitdiff
path: root/regcomp.c
diff options
context:
space:
mode:
authorNick Cleaton <nick@cleaton.net>2010-11-29 22:26:43 -0800
committerFather Chrysostomos <sprout@cpan.org>2010-11-30 05:01:59 -0800
commit779bcb7d68c0d77839c133a5b8429f43e63a961f (patch)
tree070965ea567c7d41ba3d794923a9f25612785f2c /regcomp.c
parentf603091d864eb38dabe995c559f17edd4ea9e2d6 (diff)
downloadperl-779bcb7d68c0d77839c133a5b8429f43e63a961f.tar.gz
[perl #79152] super-linear cache can prevent a valid match
The super-linear cache in regexec.c can prevent a valid match from being detected. For example: print "yay\n" if 'xayxay' =~ /(q1|.)*(q2|.)*(x(a|bc)*y){2,}/; This should match, but it doesn't because the cache fails to distinguish between matching the final xay to x(a|bc)*y as the first instance of the {2,} and matching it in the same position as the second instance. This seems to do the trick.
Diffstat (limited to 'regcomp.c')
-rw-r--r--regcomp.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/regcomp.c b/regcomp.c
index 4092d7957c..4b69bf74ee 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -3246,13 +3246,16 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp,
f |= SCF_DO_STCLASS_AND;
f &= ~SCF_DO_STCLASS_OR;
}
- /* These are the cases when once a subexpression
- fails at a particular position, it cannot succeed
- even after backtracking at the enclosing scope.
-
- XXXX what if minimal match and we are at the
- initial run of {n,m}? */
- if ((mincount != maxcount - 1) && (maxcount != REG_INFTY))
+ /* Exclude from super-linear cache processing any {n,m}
+ regops for which the combination of input pos and regex
+ pos is not enough information to determine if a match
+ will be possible.
+
+ For example, in the regex /foo(bar\s*){4,8}baz/ with the
+ regex pos at the \s*, the prospects for a match depend not
+ only on the input position but also on how many (bar\s*)
+ repeats into the {4,8} we are. */
+ if ((mincount > 1) || (maxcount > 1 && maxcount != REG_INFTY))
f &= ~SCF_WHILEM_VISITED_POS;
/* This will finish on WHILEM, setting scan, or on NULL: */