Color crash

Posted by Zeno on Sun 25 Jul 2004 04:41 AM — 8 posts, 23,704 views.

USA #0


#0  0x420751ce in calloc () from /lib/i686/libc.so.6
(gdb) bt
#0  0x420751ce in calloc () from /lib/i686/libc.so.6
#1  0x42074827 in calloc () from /lib/i686/libc.so.6
#2  0x42074544 in calloc () from /lib/i686/libc.so.6
#3  0x080aa735 in write_to_pager (d=0x837e828, txt=0x816aa43 "\e[0;32m", length=7)
    at color.c:1133
#4  0x080aa6a4 in set_pager_color (AType=82, ch=0x8377060) at color.c:1111
#5  0x08061eea in do_help (ch=0x8377060, argument=0xbfffd975 "setform") at act_info.c:1936
#6  0x080d5b67 in interpret (ch=0x8377060, argument=0xbfffd975 "setform") at interp.c:547
#7  0x080ab783 in game_loop () at comm.c:671
#8  0x080ab0b1 in main (argc=8, argv=0xbfffdd90) at comm.c:304
#9  0x42015967 in __libc_start_main () from /lib/i686/libc.so.6


So it seems like someone did 'help setform'. I can't see to get it to crash again from doing that. Maybe do_help is corrupt.

void do_help( CHAR_DATA *ch, char *argument )
{
    HELP_DATA *pHelp;
    char buf[MAX_STRING_LENGTH];

    set_pager_color( AT_HELP, ch );

    if ( (pHelp = get_help( ch, argument )) == NULL )
    {
        send_to_char( "No help on that word.\n\rPlease remember this is only alpha version.\n\r", ch );
        if ( !IS_IMMORTAL(ch))
        {
          sprintf( buf, "%s; helpfile not found: %s", ch->name, argument );
          to_channel( buf, CHANNEL_MONITOR, "HelpMonitor", LEVEL_IMMORTAL );
        }
        return;
    }

    /* Make newbies do a help start. --Shaddai */
    if ( !IS_NPC(ch) && !str_cmp( argument, "rules" ) )
        SET_BIT(ch->pcdata->flags, PCFLAG_HELPSTART);

    set_pager_color( AT_HELP, ch );

    if ( pHelp->level >= 0 && str_cmp( argument, "imotd" ) )
    {
        send_to_pager( "&G", ch );
        send_to_pager( pHelp->keyword, ch );
        send_to_pager( "\n\r", ch );
    }

    if ( pHelp->text[0] != '.' )
     send_to_pager( "&B=========================================================================&g\n\r", ch );
    /*
     * Strip leading '.' to allow initial blanks.
     */
    if ( pHelp->text[0] == '.' )
        send_to_pager_color( pHelp->text+1, ch );
    else
        send_to_pager_color( pHelp->text  , ch );
    if ( pHelp->text[0] != '.' )
     send_to_pager( "&B=========================================================================&w\n\r", ch );$
    return;
}


Anything wrong with do_help? Because it looks like something wrong with set_pager_color.
USA #1
Another crash, due to color.


#0  0x080a7cb4 in colorcode (col=0x81bc58a "Ddemon!\n\r", code=0xbfffa2a0 "\e[0m", ch=0x837d1f0) at color.c:895
895                        strncat( code, color_str( ch->desc->pagecolor, ch ), 20 );
(gdb) bt
#0  0x080a7cb4 in colorcode (col=0x81bc58a "Ddemon!\n\r", code=0xbfffa2a0 "\e[0m", ch=0x837d1f0) at color.c:895
#1  0x080a84c0 in send_to_char_color (txt=0x0, ch=0x837d1f0) at color.c:1238
#2  0x080a863b in send_to_char (txt=0x81bc560 "Diegos has lost his link.\n\r", ch=0x837d1f0) at color.c:1303
#3  0x080acb9f in act (AType=18, format=0xbfffb590 "$n's pound MASSACRES $N!", ch=0x8363438, arg1=0x0, arg2=0x8389da0,
    type=1) at comm.c:2853
#4  0x080c8574 in new_dam_message (ch=0x8363438, victim=0x8389da0, dam=25, dt=33, obj=0x0) at fight.c:3871
#5  0x080c5520 in damage (ch=0x8363438, victim=0x8389da0, dam=25, dt=1007) at fight.c:2189
#6  0x080c3b68 in one_hit (ch=0x8363438, victim=0x8389da0, dt=1007) at fight.c:1365
#7  0x080c28c3 in multi_hit (ch=0x8363438, victim=0x8389da0, dt=-1) at fight.c:804
#8  0x080c87ce in do_kill (ch=0x8363438, argument=0xbfffe982 "dem") at fight.c:3969
#9  0x080d38ac in interpret (ch=0x8363438, argument=0xbfffe982 "dem") at interp.c:557
#10 0x080a9183 in game_loop () at comm.c:671
#11 0x080a8ab1 in main (argc=8, argv=0xbfffeda0) at comm.c:304
#12 0x42015967 in __libc_start_main () from /lib/i686/libc.so.6

The char wasn't null this time, but he was link dead.
Canada #2
Ahhh, I've had a crash when someone was link dead. Are you using Samson's color snippet? If its FUSS, the snippet is pre-installed.

K, the problem seems to be here:[

     strncpy( code, ANSI_RESET, 20 ); /* Yes, this reset here is quite necessary to cancel out other things */
               if( ch )
        strncat( code, color_str( ch->desc->pagecolor, ch ), 20 );
     break;


This is in colorcode, which is called from
      if( colstr > prevstr )
         write_to_buffer( d, prevstr, ( colstr-prevstr ) );

      ln = colorcode( colstr, colbuf, d->character );
Now, the version in the snippet is different from mine, as mine seems to be old, it uses ch->desc, not d, but I think the principle still stands. If during write_to_buffer, the buffer exceeds 32000( see comm.c, write_to_buffer ), the player is disconnecting, desctroying their descriptor data. Now, there is a check:
   if ( !txt || !d->descriptor )
but it is before this section. So if this particular block is too much, d is destroyed, and then passed on to colorcode. The pointer exists, so the d = NULL in close_connection doesn't close the pointer of d in this function. So this bad pointer may crash on d->character, since d is dead. However, in my version of the code, it gets to colorcode, since it is using ch->desc instead, but now ch->desc is invalid, and it tries to call ch->desc->pagecolor, causing a crash. This is hard to see, of course, since your character was just disconnected due to a buffer overflow, heh.

Dunno if this has been resolved in the current edition, but I was faithfully able to recreate and came up with a solution for my own code:
      if ( !ch->desc ) return;
                        ln = colorcode(colstr, colbuf, ch);
You can probably check for d alone there, but that seemed to clear up the crashing issue. Hope that helps someone. If this has been resolved, just lemme know, maybe its time I updated my color code, heh.
Amended on Wed 28 Jul 2004 05:26 PM by Greven
USA #3
Hmm, so I put ( !ch->desc ) return; before each
ln = colorcode(colstr, colbuf, ch); in color.c?
Canada #4
Well, I just had the one to do, but yeah, likely others would be good.
USA #5
Well you never said what one to put it by, heh. So I didn't know where to put it.
Australia Forum Administrator #6
As far as I can see there is only one reference to ch->desc in colorcode, so why not put the test there?

Change:


 strncat( code, color_str( ch->desc->pagecolor, ch ), 20 );


to:


 if (ch->desc != NULL)
   strncat( code, color_str( ch->desc->pagecolor, ch ), 20 );
USA #7
Yeah, that was the first thing I did before I posted the second debug. Should be fixed.