From 65e4adfc4f90aa087b7cde089029636257761a36 Mon Sep 17 00:00:00 2001 From: Fate Date: Wed, 17 Jun 2009 19:37:01 +0000 Subject: Added extra checks to ensure spell invocations aren't incorrectly deleted --- src/map/chat.c | 4 ++-- src/map/magic-stmt.c | 18 +++++++++--------- src/map/magic.h | 4 ++++ src/map/map.c | 16 ++++++++++++---- src/map/map.h | 4 ++-- src/map/skill.c | 2 +- 6 files changed, 30 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/map/chat.c b/src/map/chat.c index ade4dcb..8af50da 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -137,7 +137,7 @@ int chat_leavechat(struct map_session_data *sd) if(cd->users == 0 && (*cd->owner)->type==BL_PC){ // 全員居なくなった&PCのチャットなので消す clif_clearchat(cd,0); - map_delobject(cd->bl.id); // freeまでしてくれる + map_delobject(cd->bl.id, BL_CHAT); // freeまでしてくれる } else { for(i=leavechar;i < cd->users;i++) cd->usersd[i] = cd->usersd[i+1]; @@ -307,7 +307,7 @@ int chat_deletenpcchat(struct npc_data *nd) chat_npckickall(cd); clif_clearchat(cd,0); - map_delobject(cd->bl.id); // freeまでしてくれる + map_delobject(cd->bl.id, BL_CHAT); // freeまでしてくれる nd->chat_id=0; return 0; diff --git a/src/map/magic-stmt.c b/src/map/magic-stmt.c index a8d42f1..e488c2b 100644 --- a/src/map/magic-stmt.c +++ b/src/map/magic-stmt.c @@ -76,8 +76,8 @@ clear_stack(invocation_t *invocation) invocation->stack_size = 0; } -static void -free_invocation(invocation_t *invocation) +void +spell_free_invocation(invocation_t *invocation) { if (invocation->status_change_refs) { free(invocation->status_change_refs); @@ -100,7 +100,7 @@ free_invocation(invocation_t *invocation) magic_free_env(invocation->env); map_delblock(&invocation->bl); - map_delobject(invocation->bl.id); // also frees the object + map_delobject(invocation->bl.id, BL_SPELL); // also frees the object // free(invocation); } @@ -152,12 +152,12 @@ magic_stop_completely(character_t *c) c->sc_data[i].spell_invocation = 0; while (c->active_spells) - free_invocation(c->active_spells); + spell_free_invocation(c->active_spells); if (c->attack_spell_override) { invocation_t *attack_spell = (invocation_t *)map_id2bl(c->attack_spell_override); if (attack_spell) - free_invocation(attack_spell); + spell_free_invocation(attack_spell); c->attack_spell_override = 0; char_set_weapon_icon(c, 0, 0, 0); char_set_attack_info(c, 0, 0); @@ -175,7 +175,7 @@ try_to_finish_invocation(invocation_t *invocation) invocation->end_effect = NULL; spell_execute(invocation); } else - free_invocation(invocation); + spell_free_invocation(invocation); } } @@ -517,7 +517,7 @@ op_override_attack(env_t *env, int args_nr, val_t *args) if (subject->attack_spell_override) { invocation_t *old_invocation = (invocation_t *)map_id2bl(subject->attack_spell_override); if (old_invocation) - free_invocation(old_invocation); + spell_free_invocation(old_invocation); } subject->attack_spell_override = trigger_spell(subject->bl.id, VAR(VAR_INVOCATION).v.v_int); @@ -1452,7 +1452,7 @@ spell_attack(int caster_id, int target_id) if (invocation && caster->attack_spell_override != invocation->bl.id) { /* Attack spell changed / was refreshed */ - // free_invocation(invocation); // [Fate] This would be a double free. + // spell_free_invocation(invocation); // [Fate] This would be a double free. } else if (!invocation || caster->attack_spell_charges <= 0) { caster->attack_spell_override = 0; @@ -1463,7 +1463,7 @@ spell_attack(int caster_id, int target_id) pc_stopattack(caster); if (invocation) - free_invocation(invocation); + spell_free_invocation(invocation); } return 1; diff --git a/src/map/magic.h b/src/map/magic.h index 9ca47bb..49f2883 100644 --- a/src/map/magic.h +++ b/src/map/magic.h @@ -92,4 +92,8 @@ magic_stop_completely(character_t *c); int spell_attack(int caster, int target); + +void +spell_free_invocation(struct invocation *invocation); + #endif /* !defined(MAGIC_H_) */ diff --git a/src/map/map.c b/src/map/map.c index 128d50b..1acae20 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -575,10 +575,15 @@ int map_addobject(struct block_list *bl) { * map_delobjectのfreeしないバージョン *------------------------------------------ */ -int map_delobjectnofree(int id) { +int map_delobjectnofree(int id, int type) { if(object[id]==NULL) return 0; + if (object[id]->type != type) { + fprintf(stderr, "Incorrect type: expected %d, got %d\n", type, object[id]->type); + *((char *) 0) = 0; // break for backtrace + } + map_delblock(object[id]); numdb_erase(id_db,id); // map_freeblock(object[id]); @@ -601,13 +606,13 @@ int map_delobjectnofree(int id) { * addとの対称性が無いのが気になる *------------------------------------------ */ -int map_delobject(int id) { +int map_delobject(int id, int type) { struct block_list *obj = object[id]; if(obj==NULL) return 0; - map_delobjectnofree(id); + map_delobjectnofree(id, type); if (obj->type == BL_PC) // [Fate] Not sure where else to put this... I'm not sure where delobject for PCs is called from pc_cleanup((struct map_session_data *)obj); @@ -675,7 +680,7 @@ int map_clearflooritem_timer(int tid,unsigned int tick,int id,int data) { if(data) delete_timer(fitem->cleartimer,map_clearflooritem_timer); clif_clearflooritem(fitem,0); - map_delobject(fitem->bl.id); + map_delobject(fitem->bl.id, BL_ITEM); return 0; } @@ -1752,6 +1757,9 @@ static int cleanup_sub(struct block_list *bl, va_list ap) { case BL_SKILL: skill_delunit((struct skill_unit *) bl); break; + case BL_SPELL: + spell_free_invocation((struct invocation *) bl); + break; } return 0; diff --git a/src/map/map.h b/src/map/map.h index c678501..ceb3bbf 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -667,8 +667,8 @@ int map_countnearpc(int,int,int); int map_count_oncell(int m,int x,int y); // 一時的object関連 int map_addobject(struct block_list *); -int map_delobject(int); -int map_delobjectnofree(int id); +int map_delobject(int, int type); +int map_delobjectnofree(int id, int type); void map_foreachobject(int (*)(struct block_list*,va_list),int,...); // int map_quit(struct map_session_data *); diff --git a/src/map/skill.c b/src/map/skill.c index af56cab..3a777ac 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -9225,7 +9225,7 @@ int skill_delunit(struct skill_unit *unit) unit->group=NULL; unit->alive=0; - map_delobjectnofree(unit->bl.id); + map_delobjectnofree(unit->bl.id, BL_SKILL); if(group->alive_count>0 && (--group->alive_count)<=0) skill_delunitgroup(group); -- cgit v1.2.3-70-g09d2