aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2023-02-20 21:22:41 -0500
committerStefan Monnier2023-02-20 21:22:41 -0500
commit5a864f23eb8a36ef435136c5b41cb01b875df399 (patch)
treecc7b6d2ebd44f079f0f1a2ce99783a72bcba0eaf /src
parente83c78b8c7784254c2c6f043530ab325c2fa7f16 (diff)
downloademacs-5a864f23eb8a36ef435136c5b41cb01b875df399.tar.gz
emacs-5a864f23eb8a36ef435136c5b41cb01b875df399.zip
regex-emacs.c: Reduce the use of backtracking a bit further
bug#61514 exhibited some undesirable backtracking in a case where it's easy to avoid it by making `mutually_exclusive_p` just a bit more careful. * src/regex-emacs.c (mutually_exclusive_p): Handle `on_failure_jump`s. * test/src/regex-emacs-tests.el (regexp-tests-backtrack-optimization): Add a few tests.
Diffstat (limited to 'src')
-rw-r--r--src/regex-emacs.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/regex-emacs.c b/src/regex-emacs.c
index 2dca0d16ad9..2571812cb39 100644
--- a/src/regex-emacs.c
+++ b/src/regex-emacs.c
@@ -3653,6 +3653,7 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1,
3653 re_opcode_t op2; 3653 re_opcode_t op2;
3654 bool multibyte = RE_MULTIBYTE_P (bufp); 3654 bool multibyte = RE_MULTIBYTE_P (bufp);
3655 unsigned char *pend = bufp->buffer + bufp->used; 3655 unsigned char *pend = bufp->buffer + bufp->used;
3656 re_char *p2_orig = p2;
3656 3657
3657 eassert (p1 >= bufp->buffer && p1 < pend 3658 eassert (p1 >= bufp->buffer && p1 < pend
3658 && p2 >= bufp->buffer && p2 <= pend); 3659 && p2 >= bufp->buffer && p2 <= pend);
@@ -3822,6 +3823,23 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1,
3822 case notcategoryspec: 3823 case notcategoryspec:
3823 return ((re_opcode_t) *p1 == categoryspec && p1[1] == p2[1]); 3824 return ((re_opcode_t) *p1 == categoryspec && p1[1] == p2[1]);
3824 3825
3826 case on_failure_jump_nastyloop:
3827 case on_failure_jump_smart:
3828 case on_failure_jump_loop:
3829 case on_failure_keep_string_jump:
3830 case on_failure_jump:
3831 {
3832 int mcnt;
3833 p2++;
3834 EXTRACT_NUMBER_AND_INCR (mcnt, p2);
3835 /* Don't just test `mcnt > 0` because non-greedy loops have
3836 their test at the end with an unconditional jump at the start. */
3837 if (p2 + mcnt > p2_orig) /* Ensure forward progress. */
3838 return (mutually_exclusive_p (bufp, p1, p2)
3839 && mutually_exclusive_p (bufp, p1, p2 + mcnt));
3840 break;
3841 }
3842
3825 default: 3843 default:
3826 ; 3844 ;
3827 } 3845 }