GNU bug report logs -
#77233
31.0.50; crash if message starts with a space and then without it
Previous Next
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.
Full log
Message #23 received at 77233 <at> debbugs.gnu.org (full text, mbox):
"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);
This bug report was last modified 52 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.