From b0026b697a6ec898b066e7b5637dfda206511677 Mon Sep 17 00:00:00 2001 From: dP Date: Fri, 2 Apr 2021 15:51:55 +0300 Subject: [PATCH] Fix saveload format negotiation --- src/network/core/packet.cpp | 15 +++++++++++++++ src/network/core/packet.h | 1 + src/network/network_server.cpp | 4 +++- src/saveload/saveload.cpp | 5 +++-- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/network/core/packet.cpp b/src/network/core/packet.cpp index 94ffcc5584..a7931e4c55 100644 --- a/src/network/core/packet.cpp +++ b/src/network/core/packet.cpp @@ -180,6 +180,21 @@ bool Packet::CanReadFromPacket(uint bytes_to_read) return true; } +/* CityMania code begin */ +bool Packet::CMCheckRead(uint bytes_to_read) +{ + /* Don't allow reading from a quit client/client who send bad data */ + if (this->cs->HasClientQuit()) return false; + + /* Check if variable is within packet-size */ + if (this->pos + bytes_to_read > this->size) { + return false; + } + + return true; +} +/* CityMania code end */ + /** * Reads the packet size from the raw packet and stores it in the packet->size */ diff --git a/src/network/core/packet.h b/src/network/core/packet.h index c9be4eeb53..ec7557260b 100644 --- a/src/network/core/packet.h +++ b/src/network/core/packet.h @@ -75,6 +75,7 @@ public: void PrepareToRead(); bool CanReadFromPacket (uint bytes_to_read); + bool CMCheckRead (uint bytes_to_read); // CityMaina needs check that doesn't close connections bool Recv_bool (); uint8 Recv_uint8 (); uint16 Recv_uint16(); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 7c5f0f571a..4f4ba84e05 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -908,7 +908,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) p->Recv_string(name, sizeof(name)); playas = (Owner)p->Recv_uint8(); client_lang = (NetworkLanguage)p->Recv_uint8(); - uint8 savegame_formats = p->CanReadFromPacket(1) ? p->Recv_uint8() : 23u /* assume non-modded has everything but zstd */; + uint8 savegame_formats = p->CMCheckRead(1) ? p->Recv_uint8() : 23u /* assume non-modded has everything but zstd */; if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST; @@ -917,6 +917,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) if (!preset) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); this->cm_preset = *preset; + DEBUG(sl, 2, "Using saveload preset '%s:%d' for client %d (mask %d)", this->cm_preset.format->name, (int)this->cm_preset.compression_level, (int)this->client_id, (int)savegame_formats); + /* join another company does not affect these values */ switch (playas) { case COMPANY_NEW_COMPANY: // New company diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 1e95d544cd..14ac722ae4 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -2514,11 +2514,10 @@ std::optional FindCompatibleSavePreset(const std::string &server_for */ uint8 GetAvailableLoadFormats() { - return 3; uint8 res = 0; for(auto &slf : _saveload_formats) { if (slf.init_load != nullptr) { - res &= (1 << slf.id); + res |= (1 << slf.id); } } return res; @@ -2859,6 +2858,8 @@ static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str); } + DEBUG(sl, 2, "Using saveload format '%s'", fmt->name); + _sl.lf = fmt->init_load(_sl.lf); _sl.reader = new ReadBuffer(_sl.lf); _next_offs = 0;