Przeglądaj źródła

* Fixed guild and guild member exp truncation issue (bugreport:4130, since r14242).
- Fixed guild member position, hair, hair color, gender, class and level could potentially become corrupted due to shorts being read as ints (partially since r2986).

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

ai4rei 14 lat temu
rodzic
commit
53fd4cef96

+ 2 - 0
Changelog-Trunk.txt

@@ -7,6 +7,8 @@ Date	Added
 	* Fixed map server getting notified of hair, hair color, gender, class and level changes from a char server (TXT only) twice (since r2986). [Ai4rei]
 	* Fixed saving/loading errors with compilers (such as VC6, MinGW), which do not recognize %ll format (since r14242). [Ai4rei]
 	- This also fixes guild leader name being displayed and saved as "(null)" in the guild member list.
+	* Fixed guild and guild member exp truncation issue (bugreport:4130, since r14242). [Ai4rei]
+	- Fixed guild member position, hair, hair color, gender, class and level could potentially become corrupted due to shorts being read as ints (partially since r2986).
 2010/11/21
 	* Added msinttypes (rev. 26, http://msinttypes.googlecode.com/svn/trunk/) portability framework for Visual C++ compilers (related bugreport:4059). [Ai4rei]
 	* Added 64-bit variants of the socket and buffer I/O macros. [Ai4rei]

+ 15 - 15
src/char/int_guild.c

@@ -42,7 +42,7 @@ int inter_guild_tostr(char* str, struct guild* g)
 	int i, c, len;
 
 	// save guild base info
-	len = sprintf(str, "%d\t%s\t%s\t%d,%d,%u,%d,%d\t%s#\t%s#\t",
+	len = sprintf(str, "%d\t%s\t%s\t%d,%d,%"PRIu64",%d,%d\t%s#\t%s#\t",
 		g->guild_id, g->name, g->master, g->guild_lv, g->max_member, g->exp, g->skill_point, 0, g->mes1, g->mes2);
 
 	// save guild member info
@@ -118,13 +118,13 @@ int inter_guild_fromstr(char* str, struct guild* g)
 		char master[256]; // only 24 used
 		int guildlv;
 		int max_member;
-		unsigned int exp;
+		uint64 exp;
 		int skpoint;
 		char mes1[256]; // only 60 used
 		char mes2[256]; // only 120 used
 		int len;
 
-		if( sscanf(str, "%d\t%[^\t]\t%[^\t]\t%d,%d,%u,%d,%*d\t%[^\t]\t%[^\t]\t%n",
+		if( sscanf(str, "%d\t%[^\t]\t%[^\t]\t%d,%d,%"SCNu64",%d,%*d\t%[^\t]\t%[^\t]\t%n",
 				   &guildid, name, master, &guildlv, &max_member, &exp, &skpoint, mes1, mes2, &len) < 9 )
 			return 1;
 
@@ -1236,55 +1236,55 @@ int mapif_parse_GuildMemberInfoChange(int fd, int guild_id, int account_id, int
 	}
 	switch(type) {
 	case GMI_POSITION:	// –ð�E
-		g->member[i].position = *((int *)data);
+		g->member[i].position = *((short *)data);
 		mapif_guild_memberinfochanged(guild_id, account_id, char_id, type, data, len);
 		break;
 	case GMI_EXP:	// EXP
 	{
-		unsigned int exp, old_exp=g->member[i].exp;
-		g->member[i].exp=*((unsigned int *)data);
+		uint64 exp, old_exp=g->member[i].exp;
+		g->member[i].exp=*((uint64 *)data);
 		if (g->member[i].exp > old_exp)
 		{
 			exp = g->member[i].exp - old_exp;
 			if (guild_exp_rate != 100)
 				exp = exp*guild_exp_rate/100;
-			if (exp > UINT_MAX - g->exp)
-				g->exp = UINT_MAX;
+			if (exp > UINT64_MAX - g->exp)
+				g->exp = UINT64_MAX;
 			else
 				g->exp+=exp;
 			guild_calcinfo(g);
-			mapif_guild_basicinfochanged(guild_id,GBI_EXP,&g->exp,4);
+			mapif_guild_basicinfochanged(guild_id,GBI_EXP,&g->exp,sizeof(g->exp));
 		}
 		mapif_guild_memberinfochanged(guild_id, account_id, char_id, type, data, len);
 		break;
 	}
 	case GMI_HAIR:
 	{
-		g->member[i].hair=*((int *)data);
+		g->member[i].hair=*((short *)data);
 		mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 		break;
 	}
 	case GMI_HAIR_COLOR:
 	{
-		g->member[i].hair_color=*((int *)data);
+		g->member[i].hair_color=*((short *)data);
 		mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 		break;
 	}
 	case GMI_GENDER:
 	{
-		g->member[i].gender=*((int *)data);
+		g->member[i].gender=*((short *)data);
 		mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 		break;
 	}
 	case GMI_CLASS:
 	{
-		g->member[i].class_=*((int *)data);
+		g->member[i].class_=*((short *)data);
 		mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 		break;
 	}
 	case GMI_LEVEL:
 	{
-		g->member[i].lv=*((int *)data);
+		g->member[i].lv=*((short *)data);
 		mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 		break;
 	}
@@ -1297,7 +1297,7 @@ int mapif_parse_GuildMemberInfoChange(int fd, int guild_id, int account_id, int
 	return 0;
 }
 
-int inter_guild_sex_changed(int guild_id,int account_id,int char_id, int gender)
+int inter_guild_sex_changed(int guild_id,int account_id,int char_id, short gender)
 {
 	return mapif_parse_GuildMemberInfoChange(0, guild_id, account_id, char_id, GMI_GENDER, (const char*)&gender, sizeof(gender));
 }

+ 1 - 1
src/char/int_guild.h

@@ -14,7 +14,7 @@ int inter_guild_parse_frommap(int fd);
 struct guild *inter_guild_search(int guild_id);
 int inter_guild_mapif_init(int fd);
 int inter_guild_leave(int guild_id,int account_id,int char_id);
-int inter_guild_sex_changed(int guild_id,int account_id,int char_id, int gender);
+int inter_guild_sex_changed(int guild_id,int account_id,int char_id, short gender);
 
 extern char guild_txt[1024];
 extern char castle_txt[1024];

+ 14 - 14
src/char_sql/int_guild.c

@@ -241,7 +241,7 @@ int inter_guild_tosql(struct guild *g,int flag)
 				StringBuf_AppendStr(&buf, ", ");
 			else
 				add_comma = true;
-			StringBuf_Printf(&buf, "`guild_lv`=%d, `skill_point`=%d, `exp`=%u, `next_exp`=%u, `max_member`=%d", g->guild_lv, g->skill_point, g->exp, g->next_exp, g->max_member);
+			StringBuf_Printf(&buf, "`guild_lv`=%d, `skill_point`=%d, `exp`=%"PRIu64", `next_exp`=%u, `max_member`=%d", g->guild_lv, g->skill_point, g->exp, g->next_exp, g->max_member);
 		}
 		StringBuf_Printf(&buf, " WHERE `guild_id`=%d", g->guild_id);
 		if( SQL_ERROR == Sql_Query(sql_handle, "%s", StringBuf_Value(&buf)) )
@@ -406,7 +406,7 @@ struct guild * inter_guild_fromsql(int guild_id)
 		g->max_member = MAX_GUILD;
 	}
 	Sql_GetData(sql_handle,  5, &data, NULL); g->average_lv = atoi(data);
-	Sql_GetData(sql_handle,  6, &data, NULL); g->exp = (unsigned int)strtoul(data, NULL, 10);
+	Sql_GetData(sql_handle,  6, &data, NULL); g->exp = strtoull(data, NULL, 10);
 	Sql_GetData(sql_handle,  7, &data, NULL); g->next_exp = (unsigned int)strtoul(data, NULL, 10);
 	Sql_GetData(sql_handle,  8, &data, NULL); g->skill_point = atoi(data);
 	Sql_GetData(sql_handle,  9, &data, &len); memcpy(g->mes1, data, min(len, sizeof(g->mes1)));
@@ -1588,7 +1588,7 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha
 	{
 		case GMI_POSITION:
 		  {
-			g->member[i].position=*((int *)data);
+			g->member[i].position=*((short *)data);
 			g->member[i].modified = GS_MEMBER_MODIFIED;
 			mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 			g->save_flag |= GS_MEMBER;
@@ -1596,8 +1596,8 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha
 		  }
 		case GMI_EXP:
 		{	// EXP
-			unsigned int exp, old_exp=g->member[i].exp;
-			g->member[i].exp=*((unsigned int *)data);
+			uint64 exp, old_exp=g->member[i].exp;
+			g->member[i].exp=*((uint64 *)data);
 			g->member[i].modified = GS_MEMBER_MODIFIED;
 			if (g->member[i].exp > old_exp)
 			{
@@ -1608,13 +1608,13 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha
 					exp = exp*guild_exp_rate/100;
 
 				// Update guild exp
-				if (exp > UINT_MAX - g->exp)
-					g->exp = UINT_MAX;
+				if (exp > UINT64_MAX - g->exp)
+					g->exp = UINT64_MAX;
 				else
 					g->exp+=exp;
 
 				guild_calcinfo(g);
-				mapif_guild_basicinfochanged(guild_id,GBI_EXP,&g->exp,4);
+				mapif_guild_basicinfochanged(guild_id,GBI_EXP,&g->exp,sizeof(g->exp));
 				g->save_flag |= GS_LEVEL;
 			}
 			mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
@@ -1623,7 +1623,7 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha
 		}
 		case GMI_HAIR:
 		{
-			g->member[i].hair=*((int *)data);
+			g->member[i].hair=*((short *)data);
 			g->member[i].modified = GS_MEMBER_MODIFIED;
 			mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 			g->save_flag |= GS_MEMBER; //Save new data.
@@ -1631,7 +1631,7 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha
 		}
 		case GMI_HAIR_COLOR:
 		{
-			g->member[i].hair_color=*((int *)data);
+			g->member[i].hair_color=*((short *)data);
 			g->member[i].modified = GS_MEMBER_MODIFIED;
 			mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 			g->save_flag |= GS_MEMBER; //Save new data.
@@ -1639,7 +1639,7 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha
 		}
 		case GMI_GENDER:
 		{
-			g->member[i].gender=*((int *)data);
+			g->member[i].gender=*((short *)data);
 			g->member[i].modified = GS_MEMBER_MODIFIED;
 			mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 			g->save_flag |= GS_MEMBER; //Save new data.
@@ -1647,7 +1647,7 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha
 		}
 		case GMI_CLASS:
 		{
-			g->member[i].class_=*((int *)data);
+			g->member[i].class_=*((short *)data);
 			g->member[i].modified = GS_MEMBER_MODIFIED;
 			mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 			g->save_flag |= GS_MEMBER; //Save new data.
@@ -1655,7 +1655,7 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha
 		}
 		case GMI_LEVEL:
 		{
-			g->member[i].lv=*((int *)data);
+			g->member[i].lv=*((short *)data);
 			g->member[i].modified = GS_MEMBER_MODIFIED;
 			mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
 			g->save_flag |= GS_MEMBER; //Save new data.
@@ -1668,7 +1668,7 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int cha
 	return 0;
 }
 
-int inter_guild_sex_changed(int guild_id,int account_id,int char_id, int gender)
+int inter_guild_sex_changed(int guild_id,int account_id,int char_id, short gender)
 {
 	return mapif_parse_GuildMemberInfoChange(0, guild_id, account_id, char_id, GMI_GENDER, (const char*)&gender, sizeof(gender));
 }

+ 1 - 1
src/char_sql/int_guild.h

@@ -28,7 +28,7 @@ int inter_guild_mapif_init(int fd);
 int inter_guild_leave(int guild_id,int account_id,int char_id);
 int mapif_parse_BreakGuild(int fd,int guild_id);
 int inter_guild_broken(int guild_id);
-int inter_guild_sex_changed(int guild_id,int account_id,int char_id, int gender);
+int inter_guild_sex_changed(int guild_id,int account_id,int char_id, short gender);
 int inter_guild_charname_changed(int guild_id,int account_id, int char_id, char *name);
 int inter_guild_CharOnline(int char_id, int guild_id);
 int inter_guild_CharOffline(int char_id, int guild_id);

+ 2 - 1
src/common/mmo.h

@@ -468,7 +468,8 @@ struct guild_skill {
 struct guild {
 	int guild_id;
 	short guild_lv, connect_member, max_member, average_lv;
-	unsigned int exp,next_exp;
+	uint64 exp;
+	unsigned int next_exp;
 	int skill_point;
 	char name[NAME_LENGTH],master[NAME_LENGTH];
 	struct guild_member member[MAX_GUILD];

+ 1 - 1
src/map/atcommand.c

@@ -3084,7 +3084,7 @@ ACMD_FUNC(guildlevelup)
 		added_level = 1 - guild_info->guild_lv;
 
 	if (added_level != 0) {
-		intif_guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, 2);
+		intif_guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, sizeof(added_level));
 		clif_displaymessage(fd, msg_txt(179)); // Guild level changed.
 	} else {
 		clif_displaymessage(fd, msg_txt(45)); // Guild level change failed.

+ 1 - 1
src/map/clif.c

@@ -6804,7 +6804,7 @@ int clif_guild_basicinfo(struct map_session_data *sd)
 	WFIFOL(fd,10)=g->connect_member;
 	WFIFOL(fd,14)=g->max_member;
 	WFIFOL(fd,18)=g->average_lv;
-	WFIFOL(fd,22)=g->exp;
+	WFIFOL(fd,22)=(uint32)cap_value(g->exp,0,INT_MAX);
 	WFIFOL(fd,26)=g->next_exp;
 	WFIFOL(fd,30)=0;	// Tax Points
 	WFIFOL(fd,34)=0;	// Tendency: (left) Vulgar [-100,100] Famed (right)

+ 1 - 1
src/map/guild.c

@@ -1003,7 +1003,7 @@ int guild_recv_message(int guild_id,int account_id,const char *mes,int len)
 	return 0;
 }
 // ギルドメンバの役職変更
-int guild_change_memberposition(int guild_id,int account_id,int char_id,int idx)
+int guild_change_memberposition(int guild_id,int account_id,int char_id,short idx)
 {
 	return intif_guild_change_memberinfo(guild_id,account_id,char_id,GMI_POSITION,&idx,sizeof(idx));
 }

+ 1 - 1
src/map/guild.h

@@ -73,7 +73,7 @@ int guild_check_alliance(int guild_id1, int guild_id2, int flag);
 
 int guild_send_memberinfoshort(struct map_session_data *sd,int online);
 int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_);
-int guild_change_memberposition(int guild_id,int account_id,int char_id,int idx);
+int guild_change_memberposition(int guild_id,int account_id,int char_id,short idx);
 int guild_memberposition_changed(struct guild *g,int idx,int pos);
 int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char *name);
 int guild_position_changed(int guild_id,int idx,struct guild_position *p);

+ 9 - 10
src/map/intif.c

@@ -1124,7 +1124,7 @@ int intif_parse_GuildBasicInfoChanged(int fd)
 		return 0;
 
 	switch(type) {
-	case GBI_EXP:        g->exp = RFIFOL(fd,10); break;
+	case GBI_EXP:        g->exp = RFIFOQ(fd,10); break;
 	case GBI_GUILDLV:    g->guild_lv = RFIFOW(fd,10); break;
 	case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break;
 	}
@@ -1141,8 +1141,7 @@ int intif_parse_GuildMemberInfoChanged(int fd)
 	int account_id = RFIFOL(fd,8);
 	int char_id = RFIFOL(fd,12);
 	int type = RFIFOW(fd,16);
-	void* data = RFIFOP(fd,18);
-	int dd = *((int *)data);
+	//void* data = RFIFOP(fd,18);
 
 	struct guild* g;
 	int idx;
@@ -1156,13 +1155,13 @@ int intif_parse_GuildMemberInfoChanged(int fd)
 		return 0;
 
 	switch( type ) {
-	case GMI_POSITION:   g->member[idx].position = dd; guild_memberposition_changed(g,idx,dd); break;
-	case GMI_EXP:        g->member[idx].exp = dd; break;
-	case GMI_HAIR:       g->member[idx].hair = dd; break;
-	case GMI_HAIR_COLOR: g->member[idx].hair_color = dd; break;
-	case GMI_GENDER:     g->member[idx].gender = dd; break;
-	case GMI_CLASS:      g->member[idx].class_ = dd; break;
-	case GMI_LEVEL:      g->member[idx].lv = dd; break;
+	case GMI_POSITION:   g->member[idx].position   = RFIFOW(fd,18); guild_memberposition_changed(g,idx,RFIFOW(fd,18)); break;
+	case GMI_EXP:        g->member[idx].exp        = RFIFOQ(fd,18); break;
+	case GMI_HAIR:       g->member[idx].hair       = RFIFOW(fd,18); break;
+	case GMI_HAIR_COLOR: g->member[idx].hair_color = RFIFOW(fd,18); break;
+	case GMI_GENDER:     g->member[idx].gender     = RFIFOW(fd,18); break;
+	case GMI_CLASS:      g->member[idx].class_     = RFIFOW(fd,18); break;
+	case GMI_LEVEL:      g->member[idx].lv         = RFIFOW(fd,18); break;
 	}
 	return 0;
 }