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.
This commit is contained in:
parent
e83c78b8c7
commit
5a864f23eb
2 changed files with 29 additions and 0 deletions
|
@ -3653,6 +3653,7 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1,
|
|||
re_opcode_t op2;
|
||||
bool multibyte = RE_MULTIBYTE_P (bufp);
|
||||
unsigned char *pend = bufp->buffer + bufp->used;
|
||||
re_char *p2_orig = p2;
|
||||
|
||||
eassert (p1 >= bufp->buffer && p1 < pend
|
||||
&& p2 >= bufp->buffer && p2 <= pend);
|
||||
|
@ -3822,6 +3823,23 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1,
|
|||
case notcategoryspec:
|
||||
return ((re_opcode_t) *p1 == categoryspec && p1[1] == p2[1]);
|
||||
|
||||
case on_failure_jump_nastyloop:
|
||||
case on_failure_jump_smart:
|
||||
case on_failure_jump_loop:
|
||||
case on_failure_keep_string_jump:
|
||||
case on_failure_jump:
|
||||
{
|
||||
int mcnt;
|
||||
p2++;
|
||||
EXTRACT_NUMBER_AND_INCR (mcnt, p2);
|
||||
/* Don't just test `mcnt > 0` because non-greedy loops have
|
||||
their test at the end with an unconditional jump at the start. */
|
||||
if (p2 + mcnt > p2_orig) /* Ensure forward progress. */
|
||||
return (mutually_exclusive_p (bufp, p1, p2)
|
||||
&& mutually_exclusive_p (bufp, p1, p2 + mcnt));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
|
|
@ -872,4 +872,15 @@ This evaluates the TESTS test cases from glibc."
|
|||
(should (equal (string-match "\\`\\(?:ab\\)*\\'" "a") nil))
|
||||
(should (equal (string-match "\\`a\\{2\\}*\\'" "a") nil)))
|
||||
|
||||
(ert-deftest regexp-tests-backtrack-optimization () ;bug#61514
|
||||
;; Make sure we don't use up the regexp stack needlessly.
|
||||
(with-current-buffer (get-buffer-create "*bug*")
|
||||
(erase-buffer)
|
||||
(insert (make-string 1000000 ?x) "=")
|
||||
(goto-char (point-min))
|
||||
(should (looking-at "x*=*"))
|
||||
(should (looking-at "x*\\(=\\|:\\)"))
|
||||
(should (looking-at "x*\\(=\\|:\\)*"))
|
||||
(should (looking-at "x*=*?"))))
|
||||
|
||||
;;; regex-emacs-tests.el ends here
|
||||
|
|
Loading…
Add table
Reference in a new issue