Subject: Re: bug#61215: 29.0.60; font-lock broken in diff-mode with long lines

From: Eli Zaretskii <[email-masked]>
Date: Fri, 03 Feb 2023 13:59:57 +0200

> From: Juri Linkov <[email-masked]>
> Cc: [email-masked]
> Date: Fri, 03 Feb 2023 09:53:57 +0200
> 
> >> 1. Set debug-on-error and backtrace-on-redisplay-error to t
> >> 2. Create a commit with some diff hunks in a prog mode at the beginning,
> >>    and a single-line 1MB file added at the end;
> >> 3. From *vc-change-log* type `d' on that commit that opens *vc-diff* buffer
> >> 4. Scroll the *vc-diff* buffer
> >>
> >> It displays an error in the *Warning* buffer:
> >>
> >>   ⛔ Warning (error): Error in a redisplay Lisp hook.  See buffer *Redisplay_trace*
> >
> > Can you reproduce this easily?
> 
> Once you create such a commit, it's easy to reproduce this on it.

The recipe is quite complicated, doesn't include a file with the long
line that you used, and describes several steps in incomplete and
vague manner.  So it isn't so easy to reproduce for me, not really.
I'd probably need several attempts until I succeed, and the fact that
I need to create a repository just for this doesn't help (diff-mode is
not just for VCS diffs, right?)

If you can add the missing details and the file, it might be easier.

> > If so, does the patch below help?
> 
> Unfortunately, no.  Still such a backtrace:
> 
> Error: args-out-of-range (#<buffer *vc-diff*> 2000 1906)
>   mapbacktrace(#f(compiled-function (evald func args flags) #<bytecode -0x12357049b0517812>))
>   debug-early-backtrace()
>   debug-early(error (args-out-of-range #<buffer *vc-diff*> 2000 1906))
>   buffer-substring-no-properties(2000 1906)
>   (let* ((hunk (buffer-substring-no-properties (max beg (point-min)) (min end (point-max)))) ...
>   diff-syntax-fontify-hunk(2000 250945 nil)
>   diff-syntax-fontify(2000 250945)
>   #<subr F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_39>(2000 250945)
>   diff--iterate-hunks(10000 #<subr F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_39>)
>   diff--font-lock-syntax(10000)

This probably means diff-mode relies on the buffer being widened.
Which is a bad idea for font-lock functions.

Anyway, how about the below?

diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index eb01ded..62db362 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -2762,7 +2762,10 @@ diff-syntax-fontify-hunk
   "Highlight source language syntax in diff hunk between BEG and END.
 When OLD is non-nil, highlight the hunk from the old source."
   (goto-char beg)
-  (let* ((hunk (buffer-substring-no-properties beg end))
+  (let* ((hunk (buffer-substring-no-properties (min (max beg (point-min))
+                                                    (point-max))
+                                               (max (min end (point-max))
+                                                    (point-min))))
          ;; Trim a trailing newline to find hunk in diff-syntax-fontify-props
          ;; in diffs that have no newline at end of diff file.
          (text (string-trim-right