GNU bug report logs - #37045
lisp-indent-region hangs in lisp-indent-calc-next when indenting the three characters "|#\n"

Previous Next

Package: emacs;

Reported by: eschulte <at> grammatech.com

Date: Fri, 16 Aug 2019 04:50:03 UTC

Severity: normal

Tags: fixed, patch

Found in version 26.1

Fixed in version 26.3

Done: Noam Postavsky <npostavs <at> gmail.com>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 37045 in the body.
You can then email your comments to 37045 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#37045; Package emacs. (Fri, 16 Aug 2019 04:50:03 GMT) Full text and rfc822 format available.

Acknowledgement sent to eschulte <at> grammatech.com:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Fri, 16 Aug 2019 04:50:03 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: eschulte <at> grammatech.com
To: bug-gnu-emacs <at> gnu.org
Subject: lisp-indent-region hangs in lisp-indent-calc-next when indenting the
 three characters "|#\n"
Date: Thu, 15 Aug 2019 23:46:06 -0400
[Message part 1 (text/plain, inline)]
Hi,

Indent-region sometimes hangs when indenting a lisp file.  A minimal
example is the file just containing the characters "|#" followed by a
newline.  This hang is due to an infinite loop in the while loop in the
`lisp-indent-calc-next' function.  The following version of this
function fixes this problem, but is certainly not the appropriate
long-term fix.

[lisp-indent-calc-next-workaround.lisp (text/x-lisp, inline)]
;;; Work around a bug in `lisp-indent-calc-next' in which it can hang
;;; on a dangling '|#'.  The change in the code below against the
;;; original is the addition of a block and a throw to this block when
;;; we're infinite looping (when the newly added last-last-sexp
;;; matches last-sexp).  On the off chance it is possible in normal
;;; execution for last-sexp to stay the same for some number of loop
;;; iterations this patch only aborts if they're equal 100 times in a
;;; row.
(defun lisp-indent-calc-next (state)
  "Move to next line and return calculated indent for it.
STATE is updated by side effect, the first state should be
created by `lisp-indent-initial-state'.  This function may move
by more than one line to cross a string literal."
  (pcase-let* (((cl-struct lisp-indent-state
                           (stack indent-stack) ppss ppss-point)
                state)
               (indent-depth (car ppss)) ; Corresponding to indent-stack.
               (depth indent-depth)
               (last-last-sexp nil) (counter 0))
    (block nil
      ;; Parse this line so we can learn the state to indent the
      ;; next line.
      (while (let ((last-sexp (nth 2 ppss)))
               (setq ppss (parse-partial-sexp
                           ppss-point (progn (end-of-line) (point))
                           nil nil ppss))
               ;; Preserve last sexp of state (position 2) for
               ;; `calculate-lisp-indent', if we're at the same depth.
               (if (and (not (nth 2 ppss)) (= depth (car ppss)))
                   (setf (nth 2 ppss) last-sexp)
                 (setq last-sexp (nth 2 ppss)))
               (setq depth (car ppss))
               (if (and (>= counter 100) (equal last-sexp last-last-sexp))
                   (progn (setf indent-stack nil) (return))
                 (setq last-last-sexp last-sexp
                       counter (1+ counter)))
               ;; Skip over newlines within strings.
               (nth 3 ppss))
        (let ((string-start (nth 8 ppss)))
          (setq ppss (parse-partial-sexp (point) (point-max)
                                         nil nil ppss 'syntax-table))
          (setf (nth 2 ppss) string-start) ; Finished a complete string.
          (setq depth (car ppss)))
        (setq ppss-point (point)))
      (setq ppss-point (point))
      (let* ((depth-delta (- depth indent-depth)))
        (cond ((< depth-delta 0)
               (setq indent-stack (nthcdr (- depth-delta) indent-stack)))
              ((> depth-delta 0)
               (setq indent-stack (nconc (make-list depth-delta nil)
                                         indent-stack))))))

    (prog1
        (let (indent)
          (cond ((= (forward-line 1) 1) nil)
                ;; Negative depth, probably some kind of syntax error.
                ((null indent-stack)
                 ;; Reset state.
                 (setq ppss (parse-partial-sexp (point) (point))))
                ((car indent-stack))
                ((integerp (setq indent (calculate-lisp-indent ppss)))
                 (setf (car indent-stack) indent))
                ((consp indent)       ; (COLUMN CONTAINING-SEXP-START)
                 (car indent))
                ;; This only happens if we're in a string.
                (t (error "This shouldn't happen"))))
      (setf (lisp-indent-state-stack state) indent-stack)
      (setf (lisp-indent-state-ppss-point state) ppss-point)
      (setf (lisp-indent-state-ppss state) ppss))))
[Message part 3 (text/plain, inline)]
Thanks,
Eric

P.S. I hope this isn't a duplicate report, I tried to search both the
archive https://lists.gnu.org/archive/html/bug-gnu-emacs/ and the
previous bug reports https://debbugs.gnu.org/ but I didn't find anything
relevant.


-- 
Eric Schulte, Ph.D.
Director of Automated Software Engineering
GrammaTech, Inc.
PGP Fingerprint: FA8D C2C3 E8A0 A749 34CD  9DCF 3C1B 8581 614C A05D
Pronouns: he, him, his
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#37045; Package emacs. (Fri, 16 Aug 2019 11:48:02 GMT) Full text and rfc822 format available.

Message #8 received at 37045 <at> debbugs.gnu.org (full text, mbox):

From: Noam Postavsky <npostavs <at> gmail.com>
To: eschulte <at> grammatech.com
Cc: 37045 <at> debbugs.gnu.org
Subject: Re: bug#37045: lisp-indent-region hangs in lisp-indent-calc-next when
 indenting the three characters "|#\n"
Date: Fri, 16 Aug 2019 07:47:20 -0400
[Message part 1 (text/plain, inline)]
found 37045 26.1
tags 37045 + patch
quit

eschulte <at> grammatech.com writes:

> Indent-region sometimes hangs when indenting a lisp file.  A minimal
> example is the file just containing the characters "|#" followed by a
> newline.

It's actually any unfinished string literal (in Common Lisp, |...| is
treated by Emacs as a string literal, though technically it's an escaped
symbol).

> This hang is due to an infinite loop in the while loop in the
> `lisp-indent-calc-next' function.  The following version of this
> function fixes this problem, but is certainly not the appropriate
> long-term fix.

I think the right fix is just to check for end of buffer:

@@ -810,7 +810,7 @@ lisp-indent-calc-next
                (setq last-sexp (nth 2 ppss)))
              (setq depth (car ppss))
              ;; Skip over newlines within strings.
-             (nth 3 ppss))
+             (and (not (eobp)) (nth 3 ppss)))
       (let ((string-start (nth 8 ppss)))
         (setq ppss (parse-partial-sexp (point) (point-max)
                                        nil nil ppss 'syntax-table))

Full patch with test (and some other comment updates) attached below.
Is this okay for emacs-26?  The bug is a regression from Emacs 25.

[0001-Fix-lisp-indent-infloop-on-unfinished-strings-Bug-37.patch (text/plain, attachment)]

bug Marked as found in versions 26.1. Request was from Noam Postavsky <npostavs <at> gmail.com> to control <at> debbugs.gnu.org. (Fri, 16 Aug 2019 11:48:02 GMT) Full text and rfc822 format available.

Added tag(s) patch. Request was from Noam Postavsky <npostavs <at> gmail.com> to control <at> debbugs.gnu.org. (Fri, 16 Aug 2019 11:48:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#37045; Package emacs. (Fri, 16 Aug 2019 12:56:02 GMT) Full text and rfc822 format available.

Message #15 received at 37045 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Noam Postavsky <npostavs <at> gmail.com>
Cc: 37045 <at> debbugs.gnu.org, eschulte <at> grammatech.com
Subject: Re: bug#37045: lisp-indent-region hangs in lisp-indent-calc-next when
 indenting the three characters "|#\n"
Date: Fri, 16 Aug 2019 15:54:59 +0300
> From: Noam Postavsky <npostavs <at> gmail.com>
> Date: Fri, 16 Aug 2019 07:47:20 -0400
> Cc: 37045 <at> debbugs.gnu.org
> 
> Is this okay for emacs-26?  The bug is a regression from Emacs 25.

Yes, thanks.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#37045; Package emacs. (Sat, 17 Aug 2019 13:53:01 GMT) Full text and rfc822 format available.

Message #18 received at 37045 <at> debbugs.gnu.org (full text, mbox):

From: Noam Postavsky <npostavs <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: eschulte <at> grammatech.com, 37045 <at> debbugs.gnu.org
Subject: Re: bug#37045: lisp-indent-region hangs in lisp-indent-calc-next when
 indenting the three characters "|#\n"
Date: Sat, 17 Aug 2019 09:51:55 -0400
tags 37045 fixed
close 37045 26.3
quit

Eli Zaretskii <eliz <at> gnu.org> writes:

>> From: Noam Postavsky <npostavs <at> gmail.com>
>> Date: Fri, 16 Aug 2019 07:47:20 -0400
>> Cc: 37045 <at> debbugs.gnu.org
>> 
>> Is this okay for emacs-26?  The bug is a regression from Emacs 25.
>
> Yes, thanks.

Pushed to emacs-26.

bcd0115e4d 2019-08-17T09:42:34-04:00 "Fix lisp indent infloop on unfinished strings (Bug#37045)"
https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=bcd0115e4db49791a77566b80fabc4384d9ebf57





Added tag(s) fixed. Request was from Noam Postavsky <npostavs <at> gmail.com> to control <at> debbugs.gnu.org. (Sat, 17 Aug 2019 13:53:03 GMT) Full text and rfc822 format available.

bug marked as fixed in version 26.3, send any further explanations to 37045 <at> debbugs.gnu.org and eschulte <at> grammatech.com Request was from Noam Postavsky <npostavs <at> gmail.com> to control <at> debbugs.gnu.org. (Sat, 17 Aug 2019 13:53:03 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sun, 15 Sep 2019 11:24:06 GMT) Full text and rfc822 format available.

This bug report was last modified 4 years and 196 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.