Subject: bug#66218: 29.1.50; `beginning-of-defun' jumps to wrong position in `emacs-lisp-mode'

From: Jens Schmidt <[email-masked]>
Date: Sat, 07 Oct 2023 22:31:50 +0200

Eli Zaretskii <[email-masked]> writes:

>> From: Jens Schmidt <[email-masked]>
>> Cc: [email-masked]
>> Date: Sat, 07 Oct 2023 19:39:52 +0200

>> Even if the patch is so innocent as adding a `save-match-data' in the
>> right place?
>
> No patch is "innocent" in Emacs, believe me.  But yes, even so.

Please let me summarize (plus one new point):

- This bug is hard to reproduce, also due to its asynchronous nature.

- It might not affect many users, but if one is affected, it might be
  highly confusing.  I could imagine a report like

    "If I press C-M-a at the end of a very long function, it sometimes
    does not jump to the beginning of that function."

  just because under some circumstances the beginning of that function
  might not have been propertized yet.

- The fix is a rather light-weight and IMO obvious change: Use
  `save-match-data' when you want to keep your match data save.

If that does not convince you for Emacs 29, fine with me, let's go for
master, then.  Updated patch attached.

Thanks.

Just for the record: A work-around on Emacs 29 would be to set
`syntax-propertize-function' to nil in `emacs-lisp-mode'.  Or to advise
function `syntax-ppss' to save match data.

>From 31564be89042e5a4184fa7b8e29d200f30ec596e Mon Sep 17 00:00:00 2001
From: Jens Schmidt <[email-masked]>
Date: Tue, 26 Sep 2023 21:36:19 +0200
Subject: [PATCH] Fix beginning-of-defun not jumping to BOF

In batch mode or when font-lock and some other niceties are switched
off, function `syntax-ppss' can modify match data held by function
`beginning-of-defun-raw'.  In that case, `beginning-of-defun' can jump
to some seemingly arbitrary position, and not the actual BOF.

* lisp/emacs-lisp/lisp.el (beginning-of-defun-raw): Save match data
around a call to `syntax-ppss'. (Bug#66218)
---
 lisp/emacs-lisp/lisp.el | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
index a4aa79c171e..ee481dc4ed3 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/emacs-lisp/lisp.el
@@ -422,7 +422,8 @@ beginning-of-defun-raw
 				       "\\(?:" defun-prompt-regexp "\\)\\s(")
 			     "^\\s(")
 			                      nil 'move arg))
-                    (nth 8 (syntax-ppss))))
+                    (save-match-data
+                      (nth 8 (syntax-ppss)))))
            found)
 	 (progn (goto-char (1- (match-end 0)))
                 t)))
-- 
2.30.2