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. */

Reply via email to