Subject: Re: libcurses border() leads to segfault
To: Julian Coleman <jdc@coris.org.uk>
From: Neil Ludban <nludban@columbus.rr.com>
List: current-users
Date: 10/23/2005 16:44:32
Julian Coleman wrote:
>>I've got a small libcurses test program that dumps core when linked with
>>electric fence:
> 
> 
>>Any other suggestions before I send-pr?
> 
> 
> Can you run this against a curses library with debugging enabled?  If you
> check out src/lib/libcurses [*], you can build it with DEBUG_CURSES=1 and
> FULL_DEBUG=1.  You'll also get an __curses.out file with the libraries
> internal workings.

I checked out libcurses from -current, and it looks like the bug has
been fixed since 3.99.5.  My machines are overdue for an upgrade, so
I'll just do that.  Below are a few more things I found, I also have
some __curses.out files which I can send on request (~35k each, gzipped).


Backtrace in 2.0_BETA, with debugging enabled in libcurses:

% gdb a.out a.out.core
GNU gdb 5.0nb1
Copyright 2000 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and you are
    welcome to change it and/or distribute copies of it under certain conditions.
    Type "show copying" to see the conditions.
    There is absolutely no warranty for GDB.  Type "show warranty" for details.
       This GDB was configured as "i386--netbsdelf"...Deprecated bfd_read called at /usr/src/gnu/dist/toolchain/gdb/dbxread.c line 2638 in elfstab_build_
psymtabs
       Deprecated bfd_read called at /usr/src/gnu/dist/toolchain/gdb/dbxread.c line 976 in fill_symbuf

       Core was generated by `a.out'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/libexec/ld.elf_so...done.
Loaded symbols for /usr/libexec/ld.elf_so
Reading symbols from /usr/lib/libcurses.so.5...done.
Loaded symbols for /usr/lib/libcurses.so.5
Reading symbols from /usr/lib/libc.so.12...done.
Loaded symbols for /usr/lib/libc.so.12
#0  0x4806ef21 in makech (wy=23) at refresh.c:802
802                     }
(gdb) bt
#0  0x4806ef21 in makech (wy=23) at refresh.c:802
#1  0x4806e492 in doupdate () at refresh.c:475
#2  0x4806de63 in wrefresh (win=0x4814efa8) at refresh.c:323
#3  0x4806d783 in refresh () at refresh.c:68
#4  0x8048e50 in main ()
#5  0x8048ae4 in ___start ()
(gdb) list
797                             }
798                             nsp++;
799     #ifdef DEBUG
800                             __CTRACE("makech: 2: wx = %d, lx = %d\n", wx, _cursesi_screen->lx);
801     #endif
802                     }
803                     if (_cursesi_screen->lx == wx)  /* If no change. */
804                             break;
805                     _cursesi_screen->lx = wx;
806                     if (_cursesi_screen->lx >= COLS && __tc_am)


I took the old and new __curses.out (both when linked with electric fence),
removed the timestamps and fixed the pointers, then diffed them.

This section in __curses.out, around line 3000, wasn't in the old one:

+  touchwin: (0x4813bfa8)
+  touchline: (0x4813bfa8, 0, 0, 79)
+  touchline: first = 80, last = 0
+  touchline: first = 0, last = 79
+  touchline: (0x4813bfa8, 1, 0, 79)
+  touchline: first = 80, last = 0
+  touchline: first = 0, last = 79
+  touchline: (0x4813bfa8, 2, 0, 79)
+  touchline: first = 80, last = 0
+  touchline: first = 0, last = 79
...
+  touchline: (0x4813bfa8, 22, 0, 79)
+  touchline: first = 80, last = 0
+  touchline: first = 0, last = 79
+  touchline: (0x4813bfa8, 23, 0, 79)
+  touchline: first = 80, last = 0
+  touchline: first = 0, last = 79


And the new one finishes at the end, where the old one crashed:

  makech: 2: wx = 76, lx = 0
  makech: have attributes 00010000, need attributes 00010000
  __cputchar: q
  makech: putchar(q)
  makech: 2: wx = 77, lx = 0
  makech: have attributes 00010000, need attributes 00010000
  __cputchar: q
  makech: putchar(q)
  makech: 2: wx = 78, lx = 0
  makech: have attributes 00010000, need attributes 00010000
  __cputchar: q
  makech: putchar(q)
  makech: 2: wx = 79, lx = 0
  makech: have attributes 00010000, need attributes 00010000
  makech: putchar(j)
  makech: 2: wx = 80, lx = 0
+  makech: 3: wx = 80, lx = 79
+  doupdate: line 23 notdirty
+       80      0
+  doupdate: ly=23, lx=79
+  __unsetattr: checkms = 1, ms = TRUE, wattr = 00010000
+  __cputchar: ^O
+  mvcur: moving cursor from (23, 79) to (0, 0)
+  __cputchar: ^[
+  __cputchar: [
+  __cputchar: 1
+  __cputchar: ;
+  __cputchar: 1
+  __cputchar: H
+  __unsetattr: checkms = 0, ms = TRUE, wattr = 00000000
+  __restore_stophandler: 1
+  __restore_winchhandler: 1
+  __unsetattr: checkms = 0, ms = TRUE, wattr = 00000000
+  mvcur: moving cursor from (0, 0) to (23, 0)
+  __cputchar: ^[
+  __cputchar: [
+  __cputchar: 2
+  __cputchar: 4
+  __cputchar: ;
+  __cputchar: 1
+  __cputchar: H
+  __cputchar: ^[
+  __cputchar: [
+  __cputchar: ?
+  __cputchar: 2
+  __cputchar: 5
+  __cputchar: h
+  __cputchar: ^[
+  __cputchar: [
+  __cputchar: 2
+  __cputchar: J
+  __cputchar: ^[
+  __cputchar: [
+  __cputchar: ?
+  __cputchar: 4
+  __cputchar: 7
+  __cputchar: l
+  __cputchar: ^[
+  __cputchar: 8


Rest of the differences appeared to be just the redefinition of
the attribute bit positions.

-Neil