Browse Source

Added safeguards to Redemptio's exp penalty code to prevent arithmetic overflow in case its requirement checks are somehow bypassed (see topic:152196).

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@13277 54d463be-8e91-2dee-dedb-b68131a5f0ec
ultramage 16 years ago
parent
commit
543a78b62f
2 changed files with 6 additions and 12 deletions
  1. 2 8
      src/map/pc.c
  2. 4 4
      src/map/skill.c

+ 2 - 8
src/map/pc.c

@@ -5172,10 +5172,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 			if(base_penalty) {
 			if(base_penalty) {
 			  	if (battle_config.pk_mode && src && src->type==BL_PC)
 			  	if (battle_config.pk_mode && src && src->type==BL_PC)
 					base_penalty*=2;
 					base_penalty*=2;
-				if(sd->status.base_exp < base_penalty)
-					sd->status.base_exp = 0;
-				else
-					sd->status.base_exp -= base_penalty;
+				sd->status.base_exp -= min(sd->status.base_exp, base_penalty);
 				clif_updatestatus(sd,SP_BASEEXP);
 				clif_updatestatus(sd,SP_BASEEXP);
 			}
 			}
 		}
 		}
@@ -5193,10 +5190,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 			if(base_penalty) {
 			if(base_penalty) {
 			  	if (battle_config.pk_mode && src && src->type==BL_PC)
 			  	if (battle_config.pk_mode && src && src->type==BL_PC)
 					base_penalty*=2;
 					base_penalty*=2;
-				if(sd->status.job_exp < base_penalty)
-					sd->status.job_exp = 0;
-				else
-					sd->status.job_exp -= base_penalty;
+				sd->status.job_exp -= min(sd->status.job_exp, base_penalty);
 				clif_updatestatus(sd,SP_JOBEXP);
 				clif_updatestatus(sd,SP_JOBEXP);
 			}
 			}
 		}
 		}

+ 4 - 4
src/map/skill.c

@@ -3054,8 +3054,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			}
 			}
 			skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty...
 			skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty...
 			if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty) { //Apply penalty
 			if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty) { //Apply penalty
-				sd->status.base_exp -= pc_nextbaseexp(sd) * skill_area_temp[0] * 2/1000; //0.2% penalty per each.
-				sd->status.job_exp -= pc_nextjobexp(sd) * skill_area_temp[0] * 2/1000;
+				sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * skill_area_temp[0] * 2/1000); //0.2% penalty per each.
+				sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * skill_area_temp[0] * 2/1000);
 				clif_updatestatus(sd,SP_BASEEXP);
 				clif_updatestatus(sd,SP_BASEEXP);
 				clif_updatestatus(sd,SP_JOBEXP);
 				clif_updatestatus(sd,SP_JOBEXP);
 			}
 			}
@@ -8152,8 +8152,8 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in
 	case PR_REDEMPTIO:
 	case PR_REDEMPTIO:
 		{
 		{
 			int exp;
 			int exp;
-			if(((exp = pc_nextbaseexp(sd)) > 0 && sd->status.base_exp*100/exp < 1) ||
-				((exp = pc_nextjobexp(sd)) > 0 && sd->status.job_exp*100/exp < 1)) {
+			if( ((exp = pc_nextbaseexp(sd)) > 0 && get_percentage(sd->status.base_exp, exp) < 1) ||
+				((exp = pc_nextjobexp(sd)) > 0 && get_percentage(sd->status.job_exp, exp) < 1)) {
 				clif_skill_fail(sd,skill,0,0); //Not enough exp.
 				clif_skill_fail(sd,skill,0,0); //Not enough exp.
 				return 0;
 				return 0;
 			}
 			}