Fix freeze in cperl-mode when editing a regexp

* lisp/progmodes/cperl-mode.el (cperl-forward-group-in-re): Make
sure that an error is reported back to the caller (Bug#16368).

* test/lisp/progmodes/cperl-mode-tests.el (cperl-mode-test-bug-16368):
Tests for balanced (no error) and unbalanced (caught exception)
cases of `cperl-forward-group-in-re'.
This commit is contained in:
Harald Jörg 2020-09-03 22:11:47 +02:00 committed by Stefan Kangas
parent 4ea928e14f
commit 7921b5db10
2 changed files with 27 additions and 5 deletions

View file

@ -3241,8 +3241,8 @@ Return the error message (if any). Does not work if delimiter is `)'.
Works before syntax recognition is done."
;; Works *before* syntax recognition is done
(or st-l (setq st-l (list nil))) ; Avoid overwriting '()
(let (st b reset-st)
(condition-case b
(let (st result reset-st)
(condition-case err
(progn
(setq st (cperl-cached-syntax-table st-l))
(modify-syntax-entry ?\( "()" st)
@ -3250,8 +3250,7 @@ Works before syntax recognition is done."
(setq reset-st (syntax-table))
(set-syntax-table st)
(forward-sexp 1))
(error (message
"cperl-forward-group-in-re: error %s" b)))
(error (setq result err)))
;; now restore the initial state
(if st
(progn
@ -3259,7 +3258,7 @@ Works before syntax recognition is done."
(modify-syntax-entry ?\) "." st)))
(if reset-st
(set-syntax-table reset-st))
b))
result))
(defvar font-lock-string-face)

View file

@ -33,6 +33,8 @@
(defvar cperl-test-mode #'cperl-mode)
(require 'cperl-mode)
(defun cperl-test-ppss (text regexp)
"Return the `syntax-ppss' of the first character matched by REGEXP in TEXT."
(interactive)
@ -63,4 +65,25 @@ have a face property."
(let ((code "{ $a- / $b } # /"))
(should (equal (nth 8 (cperl-test-ppss code "/")) 7))))
(ert-deftest cperl-mode-test-bug-16368 ()
"Verify that `cperl-forward-group-in-re' doesn't hide errors."
(skip-unless (eq cperl-test-mode #'cperl-mode))
(let ((code "/(\\d{4})(?{2}/;") ; the regex from the bug report
(result))
(with-temp-buffer
(insert code)
(goto-char 9)
(setq result (cperl-forward-group-in-re))
(should (equal (car result) 'scan-error))
(should (equal (nth 1 result) "Unbalanced parentheses"))
(should (= (point) 9)))) ; point remains unchanged on error
(let ((code "/(\\d{4})(?{2})/;") ; here all parens are balanced
(result))
(with-temp-buffer
(insert code)
(goto-char 9)
(setq result (cperl-forward-group-in-re))
(should (equal result nil))
(should (= (point) 15))))) ; point has skipped the group
;;; cperl-mode-tests.el ends here