Skip to content

Commit 0b2c2a8

Browse files
committed
RT #120446: /\Ga/ running slowly on long strings
This commit reverts my commit cf44e60 (except for the tests), which incorrectly disabled fix-string intuiting in the presence of anchored \G. I thought that the old behaviour was logically incorrect, but it wasn't (or at least I don't see it that way now, and none of the tests I added at the time fail under the old regime).
1 parent ea23863 commit 0b2c2a8

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

regexec.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -667,16 +667,24 @@ Perl_re_intuit_start(pTHX_
667667
}
668668
check = prog->check_substr;
669669
}
670-
if ((prog->extflags & RXf_ANCH) /* Match at beg-of-str or after \n */
671-
&& !(prog->extflags & RXf_ANCH_GPOS)) /* \G isn't a BOS or \n */
672-
{
673-
ml_anch = !( (prog->extflags & RXf_ANCH_SINGLE)
670+
if (prog->extflags & RXf_ANCH) { /* Match at \G, beg-of-str or after \n */
671+
ml_anch = !( (prog->extflags & RXf_ANCH_SINGLE)
674672
|| ( (prog->extflags & RXf_ANCH_BOL)
675673
&& !multiline ) ); /* Check after \n? */
676674

677675
if (!ml_anch) {
678-
if ( !(prog->intflags & PREGf_IMPLICIT) /* not a real BOL */
679-
&& (strpos != strbeg)) {
676+
/* we are only allowed to match at BOS or \G */
677+
678+
if (prog->extflags & RXf_ANCH_GPOS) {
679+
/* in this case, we hope(!) that the caller has already
680+
* set strpos to pos()-gofs, and will already have checked
681+
* that this anchor position is legal
682+
*/
683+
;
684+
}
685+
else if (!(prog->intflags & PREGf_IMPLICIT) /* not a real BOL */
686+
&& (strpos != strbeg))
687+
{
680688
DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log, "Not at start...\n"));
681689
goto fail;
682690
}
@@ -2277,7 +2285,7 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, char *strend,
22772285

22782286
/* in the presence of \G, we may need to start looking earlier in
22792287
* the string than the suggested start point of stringarg:
2280-
* if gofs->prog is set, then that's a known, fixed minimum
2288+
* if prog->gofs is set, then that's a known, fixed minimum
22812289
* offset, such as
22822290
* /..\G/: gofs = 2
22832291
* /ab|c\G/: gofs = 1

t/re/pat.t

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ BEGIN {
2020
require './test.pl';
2121
}
2222

23-
plan tests => 701; # Update this when adding/deleting tests.
23+
plan tests => 702; # Update this when adding/deleting tests.
2424

2525
run_tests() unless caller;
2626

@@ -1489,6 +1489,24 @@ EOP
14891489
is $^R, 42, 'assigning to *^R does not result in a crash';
14901490
}
14911491

1492+
{
1493+
# [perl #120446]
1494+
# this code should be virtually instantaneous. If it takes 10s of
1495+
# seconds, there a bug in intuit_start.
1496+
# (this test doesn't actually test for slowness - that involves
1497+
# too much danger of false positives on loaded machines - but by
1498+
# putting it here, hopefully someone might notice if it suddenly
1499+
# runs slowly)
1500+
my $s = ('a' x 1_000_000) . 'b';
1501+
my $i = 0;
1502+
for (1..10_000) {
1503+
pos($s) = $_;
1504+
$i++ if $s =~/\Gb/g;
1505+
}
1506+
is($i, 0, "RT 120446: mustn't run slowly");
1507+
}
1508+
1509+
14921510
} # End of sub run_tests
14931511

14941512
1;

0 commit comments

Comments
 (0)