Issue information

Issue ID
#9
Status
Fixed
Severity
Critical
Started
Hercules Elf Bot
Sep 4, 2007 2:32
Last Post
Hercules Elf Bot
Sep 4, 2007 2:32
Confirmation
N/A

Hercules Elf Bot - Sep 4, 2007 2:32

Originally posted by [b]theultramage[/b]
http://www.eathena.ws/board/index.php?autocom=bugtracker&showbug=9

Summary:
There is a race condition in the code concerning @unloadnpc and OnNPCKillEvent (and the other events). If you manage to unload the npc while such an event is queued for execution, a null-pointer access crash will occur.

This was reported some time ago by zephyrus_cr in this particular topic.
He brought it up again today and after taking a peek at the code, it is obvious that there are some checks missing.

Offending code:
CODE
int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char* eventname)
{
    if ( sd->npc_id!=0) {
        //Enqueue the event trigger.
        int i;
        for(i=0;i<MAX_EVENTQUEUE && sd->eventqueue[i][0];i++);
        
        if (i==MAX_EVENTQUEUE) {
            if (battle_config.error_log)
                ShowWarning("npc_event: event queue is full !\n");
        }else //Event enqueued.
            memcpy(sd->eventqueue[i],eventname,50);
        return 1;
    }
>    if (ev->nd->sc.option&OPTION_INVISIBLE) {
        //Disabled npc, shouldn't trigger event.
        npc_event_dequeue(sd);
        return 2;
    }
    run_script(ev->nd->u.scr.script,ev->pos,sd->bl.id,ev->nd->bl.id);
    return 0;
}
In that particular situation, ev->nd was NULL.
Need to check why it was null, or rather, why didn't the invoking code check it and skip it?

This post has been edited by theultramage: Sep 3 2007, 07:32 PM