In spell_effects.cpp there are a couple of lines that were introduced with the Enchanter rune patch that can be called with a negative array index.
I noticed this call was being made for Necromancers casting their pet spell, but that is likely not the only case this happens.
The pet spell fails the if((CalcBuffDuration(caster,this,spell_id)-1) != 0) and goes to the else assigning buffslot = -2
then the initialization to 0 of the buffs array for melee_rune and magic_rune is where buffslot(-2) is used on the array. This had the effect
of setting Agility and Dexterity to 0 on the server side for the Necromancer, but didn't crash anything.
Code:
bool Mob::SpellEffect(Mob* caster, int16 spell_id, float partial)
{
_ZP(Mob_SpellEffect);
int caster_level, buffslot, effect, effect_value, i;
ItemInst *SummonedItem=NULL;
#ifdef SPELL_EFFECT_SPAM
#define _EDLEN 200
char effect_desc[_EDLEN];
#endif
if(!IsValidSpell(spell_id))
return false;
const SPDat_Spell_Struct &spell = spells[spell_id];
if((CalcBuffDuration(caster,this,spell_id)-1) != 0){
buffslot = AddBuff(caster, spell_id);
if(buffslot == -1) // stacking failure
return false;
} else {
buffslot = -2; //represents not a buff I guess
}
caster_level = caster ? caster->GetCasterLevel(spell_id) : GetCasterLevel(spell_id);
#ifdef SPELL_EFFECT_SPAM
Message(0, "You are affected by spell '%s' (id %d)", spell.name, spell_id);
if(buffslot >= 0)
{
Message(0, "Buff slot: %d Duration: %d tics", buffslot, buffs[buffslot].ticsremaining);
}
#endif
buffs[buffslot].melee_rune = 0;
buffs[buffslot].magic_rune = 0;
I think it's just a simple fix of surrounding these two lines with an if check for safe array indexing
Code:
if(buffslot >= 0) {
buffs[buffslot].melee_rune = 0;
buffs[buffslot].magic_rune = 0;
}