Package: info Version: 4.8-2 Severity: normal Tags: patch Hi,
When resizing the terminal rapidly, info will segfault: (gdb) bt #0 0x0804a503 in display_update_one_window (win=0x80a3fd8) at display.c:301 #1 0x0804a02b in display_update_display (window=0x80a3fd8) at display.c:85 #2 0x08061578 in redisplay_after_signal () at signals.c:161 #3 0x08061609 in reset_info_window_sizes () at signals.c:176 #4 0x0806180f in info_signal_proc (sig=28) at signals.c:277 #5 <signal handler called> #6 0xffffe40e in __kernel_vsyscall () #7 0xb7e4d193 in read () from /lib/tls/i686/cmov/libc.so.6 #8 0x080612a6 in info_get_input_char () at session.c:5002 #9 0x080595fd in info_read_and_dispatch () at session.c:217 #10 0x08059534 in info_session () at session.c:175 #11 0x0805950c in display_startup_message_and_start () at session.c:166 #12 0x080594c9 in begin_info_session (initial_node=0x8095e10) at session.c:153 #13 0x08051b58 in main (argc=2, argv=0xbf92c224) at info.c:507 (gdb) print entry $1 = (DISPLAY_LINE *) 0x0 I easily reproduce this with "info autoconf" or "info automake" in a xterm and rapidly resizing up and down, especially to a small size. My first guess what at the second part of the if() condition, hence I tried moving the entry != NULL test higher, but that wasn't enough since entry is derefenced a couple of times afterwards. Hence, I simply protected the following chunk, and the segfaults appear less often now. The segfaults happening with entry == NULL are gone for me, and I can resize info to a small size, however I still got an occasional segfault when rapidly resizing, with a weird value of entry: (gdb) bt #0 0x0804a4f4 in display_update_one_window (win=0x80a3fd8) at display.c:303 #1 0x0804a02b in display_update_display (window=0x80a3fd8) at display.c:85 #2 0x0806157c in redisplay_after_signal () at signals.c:161 #3 0x0806160d in reset_info_window_sizes () at signals.c:176 #4 0x08061813 in info_signal_proc (sig=28) at signals.c:277 #5 <signal handler called> #6 0xffffe40e in __kernel_vsyscall () #7 0xb7e7e193 in read () from /lib/tls/i686/cmov/libc.so.6 #8 0x080612aa in info_get_input_char () at session.c:5002 #9 0x08059601 in info_read_and_dispatch () at session.c:217 #10 0x08059538 in info_session () at session.c:175 #11 0x08059510 in display_startup_message_and_start () at session.c:166 #12 0x080594cd in begin_info_session (initial_node=0x8095e10) at session.c:153 #13 0x08051b5c in main (argc=2, argv=0xbfa5eba4) at info.c:507 (gdb) print entry $1 = (DISPLAY_LINE *) 0x59 I'm afraid some corruption happens or unintialized memory is used, and I suggest you run info in valgrind. If you find them useful, please include the attached changes. (The patch is large, but only a couple of lines were truly changed.) -- System Information: Debian Release: testing/unstable APT prefers oldstable APT policy: (500, 'oldstable'), (500, 'unstable'), (500, 'testing'), (500, 'stable'), (1, 'experimental') Architecture: i386 (i686) Shell: /bin/sh linked to /bin/bash Kernel: Linux 2.6.14-2-686 Locale: [EMAIL PROTECTED], [EMAIL PROTECTED] (charmap=ISO-8859-15) Versions of packages info depends on: ii libc6 2.3.5-9 GNU C Library: Shared libraries an ii libncurses5 5.5-1 Shared libraries for terminal hand info recommends no packages. -- no debconf information -- Loïc Minier <[EMAIL PROTECTED]> Current Earth status: NOT DESTROYED
--- texinfo-4.8/debian/changelog +++ texinfo-4.8/debian/changelog @@ -1,3 +1,12 @@ +texinfo (4.8-2.1) unstable; urgency=low + + * Non-maintainer upload. + * Fix segfault when resizing the terminal rapidly by checking more carefully + whether the display line is set prior to refering to it. + [info/display.c:display_update_one_window] + + -- Loic Minier <[EMAIL PROTECTED]> Mon, 2 Jan 2006 21:31:48 +0100 + texinfo (4.8-2) unstable; urgency=low * Edit the changelog entry for 4.8-1 to include fixes for bugs that --- texinfo-4.8.orig/info/display.c +++ texinfo-4.8/info/display.c @@ -294,62 +294,65 @@ on the screen. */ entry = display[line_index + win->first_row]; - /* If the screen line is inversed, then we have to clear - the line from the screen first. Why, I don't know. - (But don't do this if we have no visible entries, as can - happen if the window is shrunk very small.) */ - if ((entry && entry->inverse) - /* Need to erase the line if it has escape sequences. */ - || (raw_escapes_p && strchr (entry->text, '\033') != 0)) - { - terminal_goto_xy (0, line_index + win->first_row); - terminal_clear_to_eol (); - entry->inverse = 0; - entry->text[0] = '\0'; - entry->textlen = 0; - } + /* If the window is very small, entry might be NULL. */ + if (entry) { + /* If the screen line is inversed, then we have to clear + the line from the screen first. Why, I don't know. + (But don't do this if we have no visible entries, as can + happen if the window is shrunk very small.) */ + if (entry->inverse + /* Need to erase the line if it has escape sequences. */ + || (raw_escapes_p && strchr (entry->text, '\033') != 0)) + { + terminal_goto_xy (0, line_index + win->first_row); + terminal_clear_to_eol (); + entry->inverse = 0; + entry->text[0] = '\0'; + entry->textlen = 0; + } - /* Find the offset where these lines differ. */ - for (i = 0; i < pl_index; i++) - if (printed_line[i] != entry->text[i]) - break; - - /* If the lines are not the same length, or if they differed - at all, we must do some redrawing. */ - if ((i != pl_index) || (pl_index != entry->textlen)) - { - /* Move to the proper point on the terminal. */ - terminal_goto_xy (i, line_index + win->first_row); + /* Find the offset where these lines differ. */ + for (i = 0; i < pl_index; i++) + if (printed_line[i] != entry->text[i]) + break; + + /* If the lines are not the same length, or if they differed + at all, we must do some redrawing. */ + if ((i != pl_index) || (pl_index != entry->textlen)) + { + /* Move to the proper point on the terminal. */ + terminal_goto_xy (i, line_index + win->first_row); - /* If there is any text to print, print it. */ - if (i != pl_index) - terminal_put_text (printed_line + i); - - /* If the printed text didn't extend all the way to the edge - of the window, and text was appearing between here and the - edge of the window, clear from here to the end of the line. */ - if ((pl_index < win->width + pl_ignore - && pl_index < entry->textlen) - || (entry->inverse)) - terminal_clear_to_eol (); - - fflush (stdout); - - /* Update the display text buffer. */ - if (strlen (printed_line) > (unsigned int) screenwidth) - /* printed_line[] can include more than screenwidth - characters if we are under -R and there are escape - sequences in it. However, entry->text was - allocated (in display_initialize_display) for - screenwidth characters only. */ - entry->text = xrealloc (entry->text, strlen (printed_line)+1); - strcpy (entry->text + i, printed_line + i); - entry->textlen = pl_index; - - /* Lines showing node text are not in inverse. Only modelines - have that distinction. */ - entry->inverse = 0; - } + /* If there is any text to print, print it. */ + if (i != pl_index) + terminal_put_text (printed_line + i); + + /* If the printed text didn't extend all the way to the edge + of the window, and text was appearing between here and the + edge of the window, clear from here to the end of the line. */ + if ((pl_index < win->width + pl_ignore + && pl_index < entry->textlen) + || (entry->inverse)) + terminal_clear_to_eol (); + + fflush (stdout); + + /* Update the display text buffer. */ + if (strlen (printed_line) > (unsigned int) screenwidth) + /* printed_line[] can include more than screenwidth + characters if we are under -R and there are escape + sequences in it. However, entry->text was + allocated (in display_initialize_display) for + screenwidth characters only. */ + entry->text = xrealloc (entry->text, strlen (printed_line)+1); + strcpy (entry->text + i, printed_line + i); + entry->textlen = pl_index; + + /* Lines showing node text are not in inverse. Only modelines + have that distinction. */ + entry->inverse = 0; + } + } /* We have done at least one line. Increment our screen line index, and check against the bottom of the window. */