瀏覽代碼

Corrected a few potential crash points (#3874)

* Fixes #3872.
* Added a couple more map data validity checks on block list counting functions.
* QD Shot should no longer remove the read status.
* Dragon Trail should no longer end the Crimson Marker status.
* Some other minor optimizations/cleanups.
* Fixed a va_arg corruption
Thanks to @attackjom, @Lemongrass3110, and @teededung!
Aleos 6 年之前
父節點
當前提交
6c86492764
共有 2 個文件被更改,包括 46 次插入13 次删除
  1. 41 1
      src/map/map.cpp
  2. 5 12
      src/map/skill.cpp

+ 41 - 1
src/map/map.cpp

@@ -625,6 +625,10 @@ int map_foreachinrangeV(int (*func)(struct block_list*,va_list),struct block_lis
 
 	struct map_data *mapdata = map_getmapdata(m);
 
+	if( mapdata == nullptr || mapdata->block == nullptr ){
+		return 0;
+	}
+
 	x0 = i16max(center->x - range, 0);
 	y0 = i16max(center->y - range, 0);
 	x1 = i16min(center->x + range, mapdata->xs - 1);
@@ -744,7 +748,6 @@ int map_foreachinareaV(int(*func)(struct block_list*, va_list), int16 m, int16 x
 
 	struct map_data *mapdata = map_getmapdata(m);
 
-	// Required for delayed monster removal in instances
 	if( mapdata == nullptr || mapdata->block == nullptr ){
 		return 0;
 	}
@@ -849,6 +852,11 @@ int map_forcountinrange(int (*func)(struct block_list*,va_list), struct block_li
 
 	m = center->m;
 	mapdata = map_getmapdata(m);
+
+	if( mapdata == nullptr || mapdata->block == nullptr ){
+		return 0;
+	}
+
 	x0 = i16max(center->x - range, 0);
 	y0 = i16max(center->y - range, 0);
 	x1 = i16min(center->x + range, mapdata->xs - 1);
@@ -919,6 +927,10 @@ int map_forcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x
 
 	struct map_data *mapdata = map_getmapdata(m);
 
+	if( mapdata == nullptr || mapdata->block == nullptr ){
+		return 0;
+	}
+
 	x0 = i16max(x0, 0);
 	y0 = i16max(y0, 0);
 	x1 = i16min(x1, mapdata->xs - 1);
@@ -978,6 +990,10 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_
 
 	struct map_data *mapdata = map_getmapdata(m);
 
+	if( mapdata == nullptr || mapdata->block == nullptr ){
+		return 0;
+	}
+
 	x0 = center->x - range;
 	x1 = center->x + range;
 	y0 = center->y - range;
@@ -1097,6 +1113,10 @@ int map_foreachincell(int (*func)(struct block_list*,va_list), int16 m, int16 x,
 	struct map_data *mapdata = map_getmapdata(m);
 	va_list ap;
 
+	if( mapdata == nullptr || mapdata->block == nullptr ){
+		return 0;
+	}
+
 	if ( x < 0 || y < 0 || x >= mapdata->xs || y >= mapdata->ys ) return 0;
 
 	by = y / BLOCK_SIZE;
@@ -1219,6 +1239,10 @@ int map_foreachinpath(int (*func)(struct block_list*,va_list),int16 m,int16 x0,i
 
 	struct map_data *mapdata = map_getmapdata(m);
 
+	if( mapdata == nullptr || mapdata->block == nullptr ){
+		return 0;
+	}
+
 	mx0 = max(mx0, 0);
 	my0 = max(my0, 0);
 	mx1 = min(mx1, mapdata->xs - 1);
@@ -1359,6 +1383,10 @@ int map_foreachindir(int(*func)(struct block_list*, va_list), int16 m, int16 x0,
 
 	struct map_data *mapdata = map_getmapdata(m);
 
+	if( mapdata == nullptr || mapdata->block == nullptr ){
+		return 0;
+	}
+
 	//Get area that needs to be checked
 	mx0 = x0 + dx*(offset / ((dir % 2) + 1));
 	my0 = y0 + dy*(offset / ((dir % 2) + 1));
@@ -1483,6 +1511,10 @@ int map_foreachinmap(int (*func)(struct block_list*,va_list), int16 m, int type,
 	struct map_data *mapdata = map_getmapdata(m);
 	va_list ap;
 
+	if( mapdata == nullptr || mapdata->block == nullptr ){
+		return 0;
+	}
+
 	bsize = mapdata->bxs * mapdata->bys;
 
 	if( type&~BL_MOB )
@@ -1595,6 +1627,10 @@ int map_searchrandfreecell(int16 m,int16 *x,int16 *y,int stack) {
 	int free_cells[9][2];
 	struct map_data *mapdata = map_getmapdata(m);
 
+	if( mapdata == nullptr || mapdata->block == nullptr ){
+		return 0;
+	}
+
 	for(free_cell=0,i=-1;i<=1;i++){
 		if(i+*y<0 || i+*y>=mapdata->ys)
 			continue;
@@ -1666,6 +1702,10 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
 
 	struct map_data *mapdata = map_getmapdata(m);
 
+	if( mapdata == nullptr || mapdata->block == nullptr ){
+		return 0;
+	}
+
 	if (rx >= 0 && ry >= 0) {
 		tries = rx2*ry2;
 		if (tries > 100) tries = 100;

+ 5 - 12
src/map/skill.cpp

@@ -6053,18 +6053,11 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 		break;
 
 	case RL_QD_SHOT:
-		if (sd)
-			status_change_end(&sd->bl, SC_QD_SHOT_READY, INVALID_TIMER);
 	case RL_D_TAIL:
-		if (!sd || (sd && tsc && tsc->data[SC_C_MARKER])) {
-			int sflag = flag;
+		if (!sd || (tsc && tsc->data[SC_C_MARKER])) {
 			if (skill_id == RL_QD_SHOT && skill_area_temp[1] == bl->id )
 				break;
-			if (flag&1)
-				sflag = (skill_area_temp[0]&0xFFF)|(flag&SD_LEVEL ? SD_LEVEL : 0)|(flag&SD_ANIMATION ? SD_ANIMATION : 0);
-			skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, sflag);
-			if (sd && skill_id == RL_D_TAIL)
-				status_change_end(bl, SC_C_MARKER, INVALID_TIMER);
+			skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION);
 		}
 		break;
 
@@ -10847,7 +10840,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		}
 		break;
 	case RL_D_TAIL:
-		map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|SD_ANIMATION|1, skill_castend_damage_id);
+		map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
 		break;
 	case RL_QD_SHOT:
 		if (sd) {
@@ -11153,9 +11146,9 @@ static int8 skill_castend_id_check(struct block_list *src, struct block_list *ta
 				int count = 0;
 
 				if (battle_config.skill_wall_check)
-					count = map_foreachinshootrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, 0, BCT_ENEMY, skill_area_sub_count);
+					count = map_foreachinshootrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, gettick(), BCT_ENEMY, skill_area_sub_count);
 				else
-					count = map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, 0, BCT_ENEMY, skill_area_sub_count);
+					count = map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, gettick(), BCT_ENEMY, skill_area_sub_count);
 
 				if (!count) {
 					return USESKILL_FAIL_LEVEL;