* 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
This commit is contained in:
ai4rei 2010-11-22 16:52:46 +00:00
parent 4a8ab94031
commit 53fd4cef96
11 changed files with 48 additions and 46 deletions

View File

@ -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]

View File

@ -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: // ð<E28093>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));
}

View File

@ -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];

View File

@ -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));
}

View File

@ -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);

View File

@ -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];

View File

@ -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.

View File

@ -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)

View File

@ -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));
}

View File

@ -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);

View File

@ -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;
}