diff options
author | shennetsind <shennetsind@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-09-26 21:00:22 +0000 |
---|---|---|
committer | shennetsind <shennetsind@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-09-26 21:00:22 +0000 |
commit | baba5683c591c05219e339e0e82c50aaa83cac96 (patch) | |
tree | 8bfe99289c5490f4290464898ab492bd73da7b27 /src/map | |
parent | 467d1cdf3c032168784aa1e89cce4b9e091636d2 (diff) | |
download | hercules-baba5683c591c05219e339e0e82c50aaa83cac96.tar.gz hercules-baba5683c591c05219e339e0e82c50aaa83cac96.tar.bz2 hercules-baba5683c591c05219e339e0e82c50aaa83cac96.tar.xz hercules-baba5683c591c05219e339e0e82c50aaa83cac96.zip |
Fixing a rare issue where a pointer of a already freed unit would have corrupted memory and causing unexpected behavior (most likely crashing)
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16803 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/battle.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index b83e2053d..2943db422 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -69,7 +69,7 @@ static int battle_gettargeted_sub(struct block_list *bl, va_list ap) if (bl->id == target_id) return 0; - if (*c >= 24) + if (*c >= 23) return 0; ud = unit_bl2ud(bl); @@ -90,7 +90,7 @@ struct block_list* battle_gettargeted(struct block_list *target) memset(bl_list, 0, sizeof(bl_list)); map_foreachinrange(battle_gettargeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id); - if (c == 0 || c > 24) + if (c == 0 || c > 23) return NULL; return bl_list[rnd()%c]; } @@ -187,8 +187,8 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int // ƒ_??[ƒW‚Ì’x‰„ struct delay_damage { - struct block_list *src; - struct block_list *target; + int src_id; + int target_id; int damage; int delay; unsigned short distance; @@ -198,29 +198,37 @@ struct delay_damage { unsigned short attack_type; }; -int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) -{ +int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { struct delay_damage *dat = (struct delay_damage *)data; - - if ( dat && dat->target && dat->target->prev != NULL && !status_isdead(dat->target) ) { - if( dat->src && dat->src->prev != NULL && id == dat->src->id && - dat->target->m == dat->src->m && - (dat->target->type != BL_PC || ((TBL_PC*)dat->target)->invincible_timer == INVALID_TIMER) && - check_distance_bl(dat->src, dat->target, dat->distance) ) //Check to see if you haven't teleported. [Skotlex] + + if ( dat ) { + struct block_list* src; + struct block_list* target = map_id2bl(dat->target_id); + + if( !target || status_isdead(target) ) {/* nothing we can do */ + ers_free(delay_damage_ers, dat); + return 0; + } + + src = map_id2bl(dat->src_id); + + if( src && target && target->m == src->m && + (target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == INVALID_TIMER) && + check_distance_bl(src, target, dat->distance) ) //Check to see if you haven't teleported. [Skotlex] { map_freeblock_lock(); - status_fix_damage(dat->src, dat->target, dat->damage, dat->delay); - if( dat->attack_type && !status_isdead(dat->target) ) - skill_additional_effect(dat->src,dat->target,dat->skill_id,dat->skill_lv,dat->attack_type,dat->dmg_lv,tick); + status_fix_damage(src, target, dat->damage, dat->delay); + if( dat->attack_type && !status_isdead(target) ) + skill_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,dat->dmg_lv,tick); if( dat->dmg_lv > ATK_BLOCK && dat->attack_type ) - skill_counter_additional_effect(dat->src,dat->target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); + skill_counter_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); map_freeblock_unlock(); - } else if( dat->skill_id == CR_REFLECTSHIELD && !map_id2bl(id) ) { + } else if( target && !src && dat->skill_id == CR_REFLECTSHIELD ) { /** * it was monster reflected damage, and the monster died, we pass the damage to the character as expected **/ map_freeblock_lock(); - status_fix_damage(dat->target, dat->target, dat->damage, dat->delay); + status_fix_damage(target, target, dat->damage, dat->delay); map_freeblock_unlock(); } } @@ -251,8 +259,8 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, return 0; } dat = ers_alloc(delay_damage_ers, struct delay_damage); - dat->src = src; - dat->target = target; + dat->src_id = src->id; + dat->target_id = target->id; dat->skill_id = skill_id; dat->skill_lv = skill_lv; dat->attack_type = attack_type; @@ -263,7 +271,7 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, if (src->type != BL_PC && amotion > 1000) amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex] - add_timer(tick+amotion, battle_delay_damage_sub, src->id, (intptr_t)dat); + add_timer(tick+amotion, battle_delay_damage_sub, 0, (intptr_t)dat); return 0; } |