summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorai4rei <ai4rei@54d463be-8e91-2dee-dedb-b68131a5f0ec>2010-11-22 16:52:46 +0000
committerai4rei <ai4rei@54d463be-8e91-2dee-dedb-b68131a5f0ec>2010-11-22 16:52:46 +0000
commit2a3ca1bcfa82023b3f890f19775b115e8a744b88 (patch)
tree589420d27d8276eb70e90fd686ac92385830965a
parent873717f2814a890f5b8c52f0302d6cd67e3e29f6 (diff)
downloadhercules-2a3ca1bcfa82023b3f890f19775b115e8a744b88.tar.gz
hercules-2a3ca1bcfa82023b3f890f19775b115e8a744b88.tar.bz2
hercules-2a3ca1bcfa82023b3f890f19775b115e8a744b88.tar.xz
hercules-2a3ca1bcfa82023b3f890f19775b115e8a744b88.zip
* 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://rathena.svn.sourceforge.net/svnroot/rathena/trunk@14487 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r--Changelog-Trunk.txt2
-rw-r--r--src/char/int_guild.c30
-rw-r--r--src/char/int_guild.h2
-rw-r--r--src/char_sql/int_guild.c28
-rw-r--r--src/char_sql/int_guild.h2
-rw-r--r--src/common/mmo.h3
-rw-r--r--src/map/atcommand.c2
-rw-r--r--src/map/clif.c2
-rw-r--r--src/map/guild.c2
-rw-r--r--src/map/guild.h2
-rw-r--r--src/map/intif.c19
11 files changed, 48 insertions, 46 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index fdec5fc24..19f2c6dd3 100644
--- a/Changelog-Trunk.txt
+++ b/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]
diff --git a/src/char/int_guild.c b/src/char/int_guild.c
index ed9e52d96..9a815200f 100644
--- a/src/char/int_guild.c
+++ b/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: // 役職
- 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));
}
diff --git a/src/char/int_guild.h b/src/char/int_guild.h
index 06293eb0f..0be6c50d9 100644
--- a/src/char/int_guild.h
+++ b/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];
diff --git a/src/char_sql/int_guild.c b/src/char_sql/int_guild.c
index 3d2df8977..00331e8e6 100644
--- a/src/char_sql/int_guild.c
+++ b/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));
}
diff --git a/src/char_sql/int_guild.h b/src/char_sql/int_guild.h
index a14e09b00..4577357f3 100644
--- a/src/char_sql/int_guild.h
+++ b/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);
diff --git a/src/common/mmo.h b/src/common/mmo.h
index b1a257e9c..6a78d840c 100644
--- a/src/common/mmo.h
+++ b/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];
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 77aef527f..ead204fb5 100644
--- a/src/map/atcommand.c
+++ b/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.
diff --git a/src/map/clif.c b/src/map/clif.c
index 94c19287a..087a41187 100644
--- a/src/map/clif.c
+++ b/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)
diff --git a/src/map/guild.c b/src/map/guild.c
index 1b91dfc93..cdc978929 100644
--- a/src/map/guild.c
+++ b/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));
}
diff --git a/src/map/guild.h b/src/map/guild.h
index 753de0da1..c6b380647 100644
--- a/src/map/guild.h
+++ b/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);
diff --git a/src/map/intif.c b/src/map/intif.c
index c8aad3807..ba5230bab 100644
--- a/src/map/intif.c
+++ b/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;
}