GNU bug report logs - #77233
31.0.50; crash if message starts with a space and then without it

Previous Next

Package: emacs;

Reported by: Daniel Clemente <n142857 <at> gmail.com>

Date: Mon, 24 Mar 2025 09:44:02 UTC

Severity: normal

Found in version 31.0.50

Fixed in version 31.1

Done: Gerd Möllmann <gerd.moellmann <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 77233 in the body.
You can then email your comments to 77233 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#77233; Package emacs. (Mon, 24 Mar 2025 09:44:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Daniel Clemente <n142857 <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Mon, 24 Mar 2025 09:44:02 GMT) Full text and rfc822 format available.

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

From: Daniel Clemente <n142857 <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 31.0.50; crash if message starts with a space and then without it
Date: Mon, 24 Mar 2025 09:42:52 +0000
Believe it or not, this crashes each time. Open emacs -Q (with or
without daemon) in a TTY, and evaluate the first part and then the progn:

(modify-frame-parameters (selected-frame) '(
      ;; background-color needs to be defined, to crash. The precise
color doesn't matter
      (background-color . "#111")
      ;; Doesn't affect the crash:
      ;; (foreground-color . "#c0c0c0")
     ))
(progn
  (message " AB")
  (message "AB")
)

Conditions for this crash:
- the same message must have appeared with an initial space and
without an initial space. Use " ABC" and "AB" and it won't crash,
because ABC != AB. But use " ABC" and "ABC" and it crashes
- it must be in this order: first with space, then without
- both messages must be contained in a progn or in a let/while/defun…
If you evaluate each message separately, it works
- the background-color needs to be set
- there must only be 1 space in the beginning. With 2 spaces or 1 tab
or 1 dot it works. Space in the end also works

This is with latest Emacs compiled right now. It seems due to recent
changes since I didn't see it in my previous version (~2 weeks old),
but I'm not sure and I didn't have time to do bisecting. Line numbers
in my
backtrace might be off by 1 since I added some lines with comments
(but it also crashes without my edits).

Discovered by running zone-pgm-stress, which triggers the condition.

Crash:

Breakpoint 1, terminate_due_to_signal (sig=6, backtrace_limit=40) at emacs.c:425
425      signal (sig, SIG_DFL);
(gdb) bt
#0  terminate_due_to_signal (sig=6, backtrace_limit=40) at emacs.c:425
#1  0x00005555556cb0b7 in emacs_abort () at sysdep.c:2378
#2  0x00005555556730a9 in cmcheckmagic (tty=0x555555a983a0) at cm.c:122
#3  0x0000555555677abd in tty_write_glyphs_1 (f=0x555555aa46e0,
string=0x7ffff6ea3670, len=1)
    at term.c:816
#4  0x0000555555678430 in tty_write_glyphs (f=0x555555aa46e0,
string=0x7ffff6ea3638, len=1)
    at term.c:992
#5  0x000055555568358b in write_glyphs (f=0x555555aa46e0,
string=0x7ffff6ea3638, len=1)
    at terminal.c:182
#6  0x0000555555593388 in write_row (f=0x555555aa46e0, vpos=60,
updating_menu_p=false)
    at dispnew.c:6159
#7  0x00005555555912d1 in write_matrix (f=0x555555aa46e0,
inhibit_id_p=true, updating_menu_p=false)
    at dispnew.c:5746
#8  0x000055555558d69b in combine_updates_for_frame (f=0x555555aa46e0,
inhibit_scrolling=true)
    at dispnew.c:4053
#9  0x00005555555cebfc in echo_area_display (update_frame_p=true) at
xdisp.c:13562
#10 0x00005555555ca99e in message3_nolog (m=XIL(0x555555da1a04)) at
xdisp.c:12460
#11 0x00005555555ca64c in message3 (m=XIL(0x555555da1a04)) at xdisp.c:12390
#12 0x000055555576f5c1 in Fmessage (nargs=1, args=0x7fffffffbb00) at
editfns.c:3127
[…]
(gdb) frame 2
#2  0x00005555556730a9 in cmcheckmagic (tty=0x555555a983a0) at cm.c:122
122        emacs_abort ();
(gdb) list
117      if (frame_size_change_delayed (XFRAME (tty->top_frame)))
118        return;
119      if (curX (tty) == FrameCols (tty))
120        {
121          if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
122        emacs_abort ();
123          if (tty->termscript)
124        putc ('\r', tty->termscript);
125          putc ('\r', tty->output);
126          if (tty->termscript)
(gdb) p curY(tty)
$1 = 60
(gdb) p FrameRows(tty)-1
$2 = 60
(gdb) p FrameCols(tty)
$3 = 100
(gdb)




In GNU Emacs 31.0.50 (build 28, x86_64-pc-linux-gnu) of 2025-03-24 built
 on sonn
Repository revision: 0cfe700e336da3cc5a2a766840d375921dcd5ee9
Repository branch: master
System Description: Devuan GNU/Linux 5 (daedalus)

Configured using:
 'configure --prefix=/opt/dc/emacs-dev/ --with-tiff=no --without-tiff
 --without-libsystemd --without-dbus --with-mailutils --without-modules
 --with-native-compilation=no --with-x-toolkit=no --without-imagemagick
 --without-xft --without-harfbuzz --without-freetype --without-libotf
 --without-xwidgets --without-xpm --without-jpeg --without-gif
 --without-png --without-webp --without-rsvg --without-cairo --without-x
 --without-sound --enable-checking=yes,glyphs --enable-profiling CC=gcc
 'CFLAGS=-g3 -O0 ''

Configured features:
GMP GNUTLS LCMS2 LIBSELINUX LIBXML2 NOTIFY INOTIFY PDUMPER SECCOMP
SQLITE3 THREADS XIM ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=SCIM
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  server-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  minibuffer-regexp-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
/w/emacs-dev/lisp/pulse hides /w/emacs-dev/lisp/cedet/pulse

Features:
(shadow sort hashcash pcase cl-macs regexp-opt mail-extr emacsbug
message mailcap yank-media puny dired dnd dired-loaddefs rfc822 mml
mml-sec password-cache epa derived epg rfc6068 epg-config gnus-util
text-property-search time-date subr-x mm-decode mm-bodies mm-encode
mail-parse rfc2231 mailabbrev gmm-utils mailheader cl-loaddefs cl-lib
sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils
term/rxvt term/xterm xterm byte-opt gv bytecomp byte-compile server rmc
iso-transl tooltip cconv eldoc paren electric uniquify ediff-hook
vc-hooks lisp-float-type elisp-mode tabulated-list replace newcomment
text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow
isearch easymenu timer select mouse jit-lock font-lock syntax font-core
term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs
theme-loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads inotify lcms2 multi-tty
make-network-process tty-child-frames emacs)

Memory information:
((conses 16 52990 10439) (symbols 48 6510 1) (strings 32 16235 1652)
 (string-bytes 1 429445) (vectors 16 8416) (vector-slots 8 76621 5913)
 (floats 8 33 11518) (intervals 56 248 14) (buffers 984 12))




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 12:57:01 GMT) Full text and rfc822 format available.

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

From: Eli Zaretskii <eliz <at> gnu.org>
To: Daniel Clemente <n142857 <at> gmail.com>
Cc: 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50;
 crash if message starts with a space and then without it
Date: Mon, 24 Mar 2025 14:56:22 +0200
> From: Daniel Clemente <n142857 <at> gmail.com>
> Date: Mon, 24 Mar 2025 09:42:52 +0000
> 
> Believe it or not, this crashes each time. Open emacs -Q (with or
> without daemon) in a TTY, and evaluate the first part and then the progn:
> 
> (modify-frame-parameters (selected-frame) '(
>       ;; background-color needs to be defined, to crash. The precise
> color doesn't matter
>       (background-color . "#111")
>       ;; Doesn't affect the crash:
>       ;; (foreground-color . "#c0c0c0")
>      ))
> (progn
>   (message " AB")
>   (message "AB")
> )

Thanks.

I cannot reproduce the crash.  My build is a bit different (for
example, not --without-x), but otherwise I have no clue.

> #2  0x00005555556730a9 in cmcheckmagic (tty=0x555555a983a0) at cm.c:122
> 122        emacs_abort ();
> (gdb) list
> 117      if (frame_size_change_delayed (XFRAME (tty->top_frame)))
> 118        return;
> 119      if (curX (tty) == FrameCols (tty))
> 120        {
> 121          if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
> 122        emacs_abort ();
> 123          if (tty->termscript)
> 124        putc ('\r', tty->termscript);
> 125          putc ('\r', tty->output);
> 126          if (tty->termscript)
> (gdb) p curY(tty)
> $1 = 60
> (gdb) p FrameRows(tty)-1
> $2 = 60
> (gdb) p FrameCols(tty)
> $3 = 100
> (gdb)

What is the value of curX(tty) ?  And if (as I'd expect) it is 100,
then do you have any idea how come it became 100 for a 2-character
message?

Can anyone else reproduce this?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 14:13:02 GMT) Full text and rfc822 format available.

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

From: Eli Zaretskii <eliz <at> gnu.org>
To: n142857 <at> gmail.com
Cc: 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50;
 crash if message starts with a space and then without it
Date: Mon, 24 Mar 2025 16:12:07 +0200
> Cc: 77233 <at> debbugs.gnu.org
> Date: Mon, 24 Mar 2025 14:56:22 +0200
> From: Eli Zaretskii <eliz <at> gnu.org>
> 
> What is the value of curX(tty) ?  And if (as I'd expect) it is 100,
> then do you have any idea how come it became 100 for a 2-character
> message?
> 
> Can anyone else reproduce this?

Does the crash depend on the terminal emulator you use?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 14:15:02 GMT) Full text and rfc822 format available.

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

From: Pip Cet <pipcet <at> protonmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: Daniel Clemente <n142857 <at> gmail.com>, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50;
 crash if message starts with a space and then without it
Date: Mon, 24 Mar 2025 14:14:11 +0000
"Eli Zaretskii" <eliz <at> gnu.org> writes:

>> #2  0x00005555556730a9 in cmcheckmagic (tty=0x555555a983a0) at cm.c:122
>> 122        emacs_abort ();
>> (gdb) list
>> 117      if (frame_size_change_delayed (XFRAME (tty->top_frame)))
>> 118        return;
>> 119      if (curX (tty) == FrameCols (tty))
>> 120        {
>> 121          if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
>> 122        emacs_abort ();
>> 123          if (tty->termscript)
>> 124        putc ('\r', tty->termscript);
>> 125          putc ('\r', tty->output);
>> 126          if (tty->termscript)
>> (gdb) p curY(tty)
>> $1 = 60
>> (gdb) p FrameRows(tty)-1
>> $2 = 60
>> (gdb) p FrameCols(tty)
>> $3 = 100
>> (gdb)
>
> What is the value of curX(tty) ?  And if (as I'd expect) it is 100,
> then do you have any idea how come it became 100 for a 2-character
> message?

It is equal to FrameCols (tty), as established in line 119 (this
requires a breakpoint in emacs_abort rather than terminate_due_to_signal).

> Can anyone else reproduce this?

I can, on GNU/Linux with no special options and in an xterm.  Reverting
6fb68f4310d808827b83da053fbc112b316b7757 avoids the crash.

Pip





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 18:21:01 GMT) Full text and rfc822 format available.

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

From: Eli Zaretskii <eliz <at> gnu.org>
To: Pip Cet <pipcet <at> protonmail.com>,
 Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: n142857 <at> gmail.com, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50;
 crash if message starts with a space and then without it
Date: Mon, 24 Mar 2025 20:20:34 +0200
> Date: Mon, 24 Mar 2025 14:14:11 +0000
> From: Pip Cet <pipcet <at> protonmail.com>
> Cc: Daniel Clemente <n142857 <at> gmail.com>, 77233 <at> debbugs.gnu.org
> 
> "Eli Zaretskii" <eliz <at> gnu.org> writes:
> 
> >> #2  0x00005555556730a9 in cmcheckmagic (tty=0x555555a983a0) at cm.c:122
> >> 122        emacs_abort ();
> >> (gdb) list
> >> 117      if (frame_size_change_delayed (XFRAME (tty->top_frame)))
> >> 118        return;
> >> 119      if (curX (tty) == FrameCols (tty))
> >> 120        {
> >> 121          if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
> >> 122        emacs_abort ();
> >> 123          if (tty->termscript)
> >> 124        putc ('\r', tty->termscript);
> >> 125          putc ('\r', tty->output);
> >> 126          if (tty->termscript)
> >> (gdb) p curY(tty)
> >> $1 = 60
> >> (gdb) p FrameRows(tty)-1
> >> $2 = 60
> >> (gdb) p FrameCols(tty)
> >> $3 = 100
> >> (gdb)
> >
> > What is the value of curX(tty) ?  And if (as I'd expect) it is 100,
> > then do you have any idea how come it became 100 for a 2-character
> > message?
> 
> It is equal to FrameCols (tty), as established in line 119 (this
> requires a breakpoint in emacs_abort rather than terminate_due_to_signal).
> 
> > Can anyone else reproduce this?
> 
> I can, on GNU/Linux with no special options and in an xterm.

And you can explain how come curX(tty) got such a large value?

> Reverting 6fb68f4310d808827b83da053fbc112b316b7757 avoids the crash.

Adding Gerd.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 19:13:02 GMT) Full text and rfc822 format available.

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

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: n142857 <at> gmail.com, Pip Cet <pipcet <at> protonmail.com>, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50; crash if message starts with a space and
 then without it
Date: Mon, 24 Mar 2025 20:12:37 +0100
Eli Zaretskii <eliz <at> gnu.org> writes:

>> > Can anyone else reproduce this?
>> 
>> I can, on GNU/Linux with no special options and in an xterm.
>
> And you can explain how come curX(tty) got such a large value?
>
>> Reverting 6fb68f4310d808827b83da053fbc112b316b7757 avoids the crash.
>
> Adding Gerd.

I think I can reproduce this, but I can't take a closer look
for a couple of days or so.

If it's urgent, maybe try to comment out the emacs_abort in cmcheckmagic
and see if that suffices.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 19:15:02 GMT) Full text and rfc822 format available.

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

From: Pip Cet <pipcet <at> protonmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>,
 n142857 <at> gmail.com, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50;
 crash if message starts with a space and then without it
Date: Mon, 24 Mar 2025 19:13:55 +0000
"Eli Zaretskii" <eliz <at> gnu.org> writes:

>> Date: Mon, 24 Mar 2025 14:14:11 +0000
>> From: Pip Cet <pipcet <at> protonmail.com>
>> Cc: Daniel Clemente <n142857 <at> gmail.com>, 77233 <at> debbugs.gnu.org
>>
>> "Eli Zaretskii" <eliz <at> gnu.org> writes:
>>
>> >> #2  0x00005555556730a9 in cmcheckmagic (tty=0x555555a983a0) at cm.c:122
>> >> 122        emacs_abort ();
>> >> (gdb) list
>> >> 117      if (frame_size_change_delayed (XFRAME (tty->top_frame)))
>> >> 118        return;
>> >> 119      if (curX (tty) == FrameCols (tty))
>> >> 120        {
>> >> 121          if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
>> >> 122        emacs_abort ();
>> >> 123          if (tty->termscript)
>> >> 124        putc ('\r', tty->termscript);
>> >> 125          putc ('\r', tty->output);
>> >> 126          if (tty->termscript)
>> >> (gdb) p curY(tty)
>> >> $1 = 60
>> >> (gdb) p FrameRows(tty)-1
>> >> $2 = 60
>> >> (gdb) p FrameCols(tty)
>> >> $3 = 100
>> >> (gdb)
>> >
>> > What is the value of curX(tty) ?  And if (as I'd expect) it is 100,
>> > then do you have any idea how come it became 100 for a 2-character
>> > message?
>>
>> It is equal to FrameCols (tty), as established in line 119 (this
>> requires a breakpoint in emacs_abort rather than terminate_due_to_signal).
>>
>> > Can anyone else reproduce this?
>>
>> I can, on GNU/Linux with no special options and in an xterm.
>
> And you can explain how come curX(tty) got such a large value?

We tried to print a character at (cols-1,rows-1), which left the
remembered cursor position at (cols,rows-1).  According to the comments
in term.c, "some terminals" would have scrolled the entire terminal when
we wrote that character, which is the situation detected by
cmcheckmagic.

The code Gerd pushed looks like this:

static void
tty_write_glyphs (struct frame *f, struct glyph *string, int len)
{
  struct tty_display_info *tty = FRAME_TTY (f);
  /* Don't dare write in last column of bottom line, if Auto-Wrap,
     since that would scroll the whole frame on some terminals.  */
  if (AutoWrap (tty)
      && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
      && curX (tty) + len == FRAME_COLS (f)
      && curX (tty) < FRAME_COLS (f) - 1
      && len > 0)
    {
      /* Write glyphs except the first. */
      int old_x = curX (tty), old_y = curY (tty);
      tty_write_glyphs_1 (f, string + 1, len - 1);

      /* Insert the first glyph, shifting the rest right.  */
      cmgoto (tty, old_y, old_x);
      tty_insert_glyphs (f, string, 1);
    }
  else
    tty_write_glyphs_1 (f, string, len);
}

in our case (len == 1), we end up in the "else" branch because curX ==
cols - 1, attempting to print a single character in the bottom-right
corner of the terminal.

The "else" branch simply prints the character and leaves the cursor
position "invalid".

Note that xterm (the application) doesn't appear to scroll the terminal
in this case, so it's a bit of a historical exercise to fix things on
those terminals that would have, but IIUC, the right way is to retrieve
the character at (cols-2,rows-1), goto (cols-2,rows-1), print the
character that's supposed to end up at (cols-1,rows-1), goto
(cols-2,rows-1) again, then print the retrieved character.

This is complicated because we'd need to retrieve the character at
(cols-2, rows-1) from the frame matrix if tty_write_glyphs is called
with len == 1 and the cursor is at (cols-1,rows-1).

Anyway, here's a patch that does this, but it seems too complicated to
be worth it to me:

diff --git a/src/term.c b/src/term.c
index e15b7a0887e..ccee6c650e3 100644
--- a/src/term.c
+++ b/src/term.c
@@ -971,16 +971,36 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
   if (AutoWrap (tty)
       && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
       && curX (tty) + len == FRAME_COLS (f)
-      && curX (tty) < FRAME_COLS (f) - 1
       && len > 0)
     {
-      /* Write glyphs except the first. */
-      int old_x = curX (tty), old_y = curY (tty);
-      tty_write_glyphs_1 (f, string + 1, len - 1);
+      if (len > 1)
+	{
+	  /* Write glyphs except the first. */
+	  int old_x = curX (tty), old_y = curY (tty);
+	  tty_write_glyphs_1 (f, string + 1, len - 1);
 
-      /* Insert the first glyph, shifting the rest right.  */
-      cmgoto (tty, old_y, old_x);
-      tty_insert_glyphs (f, string, 1);
+	  /* Insert the first glyph, shifting the rest right.  */
+	  cmgoto (tty, old_y, old_x);
+	  tty_insert_glyphs (f, string, 1);
+	}
+      else
+	{
+	  struct glyph glyphs[2];
+	  glyphs[1] = string[0];
+	  if (!f->current_matrix || f->current_matrix->matrix_h < curY (tty))
+	    return;
+	  struct glyph_row *row = &f->current_matrix->rows[curY (tty)];
+	  int area = 0;
+	  int x = curX (tty) - 1;
+	  while (x > row->used[area])
+	    {
+	      x -= row->used[area];
+	      if (area++ == LAST_AREA)
+		return;
+	    }
+	  glyphs[0] = row->glyphs[area][x];
+	  tty_write_glyphs (f, glyphs, 2);
+	}
     }
   else
     tty_write_glyphs_1 (f, string, len);





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 19:24:01 GMT) Full text and rfc822 format available.

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

From: Eli Zaretskii <eliz <at> gnu.org>
To: Pip Cet <pipcet <at> protonmail.com>
Cc: gerd.moellmann <at> gmail.com, n142857 <at> gmail.com, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50;
 crash if message starts with a space and then without it
Date: Mon, 24 Mar 2025 21:23:06 +0200
> Date: Mon, 24 Mar 2025 19:13:55 +0000
> From: Pip Cet <pipcet <at> protonmail.com>
> Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>, n142857 <at> gmail.com, 77233 <at> debbugs.gnu.org
> 
> "Eli Zaretskii" <eliz <at> gnu.org> writes:
> 
> > And you can explain how come curX(tty) got such a large value?
> 
> We tried to print a character at (cols-1,rows-1)

Why did we do that, when the messages were 2 and 3 characters long?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 19:25:02 GMT) Full text and rfc822 format available.

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

From: Pip Cet <pipcet <at> protonmail.com>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: n142857 <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50;
 crash if message starts with a space and then without it
Date: Mon, 24 Mar 2025 19:24:08 +0000
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:

> Eli Zaretskii <eliz <at> gnu.org> writes:
>
>>> > Can anyone else reproduce this?
>>>
>>> I can, on GNU/Linux with no special options and in an xterm.
>>
>> And you can explain how come curX(tty) got such a large value?
>>
>>> Reverting 6fb68f4310d808827b83da053fbc112b316b7757 avoids the crash.
>>
>> Adding Gerd.
>
> I think I can reproduce this, but I can't take a closer look
> for a couple of days or so.
>
> If it's urgent, maybe try to comment out the emacs_abort in cmcheckmagic
> and see if that suffices.

That avoids the crash here, and things work fine in an xterm, but it
means we printed a character with the cursor at (cols-1,rows-1), which
allegedly would have caused some (old, I assume?) terminals to scroll by
a line, destroying the entire Emacs layout...

However, xterm and M-x term both handle this situation sensibly, not
scrolling the frame.  Is anyone aware of a terminal emulator that
scrolls in this situation?

Pip





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 19:33:02 GMT) Full text and rfc822 format available.

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

From: Eli Zaretskii <eliz <at> gnu.org>
To: Pip Cet <pipcet <at> protonmail.com>
Cc: gerd.moellmann <at> gmail.com, n142857 <at> gmail.com, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50;
 crash if message starts with a space and then without it
Date: Mon, 24 Mar 2025 21:32:29 +0200
> Date: Mon, 24 Mar 2025 19:13:55 +0000
> From: Pip Cet <pipcet <at> protonmail.com>
> Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>, n142857 <at> gmail.com, 77233 <at> debbugs.gnu.org
> 
> Anyway, here's a patch that does this, but it seems too complicated to
> be worth it to me:

A few minor/cosmetic comments about the patch:

> +	  if (!f->current_matrix || f->current_matrix->matrix_h < curY (tty))

How can a frame not have a current_matrix?  That could only mean one
thing: the frame was not completely made, in which case its
after_make_frame flag should be reset.  Such frames should never be
considered by this function, i.e. they should be detected at entry and
the function should then return without doing anything.

> +	  struct glyph_row *row = &f->current_matrix->rows[curY (tty)];
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Please use the MATRIX_ROW macro here.

> +	  int area = 0;
> +	  int x = curX (tty) - 1;
> +	  while (x > row->used[area])
> +	    {
> +	      x -= row->used[area];
> +	      if (area++ == LAST_AREA)
> +		return;
> +	    }
> +	  glyphs[0] = row->glyphs[area][x];
> +	  tty_write_glyphs (f, glyphs, 2);
> +	}

I think this is unnecessarily complicated, since frame glyph matrices
never have marginal areas, they only have the single TEXT_AREA.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 19:42:04 GMT) Full text and rfc822 format available.

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

From: Pip Cet <pipcet <at> protonmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: gerd.moellmann <at> gmail.com, n142857 <at> gmail.com, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50;
 crash if message starts with a space and then without it
Date: Mon, 24 Mar 2025 19:40:58 +0000
"Eli Zaretskii" <eliz <at> gnu.org> writes:

>> Date: Mon, 24 Mar 2025 19:13:55 +0000
>> From: Pip Cet <pipcet <at> protonmail.com>
>> Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>, n142857 <at> gmail.com, 77233 <at> debbugs.gnu.org
>>
>> "Eli Zaretskii" <eliz <at> gnu.org> writes:
>>
>> > And you can explain how come curX(tty) got such a large value?
>>
>> We tried to print a character at (cols-1,rows-1)
>
> Why did we do that, when the messages were 2 and 3 characters long?

write_row decided to delete (using delete_glyphs) the initial space in
the final terminal line, which means the bottom-right corner no longer
has the right background color, so it needs to be redrawn (this is in a
158x44 "terminal"):

(gdb) b dispnew.c:6109 if nsp != osp
6109	  if (osp > nsp)
(gdb) bt full 1

#0  write_row (f=0x555555af45d0, vpos=44, updating_menu_p=false) at dispnew.c:6109
        obody = 0x7ffff49740d0
        nbody = 0x7ffff49120d0
        op1 = 0x7ffff4976360
        op2 = 0x7ffff4976360
        np1 = 0x7ffff4914360
        nend = 0x7ffff4914360
        tem = 1
        osp = 1
        nsp = 0
        begmatch = 157
        endmatch = 0
        olen = 158
        nlen = 158
        current_matrix = 0x555555af5b40
        desired_matrix = 0x555555af5ad0
        current_row = 0x555555b00ca0
        desired_row = 0x555555afdf90
        must_write_whole_line_p = false
        write_spaces_p = true
        colored_spaces_p = true
(More stack frames follow...)
[...]

6112	      delete_glyphs (f, osp - nsp);
(gdb) p osp - nsp
$2 = 1
[...]
6147		      cursor_to (f, vpos, nsp + begmatch);

(gdb) p nsp + begmatch

$3 = 157
(gdb) p vpos

$4 = 44
[...]
6148		      write_glyphs (f, nbody + nsp + begmatch, nlen - tem);

(gdb) p nsp + begmatch

$5 = 157
(gdb) p nlen - tem

$6 = 1

Then the abort.

(I agree with your comments about the patch, of course!  Thanks for
those.  I do think that this is an extremely rare situation and wanted
to make sure not to segfault even if the other display code is
changed...)

Pip





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 20:01:03 GMT) Full text and rfc822 format available.

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

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Pip Cet <pipcet <at> protonmail.com>
Cc: n142857 <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50; crash if message starts with a space and
 then without it
Date: Mon, 24 Mar 2025 21:00:22 +0100
Pip Cet <pipcet <at> protonmail.com> writes:

> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> Eli Zaretskii <eliz <at> gnu.org> writes:
>>
>>>> > Can anyone else reproduce this?
>>>>
>>>> I can, on GNU/Linux with no special options and in an xterm.
>>>
>>> And you can explain how come curX(tty) got such a large value?
>>>
>>>> Reverting 6fb68f4310d808827b83da053fbc112b316b7757 avoids the crash.
>>>
>>> Adding Gerd.
>>
>> I think I can reproduce this, but I can't take a closer look
>> for a couple of days or so.
>>
>> If it's urgent, maybe try to comment out the emacs_abort in cmcheckmagic
>> and see if that suffices.
>
> That avoids the crash here, and things work fine in an xterm, but it
> means we printed a character with the cursor at (cols-1,rows-1), which
> allegedly would have caused some (old, I assume?) terminals to scroll by
> a line, destroying the entire Emacs layout...

Well, it's complicated as usual.

xterm implements AutoWrap. AutoWrap means that when outputting a
character the cursor automatically moves forwawrd. In the last column of
a row, the cursor automatically moves to column 0 of the next line.
Doing this in the last line of a display scrolls the display.

And then there is insert and overwrite mode. AFAIU what you wrote in
another mail len == 1 which means we wrote nothing in overwrite mode,
and then 1 glyph in insert mode. tty_insert_glyphs probably (I don't
know), just turns on insert mode, calls tty_write_glyphs, and switches
insert mode off again. The cursor doesn't move. The terminal shifts
glyphs right that came after the cursor.

So the questing is what does inserting a glyph in the last column of the
last row do in various terminals. Does this scroll in some case even
when there are no glyphs to shift right?

> However, xterm and M-x term both handle this situation sensibly, not
> scrolling the frame.  Is anyone aware of a terminal emulator that
> scrolls in this situation?

I simply don't know. I can't remember having seen that defined anywhere.
But don't forget, this is insert mode, I'm pretty sure it scrolls if not
in insert mode.






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Mon, 24 Mar 2025 20:13:01 GMT) Full text and rfc822 format available.

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

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Pip Cet <pipcet <at> protonmail.com>
Cc: n142857 <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50; crash if message starts with a space and
 then without it
Date: Mon, 24 Mar 2025 21:12:19 +0100
Pip Cet <pipcet <at> protonmail.com> writes:

> "Eli Zaretskii" <eliz <at> gnu.org> writes:
>
>>> Date: Mon, 24 Mar 2025 14:14:11 +0000
>>> From: Pip Cet <pipcet <at> protonmail.com>
>>> Cc: Daniel Clemente <n142857 <at> gmail.com>, 77233 <at> debbugs.gnu.org
>>>
>>> "Eli Zaretskii" <eliz <at> gnu.org> writes:
>>>
>>> >> #2  0x00005555556730a9 in cmcheckmagic (tty=0x555555a983a0) at cm.c:122
>>> >> 122        emacs_abort ();
>>> >> (gdb) list
>>> >> 117      if (frame_size_change_delayed (XFRAME (tty->top_frame)))
>>> >> 118        return;
>>> >> 119      if (curX (tty) == FrameCols (tty))
>>> >> 120        {
>>> >> 121          if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
>>> >> 122        emacs_abort ();
>>> >> 123          if (tty->termscript)
>>> >> 124        putc ('\r', tty->termscript);
>>> >> 125          putc ('\r', tty->output);
>>> >> 126          if (tty->termscript)
>>> >> (gdb) p curY(tty)
>>> >> $1 = 60
>>> >> (gdb) p FrameRows(tty)-1
>>> >> $2 = 60
>>> >> (gdb) p FrameCols(tty)
>>> >> $3 = 100
>>> >> (gdb)
>>> >
>>> > What is the value of curX(tty) ?  And if (as I'd expect) it is 100,
>>> > then do you have any idea how come it became 100 for a 2-character
>>> > message?
>>>
>>> It is equal to FrameCols (tty), as established in line 119 (this
>>> requires a breakpoint in emacs_abort rather than terminate_due_to_signal).
>>>
>>> > Can anyone else reproduce this?
>>>
>>> I can, on GNU/Linux with no special options and in an xterm.
>>
>> And you can explain how come curX(tty) got such a large value?
>
> We tried to print a character at (cols-1,rows-1), which left the
> remembered cursor position at (cols,rows-1).  According to the comments
> in term.c, "some terminals" would have scrolled the entire terminal when
> we wrote that character, which is the situation detected by
> cmcheckmagic.
>
> The code Gerd pushed looks like this:
>
> static void
> tty_write_glyphs (struct frame *f, struct glyph *string, int len)
> {
>   struct tty_display_info *tty = FRAME_TTY (f);
>   /* Don't dare write in last column of bottom line, if Auto-Wrap,
>      since that would scroll the whole frame on some terminals.  */
>   if (AutoWrap (tty)
>       && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
>       && curX (tty) + len == FRAME_COLS (f)
>       && curX (tty) < FRAME_COLS (f) - 1
>       && len > 0)
>     {
>       /* Write glyphs except the first. */
>       int old_x = curX (tty), old_y = curY (tty);
>       tty_write_glyphs_1 (f, string + 1, len - 1);
>
>       /* Insert the first glyph, shifting the rest right.  */
>       cmgoto (tty, old_y, old_x);
>       tty_insert_glyphs (f, string, 1);
>     }
>   else
>     tty_write_glyphs_1 (f, string, len);
> }
>
> in our case (len == 1), we end up in the "else" branch because curX ==
> cols - 1, attempting to print a single character in the bottom-right
> corner of the terminal.
>
> The "else" branch simply prints the character and leaves the cursor
> position "invalid".
>
> Note that xterm (the application) doesn't appear to scroll the terminal
> in this case, so it's a bit of a historical exercise to fix things on
> those terminals that would have, but IIUC, the right way is to retrieve
> the character at (cols-2,rows-1), goto (cols-2,rows-1), print the
> character that's supposed to end up at (cols-1,rows-1), goto
> (cols-2,rows-1) again, then print the retrieved character.
>
> This is complicated because we'd need to retrieve the character at
> (cols-2, rows-1) from the frame matrix if tty_write_glyphs is called
> with len == 1 and the cursor is at (cols-1,rows-1).
>
> Anyway, here's a patch that does this, but it seems too complicated to
> be worth it to me:
>
> diff --git a/src/term.c b/src/term.c
> index e15b7a0887e..ccee6c650e3 100644
> --- a/src/term.c
> +++ b/src/term.c
> @@ -971,16 +971,36 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
>    if (AutoWrap (tty)
>        && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
>        && curX (tty) + len == FRAME_COLS (f)
> -      && curX (tty) < FRAME_COLS (f) - 1

Ah, I see. It got into the else branch for len = 1. I think I
misinterpreted what is happening. It didn't even try to insert. Sorry
for that.

>        && len > 0)
>      {
> -      /* Write glyphs except the first. */
> -      int old_x = curX (tty), old_y = curY (tty);
> -      tty_write_glyphs_1 (f, string + 1, len - 1);
> +      if (len > 1)
> +	{
> +	  /* Write glyphs except the first. */
> +	  int old_x = curX (tty), old_y = curY (tty);
> +	  tty_write_glyphs_1 (f, string + 1, len - 1);
>  
> -      /* Insert the first glyph, shifting the rest right.  */
> -      cmgoto (tty, old_y, old_x);
> -      tty_insert_glyphs (f, string, 1);
> +	  /* Insert the first glyph, shifting the rest right.  */
> +	  cmgoto (tty, old_y, old_x);
> +	  tty_insert_glyphs (f, string, 1);
> +	}
> +      else
> +	{
> +	  struct glyph glyphs[2];
> +	  glyphs[1] = string[0];
> +	  if (!f->current_matrix || f->current_matrix->matrix_h < curY (tty))
> +	    return;
> +	  struct glyph_row *row = &f->current_matrix->rows[curY (tty)];
> +	  int area = 0;
> +	  int x = curX (tty) - 1;
> +	  while (x > row->used[area])
> +	    {
> +	      x -= row->used[area];
> +	      if (area++ == LAST_AREA)
> +		return;
> +	    }
> +	  glyphs[0] = row->glyphs[area][x];
> +	  tty_write_glyphs (f, glyphs, 2);
> +	}

Something like that, yes.

>      }
>    else
>      tty_write_glyphs_1 (f, string, len);




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Tue, 25 Mar 2025 04:49:01 GMT) Full text and rfc822 format available.

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

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Pip Cet <pipcet <at> protonmail.com>
Cc: n142857 <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50; crash if message starts with a space and
 then without it
Date: Tue, 25 Mar 2025 05:48:23 +0100
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:

> Pip Cet <pipcet <at> protonmail.com> writes:
>
>> "Eli Zaretskii" <eliz <at> gnu.org> writes:
>>
>>>> Date: Mon, 24 Mar 2025 14:14:11 +0000
>>>> From: Pip Cet <pipcet <at> protonmail.com>
>>>> Cc: Daniel Clemente <n142857 <at> gmail.com>, 77233 <at> debbugs.gnu.org
>>>>
>>>> "Eli Zaretskii" <eliz <at> gnu.org> writes:
>>>>
>>>> >> #2  0x00005555556730a9 in cmcheckmagic (tty=0x555555a983a0) at cm.c:122
>>>> >> 122        emacs_abort ();
>>>> >> (gdb) list
>>>> >> 117      if (frame_size_change_delayed (XFRAME (tty->top_frame)))
>>>> >> 118        return;
>>>> >> 119      if (curX (tty) == FrameCols (tty))
>>>> >> 120        {
>>>> >> 121          if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
>>>> >> 122        emacs_abort ();
>>>> >> 123          if (tty->termscript)
>>>> >> 124        putc ('\r', tty->termscript);
>>>> >> 125          putc ('\r', tty->output);
>>>> >> 126          if (tty->termscript)
>>>> >> (gdb) p curY(tty)
>>>> >> $1 = 60
>>>> >> (gdb) p FrameRows(tty)-1
>>>> >> $2 = 60
>>>> >> (gdb) p FrameCols(tty)
>>>> >> $3 = 100
>>>> >> (gdb)
>>>> >
>>>> > What is the value of curX(tty) ?  And if (as I'd expect) it is 100,
>>>> > then do you have any idea how come it became 100 for a 2-character
>>>> > message?
>>>>
>>>> It is equal to FrameCols (tty), as established in line 119 (this
>>>> requires a breakpoint in emacs_abort rather than terminate_due_to_signal).
>>>>
>>>> > Can anyone else reproduce this?
>>>>
>>>> I can, on GNU/Linux with no special options and in an xterm.
>>>
>>> And you can explain how come curX(tty) got such a large value?
>>
>> We tried to print a character at (cols-1,rows-1), which left the
>> remembered cursor position at (cols,rows-1).  According to the comments
>> in term.c, "some terminals" would have scrolled the entire terminal when
>> we wrote that character, which is the situation detected by
>> cmcheckmagic.
>>
>> The code Gerd pushed looks like this:
>>
>> static void
>> tty_write_glyphs (struct frame *f, struct glyph *string, int len)
>> {
>>   struct tty_display_info *tty = FRAME_TTY (f);
>>   /* Don't dare write in last column of bottom line, if Auto-Wrap,
>>      since that would scroll the whole frame on some terminals.  */
>>   if (AutoWrap (tty)
>>       && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
>>       && curX (tty) + len == FRAME_COLS (f)
>>       && curX (tty) < FRAME_COLS (f) - 1
>>       && len > 0)
>>     {
>>       /* Write glyphs except the first. */
>>       int old_x = curX (tty), old_y = curY (tty);
>>       tty_write_glyphs_1 (f, string + 1, len - 1);
>>
>>       /* Insert the first glyph, shifting the rest right.  */
>>       cmgoto (tty, old_y, old_x);
>>       tty_insert_glyphs (f, string, 1);
>>     }
>>   else
>>     tty_write_glyphs_1 (f, string, len);
>> }
>>
>> in our case (len == 1), we end up in the "else" branch because curX ==
>> cols - 1, attempting to print a single character in the bottom-right
>> corner of the terminal.
>>
>> The "else" branch simply prints the character and leaves the cursor
>> position "invalid".
>>
>> Note that xterm (the application) doesn't appear to scroll the terminal
>> in this case, so it's a bit of a historical exercise to fix things on
>> those terminals that would have, but IIUC, the right way is to retrieve
>> the character at (cols-2,rows-1), goto (cols-2,rows-1), print the
>> character that's supposed to end up at (cols-1,rows-1), goto
>> (cols-2,rows-1) again, then print the retrieved character.
>>
>> This is complicated because we'd need to retrieve the character at
>> (cols-2, rows-1) from the frame matrix if tty_write_glyphs is called
>> with len == 1 and the cursor is at (cols-1,rows-1).
>>
>> Anyway, here's a patch that does this, but it seems too complicated to
>> be worth it to me:
>>
>> diff --git a/src/term.c b/src/term.c
>> index e15b7a0887e..ccee6c650e3 100644
>> --- a/src/term.c
>> +++ b/src/term.c
>> @@ -971,16 +971,36 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
>>    if (AutoWrap (tty)
>>        && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
>>        && curX (tty) + len == FRAME_COLS (f)
>> -      && curX (tty) < FRAME_COLS (f) - 1
>
> Ah, I see. It got into the else branch for len = 1. I think I
> misinterpreted what is happening. It didn't even try to insert. Sorry
> for that.
>
>>        && len > 0)
>>      {
>> -      /* Write glyphs except the first. */
>> -      int old_x = curX (tty), old_y = curY (tty);
>> -      tty_write_glyphs_1 (f, string + 1, len - 1);
>> +      if (len > 1)
>> +	{
>> +	  /* Write glyphs except the first. */
>> +	  int old_x = curX (tty), old_y = curY (tty);
>> +	  tty_write_glyphs_1 (f, string + 1, len - 1);
>>
>> -      /* Insert the first glyph, shifting the rest right.  */
>> -      cmgoto (tty, old_y, old_x);
>> -      tty_insert_glyphs (f, string, 1);
>> +	  /* Insert the first glyph, shifting the rest right.  */
>> +	  cmgoto (tty, old_y, old_x);
>> +	  tty_insert_glyphs (f, string, 1);
>> +	}
>> +      else
>> +	{
>> +	  struct glyph glyphs[2];
>> +	  glyphs[1] = string[0];
>> +	  if (!f->current_matrix || f->current_matrix->matrix_h < curY (tty))
>> +	    return;
>> +	  struct glyph_row *row = &f->current_matrix->rows[curY (tty)];
>> +	  int area = 0;
>> +	  int x = curX (tty) - 1;
>> +	  while (x > row->used[area])
>> +	    {
>> +	      x -= row->used[area];
>> +	      if (area++ == LAST_AREA)
>> +		return;
>> +	    }
>> +	  glyphs[0] = row->glyphs[area][x];
>> +	  tty_write_glyphs (f, glyphs, 2);
>> +	}
>
> Something like that, yes.

Or maybe simply use the glyph at string - 1 when cur_x == last column.
STRING is always part of a row, and we don't have rows that are
only partially filled, or are so narrow that string - 1 isn't valid.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Tue, 25 Mar 2025 05:07:02 GMT) Full text and rfc822 format available.

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

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Pip Cet <pipcet <at> protonmail.com>
Cc: n142857 <at> gmail.com, Eli Zaretskii <eliz <at> gnu.org>, 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50; crash if message starts with a space and
 then without it
Date: Tue, 25 Mar 2025 06:06:29 +0100
[Message part 1 (text/plain, inline)]
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:

>> Something like that, yes.
>
> Or maybe simply use the glyph at string - 1 when cur_x == last column.
> STRING is always part of a row, and we don't have rows that are
> only partially filled, or are so narrow that string - 1 isn't valid.

Like this:

[wrap.diff (text/x-patch, attachment)]
[Message part 3 (text/plain, inline)]
Sorry for being terse, have to get the train now :-).

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Wed, 26 Mar 2025 14:25:02 GMT) Full text and rfc822 format available.

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

From: Daniel Clemente <n142857 <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 77233 <at> debbugs.gnu.org
Subject: Re: bug#77233: 31.0.50; crash if message starts with a space and then
 without it
Date: Wed, 26 Mar 2025 14:23:50 +0000
> Does the crash depend on the terminal emulator you use?

I was using urxvt, which also implements autowrap. As mentioned in the
thread, it also happens in xterm.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Wed, 26 Mar 2025 14:25:03 GMT) Full text and rfc822 format available.

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

From: Daniel Clemente <n142857 <at> gmail.com>
To: Pip Cet <pipcet <at> protonmail.com>
Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>,
 77233 <at> debbugs.gnu.org, Eli Zaretskii <eliz <at> gnu.org>
Subject: Re: bug#77233: 31.0.50; crash if message starts with a space and then
 without it
Date: Wed, 26 Mar 2025 14:24:04 +0000
[Message part 1 (text/plain, inline)]
> > If it's urgent, maybe try to comment out the emacs_abort in cmcheckmagic
> > and see if that suffices.
>
> That avoids the crash here, and things work fine in an xterm, but it
> means we printed a character with the cursor at (cols-1,rows-1), which
> allegedly would have caused some (old, I assume?) terminals to scroll by
> a line, destroying the entire Emacs layout...
>
> However, xterm and M-x term both handle this situation sensibly, not
> scrolling the frame.  Is anyone aware of a terminal emulator that
> scrolls in this situation?

If I comment the emacs_abort, I see everything scroll 1 line upwards,
in many terminals: xterm, urxvt, mlterm, Eterm, lxterm,
cool-retro-term.
Every C-x C-e scrolls it 1 line. C-l fixes it.
I have several customizations in .Xresources that may affect what I'm
seeing in some terminal, but not in all the ones I tested.  I don't
know why doesn't your Emacs-in-xterm scroll. Did you run the part that
sets the background color?


On first thought it seems safer to avoid printing at (cols-1, rows-1)
when we know that AutoWrap is enabled…

I know this is a different language and scenario, but I just checked
ncurses in Python, and it rejects writing at the bottom right corner:
  File "/n/cursor1.py", line 41, in main
    stdscr.addstr(y, x, letter, curses.color_pair(1))
_curses.error: addwstr() returned ERR

However, with C and using terminal sequences, I saw it's possible to
print at the bottom right without scrolling, in all of the terminal
emulators mentioned above.
I attach a test program that prints a letter in all four corners and
in the center, and doesn't scroll.
I don't know why Emacs scrolls but this test program doesn't (even
with autoscroll on). I don't know enough about terminals, so please
forgive my small mistakes.
[cursor2.c (text/x-csrc, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Thu, 27 Mar 2025 05:15:06 GMT) Full text and rfc822 format available.

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

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Daniel Clemente <n142857 <at> gmail.com>
Cc: 77233 <at> debbugs.gnu.org, Pip Cet <pipcet <at> protonmail.com>,
 Eli Zaretskii <eliz <at> gnu.org>
Subject: Re: bug#77233: 31.0.50; crash if message starts with a space and
 then without it
Date: Thu, 27 Mar 2025 06:14:23 +0100
Daniel Clemente <n142857 <at> gmail.com> writes:

> On first thought it seems safer to avoid printing at (cols-1, rows-1)
> when we know that AutoWrap is enabled…

I agree. That auto-wrap code is there since the very beginning, added to
Emacs 1985, derived from public domain code which is even older of
course (VT100 is from the mid 70s). Of course it would be nice if the
code could be "modernized", but who's gone do that, realistically?

Anyway. Since nobody complained about my patch while I was away, I've
pushed something like that now. Could you please give it a try, Daniel?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Thu, 27 Mar 2025 17:11:02 GMT) Full text and rfc822 format available.

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

From: Daniel Clemente <n142857 <at> gmail.com>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: 77233 <at> debbugs.gnu.org, Pip Cet <pipcet <at> protonmail.com>,
 Eli Zaretskii <eliz <at> gnu.org>
Subject: Re: bug#77233: 31.0.50; crash if message starts with a space and then
 without it
Date: Thu, 27 Mar 2025 17:09:31 +0000
> Anyway. Since nobody complained about my patch while I was away, I've
> pushed something like that now. Could you please give it a try, Daniel?

It's fixed now, and I can't reproduce the crash in any of the terminal
emulators mentioned. I tried:
- with zone-pgm-stress (or others)
- running zone, while resizing the terminal emulator
- with very small window sizes
- with other messages (e.g. garbage-collection-messages) are appearing
while zone-pgm-stress runs

Editing and everything else works normally.

So thanks!, and I think the bug can be closed.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77233; Package emacs. (Thu, 27 Mar 2025 17:17:02 GMT) Full text and rfc822 format available.

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

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: Daniel Clemente <n142857 <at> gmail.com>
Cc: 77233 <at> debbugs.gnu.org, Pip Cet <pipcet <at> protonmail.com>,
 Eli Zaretskii <eliz <at> gnu.org>
Subject: Re: bug#77233: 31.0.50; crash if message starts with a space and
 then without it
Date: Thu, 27 Mar 2025 18:16:25 +0100
Daniel Clemente <n142857 <at> gmail.com> writes:

>> Anyway. Since nobody complained about my patch while I was away, I've
>> pushed something like that now. Could you please give it a try, Daniel?
>
> It's fixed now, and I can't reproduce the crash in any of the terminal
> emulators mentioned. I tried:
> - with zone-pgm-stress (or others)
> - running zone, while resizing the terminal emulator
> - with very small window sizes
> - with other messages (e.g. garbage-collection-messages) are appearing
> while zone-pgm-stress runs
>
> Editing and everything else works normally.
>
> So thanks!, and I think the bug can be closed.

Thanks for testing. And closing.




bug marked as fixed in version 31.1, send any further explanations to 77233 <at> debbugs.gnu.org and Daniel Clemente <n142857 <at> gmail.com> Request was from Gerd Möllmann <gerd.moellmann <at> gmail.com> to control <at> debbugs.gnu.org. (Thu, 27 Mar 2025 17:18:02 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. (Fri, 25 Apr 2025 11:24:08 GMT) Full text and rfc822 format available.

This bug report was last modified 51 days ago.

Previous Next


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