Skip to content

Commit afe1b03

Browse files
gh-153169: Look through marks in the regex alternation quick check
The BRANCH quick check skips an alternative whose first literal or character set cannot match the current character, but only when it is the very first op, so alternatives starting with a capturing group or with a repeat with a nonzero minimum were never skipped. Look through MARK ops and into the repeated item. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent a47a66c commit afe1b03

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Speed up matching of regular expression alternations whose alternatives
2+
start with a capturing group or with a repeat with a nonzero minimum:
3+
such alternatives can now be skipped without entering them when their
4+
first character cannot match.

Modules/_sre/sre_lib.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,42 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel)
875875
!SRE(charset)(state, pattern + 3,
876876
(SRE_CODE) *ptr)))
877877
continue;
878+
if (pattern[1] == SRE_OP_MARK) {
879+
/* the quick checks above also apply behind group marks
880+
and to a repeat of one item with a nonzero minimum */
881+
const SRE_CODE *alt = pattern + 1;
882+
do {
883+
alt += 2;
884+
} while (alt[0] == SRE_OP_MARK);
885+
if ((alt[0] == SRE_OP_REPEAT_ONE ||
886+
alt[0] == SRE_OP_MIN_REPEAT_ONE ||
887+
alt[0] == SRE_OP_POSSESSIVE_REPEAT_ONE) &&
888+
alt[2] > 0)
889+
alt += 4;
890+
if (alt[0] == SRE_OP_LITERAL &&
891+
(ptr >= end ||
892+
(SRE_CODE) *ptr != alt[1]))
893+
continue;
894+
if (alt[0] == SRE_OP_IN &&
895+
(ptr >= end ||
896+
!SRE(charset)(state, alt + 2,
897+
(SRE_CODE) *ptr)))
898+
continue;
899+
}
900+
else if ((pattern[1] == SRE_OP_REPEAT_ONE ||
901+
pattern[1] == SRE_OP_MIN_REPEAT_ONE ||
902+
pattern[1] == SRE_OP_POSSESSIVE_REPEAT_ONE) &&
903+
pattern[3] > 0) {
904+
if (pattern[5] == SRE_OP_LITERAL &&
905+
(ptr >= end ||
906+
(SRE_CODE) *ptr != pattern[6]))
907+
continue;
908+
if (pattern[5] == SRE_OP_IN &&
909+
(ptr >= end ||
910+
!SRE(charset)(state, pattern + 7,
911+
(SRE_CODE) *ptr)))
912+
continue;
913+
}
878914
state->ptr = ptr;
879915
DO_JUMP(JUMP_BRANCH, jump_branch, pattern+1);
880916
if (ret) {

0 commit comments

Comments
 (0)