Переглянути джерело

Following r16914
-fix @zeny for negative amout bugreport:6886, bugreport:6895 bugreport:6888
-fix @cash,@points command display result
-enforce bound chk for both

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16924 54d463be-8e91-2dee-dedb-b68131a5f0ec

glighta 12 роки тому
батько
коміт
b4b7d621ee
7 змінених файлів з 76 додано та 50 видалено
  1. 30 17
      src/map/atcommand.c
  2. 1 1
      src/map/intif.c
  3. 0 1
      src/map/mail.c
  4. 1 1
      src/map/party.c
  5. 16 5
      src/map/pc.c
  6. 2 2
      src/map/pc.h
  7. 26 23
      src/map/trade.c

+ 30 - 17
src/map/atcommand.c

@@ -2522,7 +2522,7 @@ ACMD_FUNC(skillpoint)
 }
 
 /*==========================================
- * @zeny (Rewritten by [Yor])
+ * @zeny
  *------------------------------------------*/
 ACMD_FUNC(zeny)
 {
@@ -2533,10 +2533,14 @@ ACMD_FUNC(zeny)
 		clif_displaymessage(fd, msg_txt(1012)); // Please enter an amount (usage: @zeny <amount>).
 		return -1;
 	}
-	if(zeny > 0)
-	    pc_getzeny(sd,zeny,LOG_TYPE_COMMAND,NULL);
-	else
-	    pc_payzeny(sd,zeny,LOG_TYPE_COMMAND,NULL);
+
+	if(zeny > 0){
+	    if(pc_getzeny(sd,zeny,LOG_TYPE_COMMAND,NULL) == 1)
+		clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value.
+	}
+	else if(pc_payzeny(sd,-zeny,LOG_TYPE_COMMAND,NULL) == 1){
+	    clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value.
+	}
 	return 0;
 }
 
@@ -7858,6 +7862,7 @@ ACMD_FUNC(cash)
 {
 	char output[128];
 	int value;
+	int ret=0;
 	nullpo_retr(-1, sd);
 
 	if( !message || !*message || (value = atoi(message)) == 0 ) {
@@ -7868,25 +7873,33 @@ ACMD_FUNC(cash)
 	if( !strcmpi(command+1,"cash") )
 	{
 		if( value > 0 ) {
-			pc_getcash(sd, value, 0);
-			sprintf(output, msg_txt(505), value, sd->cashPoints);
-			clif_disp_onlyself(sd, output, strlen(output));
+			if( (ret=pc_getcash(sd, value, 0)) >= 0){
+			    sprintf(output, msg_txt(505), ret, sd->cashPoints);
+			    clif_disp_onlyself(sd, output, strlen(output));
+			}
+			else clif_displaymessage(fd, msg_txt(149)); // Unable to decrease the number/value.
 		} else {
-			pc_paycash(sd, -value, 0);
-			sprintf(output, msg_txt(410), value, sd->cashPoints);
-			clif_disp_onlyself(sd, output, strlen(output));
+			if( (ret=pc_paycash(sd, -value, 0)) >= 0){
+			    sprintf(output, msg_txt(410), ret, sd->cashPoints);
+			    clif_disp_onlyself(sd, output, strlen(output));
+			}
+			else clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value.
 		}
 	}
 	else
 	{ // @points
 		if( value > 0 ) {
-			pc_getcash(sd, 0, value);
-			sprintf(output, msg_txt(506), value, sd->kafraPoints);
-			clif_disp_onlyself(sd, output, strlen(output));
+			if( (ret=pc_getcash(sd, 0, value)) >= 0){
+			    sprintf(output, msg_txt(506), ret, sd->kafraPoints);
+			    clif_disp_onlyself(sd, output, strlen(output));
+			}
+			else clif_displaymessage(fd, msg_txt(149)); // Unable to decrease the number/value.
 		} else {
-			pc_paycash(sd, -value, -value);
-			sprintf(output, msg_txt(411), -value, sd->kafraPoints);
-			clif_disp_onlyself(sd, output, strlen(output));
+			if( (ret=pc_paycash(sd, -value, -value)) >= 0){
+			    sprintf(output, msg_txt(411), ret, sd->kafraPoints);
+			    clif_disp_onlyself(sd, output, strlen(output));
+			}
+			else clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value.
 		}
 	}
 

+ 1 - 1
src/map/intif.c

@@ -1827,7 +1827,7 @@ static void intif_parse_Auction_register(int fd)
 		clif_Auction_message(sd->fd, 4);
 		pc_additem(sd, &auction.item, auction.item.amount, LOG_TYPE_AUCTION);
 
-		pc_getzeny(sd, zeny, LOG_TYPE_AUCTION,NULL);
+		pc_getzeny(sd, zeny, LOG_TYPE_AUCTION, NULL);
 	}
 }
 

+ 0 - 1
src/map/mail.c

@@ -51,7 +51,6 @@ int mail_removezeny(struct map_session_data *sd, short flag)
 		pc_payzeny(sd,sd->mail.zeny,LOG_TYPE_MAIL, NULL);
 	}
 	sd->mail.zeny = 0;
-	clif_updatestatus(sd, SP_ZENY);
 
 	return 1;
 }

+ 1 - 1
src/map/party.c

@@ -949,7 +949,7 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b
 		pc_gainexp(sd[i], src, base_exp, job_exp, false);
 
 		if (zeny) // zeny from mobs [Valaris]
-			pc_getzeny(sd[i],zeny,LOG_TYPE_OTHER,NULL);
+			pc_getzeny(sd[i],zeny,LOG_TYPE_PICKDROP_MONSTER,NULL);
 	}
 	return 0;
 }

+ 16 - 5
src/map/pc.c

@@ -3590,6 +3590,7 @@ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
 {
 	nullpo_ret(sd);
 
+	zeny = cap_value(zeny,-MAX_ZENY,MAX_ZENY); //prevent command UB
 	if( zeny < 0 )
 	{
 		ShowError("pc_payzeny: Paying negative Zeny (zeny=%d, account_id=%d, char_id=%d).\n", zeny, sd->status.account_id, sd->status.char_id);
@@ -3616,16 +3617,17 @@ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
  * Cash Shop
  *------------------------------------------*/
 
-void pc_paycash(struct map_session_data *sd, int price, int points)
+int pc_paycash(struct map_session_data *sd, int price, int points)
 {
 	char output[128];
 	int cash;
 	nullpo_retv(sd);
 
+	points = cap_value(points,-MAX_ZENY,MAX_ZENY); //prevent command UB
 	if( price < 0 || points < 0 )
 	{
 		ShowError("pc_paycash: Paying negative points (price=%d, points=%d, account_id=%d, char_id=%d).\n", price, points, sd->status.account_id, sd->status.char_id);
-		return;
+		return -2;
 	}
 
 	if( points > price )
@@ -3639,7 +3641,7 @@ void pc_paycash(struct map_session_data *sd, int price, int points)
 	if( sd->cashPoints < cash || sd->kafraPoints < points )
 	{
 		ShowError("pc_paycash: Not enough points (cash=%d, kafra=%d) to cover the price (cash=%d, kafra=%d) (account_id=%d, char_id=%d).\n", sd->cashPoints, sd->kafraPoints, cash, points, sd->status.account_id, sd->status.char_id);
-		return;
+		return -1;
 	}
 
 	pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints-cash);
@@ -3650,13 +3652,16 @@ void pc_paycash(struct map_session_data *sd, int price, int points)
 		sprintf(output, msg_txt(504), points, cash, sd->kafraPoints, sd->cashPoints);
 		clif_disp_onlyself(sd, output, strlen(output));
 	}
+	return cash+points;
 }
 
-void pc_getcash(struct map_session_data *sd, int cash, int points)
+int pc_getcash(struct map_session_data *sd, int cash, int points)
 {
 	char output[128];
 	nullpo_retv(sd);
 
+	cash = cap_value(cash,-MAX_ZENY,MAX_ZENY); //prevent command UB
+	points = cap_value(points,-MAX_ZENY,MAX_ZENY); //prevent command UB
 	if( cash > 0 )
 	{
 		if( cash > MAX_ZENY-sd->cashPoints )
@@ -3672,10 +3677,12 @@ void pc_getcash(struct map_session_data *sd, int cash, int points)
 			sprintf(output, msg_txt(505), cash, sd->cashPoints);
 			clif_disp_onlyself(sd, output, strlen(output));
 		}
+		return cash;
 	}
 	else if( cash < 0 )
 	{
 		ShowError("pc_getcash: Obtaining negative cash points (cash=%d, account_id=%d, char_id=%d).\n", cash, sd->status.account_id, sd->status.char_id);
+		return -1;
 	}
 
 	if( points > 0 )
@@ -3693,11 +3700,14 @@ void pc_getcash(struct map_session_data *sd, int cash, int points)
 			sprintf(output, msg_txt(506), points, sd->kafraPoints);
 			clif_disp_onlyself(sd, output, strlen(output));
 		}
+		return points;
 	}
 	else if( points < 0 )
 	{
 		ShowError("pc_getcash: Obtaining negative kafra points (points=%d, account_id=%d, char_id=%d).\n", points, sd->status.account_id, sd->status.char_id);
+		return -1;
 	}
+	return -2; //shouldn't happen but jsut in case
 }
 
 /*==========================================
@@ -3708,6 +3718,7 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
 {
 	nullpo_ret(sd);
 
+	zeny = cap_value(zeny,-MAX_ZENY,MAX_ZENY); //prevent command UB
 	if( zeny < 0 )
 	{
 		ShowError("pc_getzeny: Obtaining negative Zeny (zeny=%d, account_id=%d, char_id=%d).\n", zeny, sd->status.account_id, sd->status.char_id);
@@ -3720,7 +3731,7 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
 	sd->status.zeny += zeny;
 	clif_updatestatus(sd,SP_ZENY);
 
-	if(!sd) tsd = sd;
+	if(!tsd) tsd = sd;
 	log_zeny(sd, type, tsd, zeny);
 	if( zeny > 0 && sd->state.showzeny ) {
 		char output[255];

+ 2 - 2
src/map/pc.h

@@ -701,8 +701,8 @@ int pc_getzeny(struct map_session_data*,int, enum e_log_pick_type, struct map_se
 int pc_delitem(struct map_session_data*,int,int,int,short,e_log_pick_type);
 
 // Special Shop System
-void pc_paycash(struct map_session_data *sd, int price, int points);
-void pc_getcash(struct map_session_data *sd, int cash, int points);
+int pc_paycash(struct map_session_data *sd, int price, int points);
+int pc_getcash(struct map_session_data *sd, int cash, int points);
 
 int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type);
 int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type);

+ 26 - 23
src/map/trade.c

@@ -74,15 +74,15 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
 		clif_displaymessage(sd->fd, msg_txt(246));
 		clif_tradestart(sd, 2); // GM is not allowed to trade
 		return;
-	} 
-	
+	}
+
 	// Players can not request trade from far away, unless they are allowed to use @trade.
 	if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) &&
 	    (sd->bl.m != target_sd->bl.m || !check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE))) {
 		clif_tradestart(sd, 0); // too far
 		return ;
 	}
-	
+
 	target_sd->trade_partner = sd->status.account_id;
 	sd->trade_partner = target_sd->status.account_id;
 	clif_traderequest(target_sd, sd->status.name);
@@ -106,7 +106,7 @@ void trade_tradeack(struct map_session_data *sd, int type)
 
 	if (sd->state.trading || !sd->trade_partner)
 		return; //Already trading or no partner set.
-	
+
 	if ((tsd = map_id2sd(sd->trade_partner)) == NULL) {
 		clif_tradestart(sd, 1); // character does not exist
 		sd->trade_partner=0;
@@ -177,7 +177,7 @@ int impossible_trade_check(struct map_session_data *sd)
 	int i, index;
 
 	nullpo_retr(1, sd);
-	
+
 	if(sd->deal.zeny > sd->status.zeny)
 	{
 		pc_setglobalreg(sd,"ZENY_HACKER",1);
@@ -220,7 +220,7 @@ int impossible_trade_check(struct map_session_data *sd)
 			} else
 				// message about the ban
 				strcpy(message_to_gm, msg_txt(508)); //  This player hasn't been banned (Ban option is disabled).
-			
+
 			intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
 			return 1;
 		}
@@ -257,7 +257,7 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
 			n = sd->deal.item[trade_i].index;
 			if (amount > inventory[n].amount)
 				return 0; //qty Exploit?
-			
+
 			data = itemdb_search(inventory[n].nameid);
 			i = MAX_INVENTORY;
 			if (itemdb_isstackable2(data)) { //Stackable item.
@@ -272,7 +272,7 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
 						break;
 					}
 			}
-			
+
 			if (i == MAX_INVENTORY) {// look for an empty slot.
 				for(i = 0; i < MAX_INVENTORY && inventory2[i].nameid; i++);
 				if (i == MAX_INVENTORY)
@@ -439,7 +439,7 @@ void trade_tradeok(struct map_session_data *sd)
 
 	if(sd->state.deal_locked || !sd->state.trading)
 		return;
-	
+
 	if ((target_sd = map_id2sd(sd->trade_partner)) == NULL) {
 		trade_tradecancel(sd);
 		return;
@@ -470,7 +470,7 @@ void trade_tradecancel(struct map_session_data *sd)
 		clif_tradecancelled(sd);
 		return;
 	}
-	
+
 	for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual)
 		if (!sd->deal.item[trade_i].amount)
 			continue;
@@ -498,7 +498,7 @@ void trade_tradecancel(struct map_session_data *sd)
 		target_sd->deal.item[trade_i].index = 0;
 		target_sd->deal.item[trade_i].amount = 0;
 	}
-	
+
 	if (target_sd->deal.zeny) {
 		clif_updatestatus(target_sd, SP_ZENY);
 		target_sd->deal.zeny = 0;
@@ -525,9 +525,9 @@ void trade_tradecommit(struct map_session_data *sd)
 		trade_tradecancel(sd);
 		return;
 	}
-	
+
 	sd->state.deal_locked = 2;
-	
+
 	if (tsd->state.deal_locked < 2)
 		return; //Not yet time for trading.
 
@@ -547,7 +547,7 @@ void trade_tradecommit(struct map_session_data *sd)
 		trade_tradecancel(sd);
 		return;
 	}
-	
+
 	// trade is accepted and correct.
 	for( trade_i = 0; trade_i < 10; trade_i++ )
 	{
@@ -578,30 +578,33 @@ void trade_tradecommit(struct map_session_data *sd)
 		}
 	}
 
-	if( sd->deal.zeny || tsd->deal.zeny )
-	{
-		pc_getzeny(sd,tsd->deal.zeny - sd->deal.zeny,LOG_TYPE_TRADE, tsd);
-		pc_getzeny(tsd,sd->deal.zeny - tsd->deal.zeny,LOG_TYPE_TRADE, sd);
-
+	if( sd->deal.zeny ) {
+		pc_payzeny(sd ,sd->deal.zeny, LOG_TYPE_TRADE, tsd);
+		pc_getzeny(tsd,sd->deal.zeny,LOG_TYPE_TRADE, sd);
 		sd->deal.zeny = 0;
+
+	}
+	if ( tsd->deal.zeny) {
+		pc_payzeny(tsd,tsd->deal.zeny,LOG_TYPE_TRADE, sd);
+		pc_getzeny(sd ,tsd->deal.zeny,LOG_TYPE_TRADE, tsd);
 		tsd->deal.zeny = 0;
 	}
-	
+
 	sd->state.deal_locked = 0;
 	sd->trade_partner = 0;
 	sd->state.trading = 0;
-	
+
 	tsd->state.deal_locked = 0;
 	tsd->trade_partner = 0;
 	tsd->state.trading = 0;
-	
+
 	clif_tradecompleted(sd, 0);
 	clif_tradecompleted(tsd, 0);
 
 	// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
 	if (save_settings&1)
   	{
-		chrif_save(sd,0); 
+		chrif_save(sd,0);
 		chrif_save(tsd,0);
 	}
 }