Commit bc9f07c1 authored by nanahira's avatar nanahira

Merge branch 'patch-pointer' of github.com:salix5/ygopro into develop

parents 017fec71 9e8dbeeb
...@@ -935,11 +935,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) { ...@@ -935,11 +935,11 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) {
break; break;
} }
case STOC_HS_PLAYER_ENTER: { case STOC_HS_PLAYER_ENTER: {
if (len < 1 + (int)sizeof(STOC_HS_PlayerEnter)) if (len < 1 + STOC_HS_PlayerEnter_size)
return; return;
soundManager.PlaySoundEffect(SOUND_PLAYER_ENTER); soundManager.PlaySoundEffect(SOUND_PLAYER_ENTER);
STOC_HS_PlayerEnter packet; STOC_HS_PlayerEnter packet;
std::memcpy(&packet, pdata, sizeof packet); std::memcpy(&packet, pdata, STOC_HS_PlayerEnter_size);
const auto* pkt = &packet; const auto* pkt = &packet;
if(pkt->pos > 3) if(pkt->pos > 3)
break; break;
......
...@@ -8,82 +8,144 @@ ...@@ -8,82 +8,144 @@
#include <event2/bufferevent.h> #include <event2/bufferevent.h>
#include <event2/buffer.h> #include <event2/buffer.h>
#include <event2/thread.h> #include <event2/thread.h>
#include <type_traits>
#define check_trivially_copyable(T) static_assert(std::is_trivially_copyable<T>::value == true, "not trivially copyable")
namespace ygo { namespace ygo {
constexpr int SIZE_NETWORK_BUFFER = 0x2000; constexpr int SIZE_NETWORK_BUFFER = 0x2000;
constexpr int MAX_DATA_SIZE = SIZE_NETWORK_BUFFER - 3; constexpr int MAX_DATA_SIZE = SIZE_NETWORK_BUFFER - 3;
constexpr int MAINC_MAX = 250; // the limit of card_state
constexpr int SIDEC_MAX = MAINC_MAX;
struct HostInfo { struct HostInfo {
unsigned int lflist{}; uint32_t lflist{};
unsigned char rule{}; unsigned char rule{};
unsigned char mode{}; unsigned char mode{};
unsigned char duel_rule{}; unsigned char duel_rule{};
unsigned char no_check_deck{}; unsigned char no_check_deck{};
unsigned char no_shuffle_deck{}; unsigned char no_shuffle_deck{};
unsigned int start_lp{}; // byte padding[3]
uint32_t start_lp{};
unsigned char start_hand{}; unsigned char start_hand{};
unsigned char draw_count{}; unsigned char draw_count{};
unsigned short time_limit{}; uint16_t time_limit{};
}; };
check_trivially_copyable(HostInfo);
static_assert(sizeof(HostInfo) == 20, "size mismatch: HostInfo");
struct HostPacket { struct HostPacket {
unsigned short identifier; uint16_t identifier;
unsigned short version; uint16_t version;
unsigned short port; uint16_t port;
unsigned int ipaddr; // byte padding[2]
unsigned short name[20];
uint32_t ipaddr;
uint16_t name[20];
HostInfo host; HostInfo host;
}; };
check_trivially_copyable(HostPacket);
static_assert(sizeof(HostPacket) == 72, "size mismatch: HostPacket");
struct HostRequest { struct HostRequest {
unsigned short identifier; uint16_t identifier;
}; };
check_trivially_copyable(HostRequest);
static_assert(sizeof(HostRequest) == 2, "size mismatch: HostRequest");
struct CTOS_HandResult { struct CTOS_HandResult {
unsigned char res; unsigned char res;
}; };
check_trivially_copyable(CTOS_HandResult);
static_assert(sizeof(CTOS_HandResult) == 1, "size mismatch: CTOS_HandResult");
struct CTOS_TPResult { struct CTOS_TPResult {
unsigned char res; unsigned char res;
}; };
check_trivially_copyable(CTOS_TPResult);
static_assert(sizeof(CTOS_TPResult) == 1, "size mismatch: CTOS_TPResult");
struct CTOS_PlayerInfo { struct CTOS_PlayerInfo {
unsigned short name[20]; uint16_t name[20];
}; };
check_trivially_copyable(CTOS_PlayerInfo);
static_assert(sizeof(CTOS_PlayerInfo) == 40, "size mismatch: CTOS_PlayerInfo");
struct CTOS_CreateGame { struct CTOS_CreateGame {
HostInfo info; HostInfo info;
unsigned short name[20]; uint16_t name[20];
unsigned short pass[20]; uint16_t pass[20];
}; };
check_trivially_copyable(CTOS_CreateGame);
static_assert(sizeof(CTOS_CreateGame) == 100, "size mismatch: CTOS_CreateGame");
struct CTOS_JoinGame { struct CTOS_JoinGame {
unsigned short version; uint16_t version;
unsigned int gameid; // byte padding[2]
unsigned short pass[20];
uint32_t gameid;
uint16_t pass[20];
}; };
check_trivially_copyable(CTOS_JoinGame);
static_assert(sizeof(CTOS_JoinGame) == 48, "size mismatch: CTOS_JoinGame");
struct CTOS_Kick { struct CTOS_Kick {
unsigned char pos; unsigned char pos;
}; };
check_trivially_copyable(CTOS_Kick);
static_assert(sizeof(CTOS_Kick) == 1, "size mismatch: CTOS_Kick");
// STOC // STOC
struct STOC_ErrorMsg { struct STOC_ErrorMsg {
unsigned char msg; unsigned char msg;
unsigned int code; // byte padding[3]
uint32_t code;
}; };
check_trivially_copyable(STOC_ErrorMsg);
static_assert(sizeof(STOC_ErrorMsg) == 8, "size mismatch: STOC_ErrorMsg");
struct STOC_HandResult { struct STOC_HandResult {
unsigned char res1; unsigned char res1;
unsigned char res2; unsigned char res2;
}; };
check_trivially_copyable(STOC_HandResult);
static_assert(sizeof(STOC_HandResult) == 2, "size mismatch: STOC_HandResult");
struct STOC_CreateGame { struct STOC_CreateGame {
unsigned int gameid; uint32_t gameid;
}; };
check_trivially_copyable(STOC_CreateGame);
static_assert(sizeof(STOC_CreateGame) == 4, "size mismatch: STOC_CreateGame");
struct STOC_JoinGame { struct STOC_JoinGame {
HostInfo info; HostInfo info;
}; };
check_trivially_copyable(STOC_JoinGame);
static_assert(sizeof(STOC_JoinGame) == 20, "size mismatch: STOC_JoinGame");
struct STOC_TypeChange { struct STOC_TypeChange {
unsigned char type; unsigned char type;
}; };
check_trivially_copyable(STOC_TypeChange);
static_assert(sizeof(STOC_TypeChange) == 1, "size mismatch: STOC_TypeChange");
struct STOC_ExitGame { struct STOC_ExitGame {
unsigned char pos; unsigned char pos;
}; };
check_trivially_copyable(STOC_ExitGame);
static_assert(sizeof(STOC_ExitGame) == 1, "size mismatch: STOC_ExitGame");
struct STOC_TimeLimit { struct STOC_TimeLimit {
unsigned char player; unsigned char player;
unsigned short left_time; // byte padding[1]
uint16_t left_time;
}; };
check_trivially_copyable(STOC_TimeLimit);
static_assert(sizeof(STOC_TimeLimit) == 4, "size mismatch: STOC_TimeLimit");
/* /*
* STOC_Chat * STOC_Chat
* uint16_t player_type; * uint16_t player_type;
...@@ -92,17 +154,28 @@ struct STOC_TimeLimit { ...@@ -92,17 +154,28 @@ struct STOC_TimeLimit {
constexpr int LEN_CHAT_PLAYER = 1; constexpr int LEN_CHAT_PLAYER = 1;
constexpr int LEN_CHAT_MSG = 256; constexpr int LEN_CHAT_MSG = 256;
constexpr int SIZE_STOC_CHAT = (LEN_CHAT_PLAYER + LEN_CHAT_MSG) * sizeof(uint16_t); constexpr int SIZE_STOC_CHAT = (LEN_CHAT_PLAYER + LEN_CHAT_MSG) * sizeof(uint16_t);
struct STOC_HS_PlayerEnter { struct STOC_HS_PlayerEnter {
unsigned short name[20]; uint16_t name[20];
unsigned char pos; unsigned char pos;
// byte padding[1]
}; };
check_trivially_copyable(STOC_HS_PlayerEnter);
//static_assert(sizeof(STOC_HS_PlayerEnter) == 42, "size mismatch: STOC_HS_PlayerEnter");
constexpr int STOC_HS_PlayerEnter_size = 41; //workwround
struct STOC_HS_PlayerChange { struct STOC_HS_PlayerChange {
//pos<<4 | state //pos<<4 | state
unsigned char status; unsigned char status;
}; };
check_trivially_copyable(STOC_HS_PlayerChange);
static_assert(sizeof(STOC_HS_PlayerChange) == 1, "size mismatch: STOC_HS_PlayerChange");
struct STOC_HS_WatchChange { struct STOC_HS_WatchChange {
unsigned short watch_count; uint16_t watch_count;
}; };
check_trivially_copyable(STOC_HS_WatchChange);
static_assert(sizeof(STOC_HS_WatchChange) == 2, "size mismatch: STOC_HS_WatchChange");
class DuelMode; class DuelMode;
......
...@@ -279,16 +279,16 @@ void SingleDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) { ...@@ -279,16 +279,16 @@ void SingleDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) {
void SingleDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) { void SingleDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {
if(dp->type > 1 || ready[dp->type]) if(dp->type > 1 || ready[dp->type])
return; return;
if (len <= 8 || len % sizeof(int32_t) != 0) if (len < 8)
return; return;
bool valid = true; bool valid = true;
auto deckbuf = pdata; auto deckbuf = pdata;
int mainc = BufferIO::ReadInt32(deckbuf); int mainc = BufferIO::ReadInt32(deckbuf);
int sidec = BufferIO::ReadInt32(deckbuf); int sidec = BufferIO::ReadInt32(deckbuf);
const int deck_size = len - 2 * sizeof(int32_t); const int deck_size = len - 2 * sizeof(int32_t);
if (mainc < DECK_MIN_SIZE || mainc > DECK_MAX_SIZE + EXTRA_MAX_SIZE) if (mainc < 0 || mainc > MAINC_MAX)
valid = false; valid = false;
else if (sidec < 0 || sidec > SIDE_MAX_SIZE) else if (sidec < 0 || sidec > SIDEC_MAX)
valid = false; valid = false;
else if (deck_size != (mainc + sidec) * (int)sizeof(int32_t)) else if (deck_size != (mainc + sidec) * (int)sizeof(int32_t))
valid = false; valid = false;
...@@ -299,7 +299,7 @@ void SingleDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) { ...@@ -299,7 +299,7 @@ void SingleDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem); NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return; return;
} }
int deck_list[DECK_MAX_SIZE + EXTRA_MAX_SIZE + SIDE_MAX_SIZE]; int deck_list[SIZE_NETWORK_BUFFER / sizeof(int32_t)];
std::memcpy(deck_list, deckbuf, deck_size); std::memcpy(deck_list, deckbuf, deck_size);
if(duel_count == 0) { if(duel_count == 0) {
deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], deck_list, mainc, sidec); deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], deck_list, mainc, sidec);
......
...@@ -262,16 +262,16 @@ void TagDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) { ...@@ -262,16 +262,16 @@ void TagDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) {
void TagDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) { void TagDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {
if(dp->type > 3 || ready[dp->type]) if(dp->type > 3 || ready[dp->type])
return; return;
if (len <= 8 || len % sizeof(int32_t) != 0) if (len < 8)
return; return;
bool valid = true; bool valid = true;
auto deckbuf = pdata; auto deckbuf = pdata;
int mainc = BufferIO::ReadInt32(deckbuf); int mainc = BufferIO::ReadInt32(deckbuf);
int sidec = BufferIO::ReadInt32(deckbuf); int sidec = BufferIO::ReadInt32(deckbuf);
const int deck_size = len - 2 * sizeof(int32_t); const int deck_size = len - 2 * sizeof(int32_t);
if (mainc < DECK_MIN_SIZE || mainc > DECK_MAX_SIZE + EXTRA_MAX_SIZE) if (mainc < 0 || mainc > MAINC_MAX)
valid = false; valid = false;
else if (sidec < 0 || sidec > SIDE_MAX_SIZE) else if (sidec < 0 || sidec > SIDEC_MAX)
valid = false; valid = false;
else if (deck_size != (mainc + sidec) * (int)sizeof(int32_t)) else if (deck_size != (mainc + sidec) * (int)sizeof(int32_t))
valid = false; valid = false;
...@@ -282,7 +282,7 @@ void TagDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) { ...@@ -282,7 +282,7 @@ void TagDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem); NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return; return;
} }
int deck_list[DECK_MAX_SIZE + EXTRA_MAX_SIZE + SIDE_MAX_SIZE]; int deck_list[SIZE_NETWORK_BUFFER / sizeof(int32_t)];
std::memcpy(deck_list, deckbuf, deck_size); std::memcpy(deck_list, deckbuf, deck_size);
deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], deck_list, mainc, sidec); deck_error[dp->type] = deckManager.LoadDeck(pdeck[dp->type], deck_list, mainc, sidec);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment