From 4cff7105fd50de5b81a56bb28f030a9292733c22 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Fri, 1 Apr 2022 11:06:23 -0700 Subject: [PATCH] fix uninitialized memory in ep3 game join --- README.md | 1 + src/Player.cc | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/Player.hh | 22 ++++++++++++ 3 files changed, 121 insertions(+) diff --git a/README.md b/README.md index 356dff29..9361592d 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Current known issues / missing features: - The trade window isn't implemented yet. - PSO PC and PSOBB are essentially entirely untested. Only GC is fairly well-tested. - Add all the chat commands that khyller used to have. (Most, but not all, currently exist in newserv.) +- Hide the guild card number assigned by the remote server when proxying, and instead rewrite all commands that include the client's guild card number. ## Usage diff --git a/src/Player.cc b/src/Player.cc index bb9af277..2dffbac5 100644 --- a/src/Player.cc +++ b/src/Player.cc @@ -21,6 +21,33 @@ using namespace std; +PlayerStats::PlayerStats() noexcept + : atp(0), mst(0), evp(0), hp(0), dfp(0), ata(0), lck(0) { } + +PlayerDispDataPCGC::PlayerDispDataPCGC() noexcept + : level(0), + experience(0), + meseta(0), + unknown_a2(0), + name_color(0), + extra_model(0), + name_color_checksum(0), + section_id(0), + char_class(0), + v2_flags(0), + version(0), + v1_flags(0), + costume(0), + skin(0), + face(0), + head(0), + hair(0), + hair_r(0), + hair_g(0), + hair_b(0), + proportion_x(0), + proportion_y(0) { } + void PlayerDispDataPCGC::enforce_pc_limits() { // PC has fewer classes, so we'll substitute some here if (this->char_class == 11) { @@ -80,6 +107,32 @@ PlayerDispDataBB PlayerDispDataPCGC::to_bb() const { return bb; } + + +PlayerDispDataBB::PlayerDispDataBB() noexcept + : level(0), + experience(0), + meseta(0), + unknown_a2(0), + name_color(0), + extra_model(0), + name_color_checksum(0), + section_id(0), + char_class(0), + v2_flags(0), + version(0), + v1_flags(0), + costume(0), + skin(0), + face(0), + head(0), + hair(0), + hair_r(0), + hair_g(0), + hair_b(0), + proportion_x(0), + proportion_y(0) { } + // converts BB player data to PC/GC format PlayerDispDataPCGC PlayerDispDataBB::to_pcgc() const { PlayerDispDataPCGC pcgc; @@ -180,6 +233,40 @@ void PlayerDispDataBB::apply_preview(const PlayerDispDataBBPreview& pre) { +PlayerDispDataBBPreview::PlayerDispDataBBPreview() noexcept + : experience(0), + level(0), + unknown_a2(0), + name_color(0), + extra_model(0), + name_color_checksum(0), + section_id(0), + char_class(0), + v2_flags(0), + version(0), + v1_flags(0), + costume(0), + skin(0), + face(0), + head(0), + hair(0), + hair_r(0), + hair_g(0), + hair_b(0), + proportion_x(0), + proportion_y(0), + play_time(0) { } + + + +GuildCardGC::GuildCardGC() noexcept + : player_tag(0), serial_number(0), reserved1(1), reserved2(1), section_id(0), char_class(0) { } + +GuildCardBB::GuildCardBB() noexcept + : serial_number(0), reserved1(1), reserved2(1), section_id(0), char_class(0) { } + + + void PlayerBank::load(const string& filename) { *this = load_object_file(filename); for (uint32_t x = 0; x < this->num_items; x++) { @@ -339,6 +426,17 @@ void Player::save_player_data(const string& filename) const { +PlayerLobbyDataPC::PlayerLobbyDataPC() noexcept + : player_tag(0), guild_card(0), ip_address(0), client_id(0) { } + +PlayerLobbyDataGC::PlayerLobbyDataGC() noexcept + : player_tag(0), guild_card(0), ip_address(0), client_id(0) { } + +PlayerLobbyDataBB::PlayerLobbyDataBB() noexcept + : player_tag(0), guild_card(0), ip_address(0), client_id(0), unknown2(0) { } + + + //////////////////////////////////////////////////////////////////////////////// static const unordered_map combine_item_to_max({ diff --git a/src/Player.hh b/src/Player.hh index 55503b5c..31b8cb91 100644 --- a/src/Player.hh +++ b/src/Player.hh @@ -89,6 +89,8 @@ struct PlayerStats { le_uint16_t dfp; le_uint16_t ata; le_uint16_t lck; + + PlayerStats() noexcept; } __attribute__((packed)); struct PlayerDispDataBB; @@ -124,6 +126,12 @@ struct PlayerDispDataPCGC { // 0xD0 in size parray config; parray technique_levels; + // Note: This struct has a default constructor because it's used in a command + // that has a fixed-size array. If we didn't define this constructor, the + // trivial fields in that array's members would be uninitialized, and we could + // send uninitialized memory to the client. + PlayerDispDataPCGC() noexcept; + void enforce_pc_limits(); PlayerDispDataBB to_bb() const; } __attribute__((packed)); @@ -155,6 +163,8 @@ struct PlayerDispDataBBPreview { le_float proportion_y; ptext name; uint32_t play_time; + + PlayerDispDataBBPreview() noexcept; } __attribute__((packed)); // BB player appearance and stats data @@ -189,6 +199,8 @@ struct PlayerDispDataBB { parray config; parray technique_levels; + PlayerDispDataBB() noexcept; + inline void enforce_pc_limits() { } PlayerDispDataPCGC to_pcgc() const; PlayerDispDataBBPreview to_preview() const; @@ -206,6 +218,8 @@ struct GuildCardGC { uint8_t reserved2; // should be 1 uint8_t section_id; uint8_t char_class; + + GuildCardGC() noexcept; } __attribute__((packed)); // BB guild card format @@ -218,6 +232,8 @@ struct GuildCardBB { uint8_t reserved2; // should be 1 uint8_t section_id; uint8_t char_class; + + GuildCardBB() noexcept; } __attribute__((packed)); // an entry in the BB guild card file @@ -265,6 +281,8 @@ struct PlayerLobbyDataPC { be_uint32_t ip_address; le_uint32_t client_id; ptext name; + + PlayerLobbyDataPC() noexcept; } __attribute__((packed)); struct PlayerLobbyDataGC { @@ -273,6 +291,8 @@ struct PlayerLobbyDataGC { be_uint32_t ip_address; le_uint32_t client_id; ptext name; + + PlayerLobbyDataGC() noexcept; } __attribute__((packed)); struct PlayerLobbyDataBB { @@ -283,6 +303,8 @@ struct PlayerLobbyDataBB { le_uint32_t client_id; ptext name; le_uint32_t unknown2; + + PlayerLobbyDataBB() noexcept; } __attribute__((packed));