diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 85d5d15ee..a93cd492a 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -918,6 +918,12 @@ namespace { return; } + // Still starting (asked for right after it was created): answered when its world server is ready + if (!instance->GetIsReady()) { + instance->GetPendingRequests().push_back({ requestID, static_cast(mythranShift), sysAddr, {} }); + return; + } + const auto& zone = instance->GetZoneID(); RequestZoneTransferResponse response; diff --git a/dNet/MasterPackets.cpp b/dNet/MasterPackets.cpp index 42279ac7d..0d18dce19 100644 --- a/dNet/MasterPackets.cpp +++ b/dNet/MasterPackets.cpp @@ -16,7 +16,12 @@ namespace { uint32_t length{}; VALIDATE_READ(bitStream.Read(length)); value.resize(std::min(length, maxLength)); - return value.empty() || bitStream.ReadBits(reinterpret_cast(value.data()), BYTES_TO_BITS(value.size()), true); + if (!value.empty() && !bitStream.ReadBits(reinterpret_cast(value.data()), BYTES_TO_BITS(value.size()), true)) return false; + const uint32_t rest = length - static_cast(value.size()); + if (rest == 0) return true; + if (BITS_TO_BYTES(bitStream.GetNumberOfUnreadBits()) < rest) return false; + bitStream.IgnoreBits(BYTES_TO_BITS(rest)); + return true; } } diff --git a/tests/dGameTests/dNetTests/MasterPacketsTests.cpp b/tests/dGameTests/dNetTests/MasterPacketsTests.cpp index 6ddcdb6b0..a732e3861 100644 --- a/tests/dGameTests/dNetTests/MasterPacketsTests.cpp +++ b/tests/dGameTests/dNetTests/MasterPacketsTests.cpp @@ -720,3 +720,20 @@ TEST(MasterPacketsTests, ServerListWithoutOutdatedFlags) { ASSERT_TRUE(withFlag.Deserialize(again)); EXPECT_EQ(withFlag.instances[0].outdated, 1); } + +// A password longer than master keeps is cut, and the characters cut are skipped: nothing of it is left to be read +// as what follows +TEST(MasterPacketsTests, CappedPasswordSkipsWhatItCut) { + for (const auto& password : g_Strings) { + MasterPackets::CreatePrivateZone sent; + sent.zoneID = 1100; + sent.cloneID = 7; + sent.password = password; + RakNet::BitStream stream; + LoadPayload(stream, sent); + MasterPackets::CreatePrivateZone read; + ASSERT_TRUE(read.Deserialize(stream)); + EXPECT_EQ(read.password, password.substr(0, MasterPackets::CreatePrivateZone::MAX_PASSWORD_LENGTH)); + EXPECT_EQ(stream.GetNumberOfUnreadBits(), 0u); + } +}