[IRCServices Coding] svcs5

v13 at priest.com v13 at priest.com
Sun Dec 16 17:09:35 PST 2001


I don't understand this completely, but i get coredumps when
doing /msg chanserv levels #chan set ignore 6

it seems that there is something wrong...

in chanserv/util.c:

ChannelInfo *makechan(const char *chan)
{
    ChannelInfo *ci;

    ci = scalloc(sizeof(ChannelInfo), 1);
    strscpy(ci->name, chan, CHANMAX);
    ci->time_registered = time(NULL);
>>>>>    reset_levels(ci, 0);  <<<<<<
    return add_channelinfo(ci);
}

i bellieve this should be:
reset_levels(ci,1);


also in chanserv/access.c:

EXPORT_FUNC(reset_levels)
void reset_levels(ChannelInfo *ci, int set)
{
    int i;

>>>>>    free(ci->levels); <<<<<
    if (set) {
        ci->levels = scalloc(CA_SIZE, sizeof(*ci->levels));
        for (i = 0; i < CA_SIZE; i++)
            ci->levels[i] = def_levels[i];
    } else {
        ci->levels = NULL;
    }
}

this may try to free something that is not malloced (if i get this right)
when it is called from makechan() (free(NULL) works under glibc, but i don't
know how portable/standard it is)


finaly in chanserv/access-levels.c, in do_levels():

        for (i = 0; levelinfo[i].what >= 0; i++) {
            if (stricmp(levelinfo[i].name, what) == 0) {
                if (ci->levels)
                    reset_levels(ci, 1);
>>>>>                ci->levels[levelinfo[i].what] = level;  <<<<<<
                notice_lang(s_ChanServ, u, CHAN_LEVELS_CHANGED,
                        levelinfo[i].name, chan, level);
                put_channelinfo(ci);
                return;
            }
        }

the marked line is where i get the coredump...
it doesn't make any sense.. 
if ci->levels is NULL, then reset_levels is not called...
so it remains NULL and then ci->levels[] is used

(from gdb) (not wrapped)

(gdb) bt
#0  do_levels (u=0x814cf0c) at access-levels.c:324
#1  0x0804df4c in run_cmd (service=0x8144bd4 "ChanServ", u=0x814cf0c, id=0x81449c4, cmd=0xbffff5f2 "levels") at commands.c:158
#2  0x401a0070 in chanserv (source=0xbffff820 "V13", target=0xbffff5e8 "chanserv", buf=0xbffff5f2 "levels") at main.c:226
#3  0x08054cba in call_callback_5 (module=0x0, id=25, arg1=0xbffff820, arg2=0xbffff5e8, arg3=0xbffff5f2, arg4=0x0, arg5=0x0) at modules.c:605
#4  0x08052f3f in m_privmsg (source=0xbffff820 "V13", ac=2, av=0x814cd8c) at messages.c:169
#5  0x08055260 in process () at process.c:131
#6  0x08056395 in check_sockets () at sockets.c:362
#7  0x080526cc in main (ac=3, av=0xbffffa54, envp=0xbffffa64) at main.c:377
#8  0x4004d823 in __libc_start_main () from /lib/libc.so.6
(gdb) l access-levels.c:324
319             }
320             for (i = 0; levelinfo[i].what >= 0; i++) {
321                 if (stricmp(levelinfo[i].name, what) == 0) {
322                     if (ci->levels)
323                         reset_levels(ci, 1);
324                     ci->levels[levelinfo[i].what] = level;
325                     notice_lang(s_ChanServ, u, CHAN_LEVELS_CHANGED,
326                             levelinfo[i].name, chan, level);
327                     put_channelinfo(ci);
328                     return;
(gdb) p i
$1 = 224


<<V13>>