summaryrefslogtreecommitdiff
path: root/regexec.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2014-02-07 16:43:19 +0000
committerDavid Mitchell <davem@iabyn.com>2014-02-08 14:04:55 +0000
commitec19cf6bc850473f27f9bb92a316cd58fd76797c (patch)
treef9b15b83a992a1035c37bee788ad46576d6e7637 /regexec.c
parente7a14a9c2dc20193ef41eda2055fda4ef2dc6c6e (diff)
downloadperl-ec19cf6bc850473f27f9bb92a316cd58fd76797c.tar.gz
re_intuit_start(): don't decrease other_last
The /^../m failure code did an unconditional other_last = rx_origin; if other_last was already high, it could get shrunk and we'd end up running fbm over the same bit of string repeatedly. The following code $s = "-ab\n" x 500_000; $s .= 'abx'; $s =~ /^ab.*x/m; (which went quadratic on length) reduces from minutes to millisecs with this commit. This is because we'd keep going back to near the beginning of the string and searching for 'x' again.
Diffstat (limited to 'regexec.c')
-rw-r--r--regexec.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/regexec.c b/regexec.c
index 181afe7d35..ed6f9fc4c7 100644
--- a/regexec.c
+++ b/regexec.c
@@ -1121,7 +1121,8 @@ Perl_re_intuit_start(pTHX_
DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log,
" Found /%s^%s/m, restarting lookup for check-string at offset %ld...\n",
PL_colors[0], PL_colors[1], (long)(t + 1 - strpos)));
- other_last = rx_origin;
+ if (other_last < rx_origin)
+ other_last = rx_origin;
goto restart;
}