diff options
author | Shauren <shauren.trinity@gmail.com> | 2025-05-22 23:17:01 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2025-05-22 23:17:01 +0200 |
commit | 5bebf0520968665af288d1d3619f1c42a7322ccb (patch) | |
tree | 26db7a76b581566ced3da9517701bee1ec3d0d40 /src | |
parent | fde4ba92f6540df1b9e4c3b9722c9341ed9febed (diff) |
Core/PacketIO: Mark packet parsing exception throwing code paths as [[noreturn]]
Diffstat (limited to 'src')
13 files changed, 48 insertions, 21 deletions
diff --git a/src/server/game/Server/Packets/AuctionHousePackets.cpp b/src/server/game/Server/Packets/AuctionHousePackets.cpp index 399cdc40e12..0becd9e5f9c 100644 --- a/src/server/game/Server/Packets/AuctionHousePackets.cpp +++ b/src/server/game/Server/Packets/AuctionHousePackets.cpp @@ -282,7 +282,7 @@ void AuctionBrowseQuery::Read() uint32 knownPetsSize = _worldPacket.read<uint32>(); uint32 const sizeLimit = sBattlePetSpeciesStore.GetNumRows() / (sizeof(decltype(KnownPets)::value_type) * 8) + 1; if (knownPetsSize >= sizeLimit) - throw PacketArrayMaxCapacityException(knownPetsSize, sizeLimit); + OnInvalidArraySize(knownPetsSize, sizeLimit); KnownPets.resize(knownPetsSize); _worldPacket >> MaxPetLevel; diff --git a/src/server/game/Server/Packets/BattlenetPackets.cpp b/src/server/game/Server/Packets/BattlenetPackets.cpp index 278ebcad175..f3080ffc119 100644 --- a/src/server/game/Server/Packets/BattlenetPackets.cpp +++ b/src/server/game/Server/Packets/BattlenetPackets.cpp @@ -82,7 +82,7 @@ void Request::Read() _worldPacket >> protoSize; if (protoSize > 0xFFFF) - throw PacketArrayMaxCapacityException(protoSize, 0xFFFF); + OnInvalidArraySize(protoSize, 0xFFFF); if (protoSize) { diff --git a/src/server/game/Server/Packets/ClientConfigPackets.cpp b/src/server/game/Server/Packets/ClientConfigPackets.cpp index 06de1098f4d..9eda3e61332 100644 --- a/src/server/game/Server/Packets/ClientConfigPackets.cpp +++ b/src/server/game/Server/Packets/ClientConfigPackets.cpp @@ -66,7 +66,7 @@ void UserClientUpdateAccountData::Read() std::size_t pos = _worldPacket.rpos(); std::size_t remainingSize = _worldPacket.size() - pos; if (compressedSize > remainingSize) - throw ByteBufferPositionException(_worldPacket.rpos(), _worldPacket.size(), compressedSize); + OnInvalidArraySize(compressedSize, remainingSize); CompressedData = { _worldPacket.data() + pos, compressedSize }; _worldPacket.rpos(pos + compressedSize); diff --git a/src/server/game/Server/Packets/HotfixPackets.cpp b/src/server/game/Server/Packets/HotfixPackets.cpp index 4b1be2daad8..97125c65536 100644 --- a/src/server/game/Server/Packets/HotfixPackets.cpp +++ b/src/server/game/Server/Packets/HotfixPackets.cpp @@ -94,7 +94,7 @@ void HotfixRequest::Read() uint32 hotfixCount = _worldPacket.read<uint32>(); if (hotfixCount > sDB2Manager.GetHotfixCount()) - throw PacketArrayMaxCapacityException(hotfixCount, sDB2Manager.GetHotfixCount()); + OnInvalidArraySize(hotfixCount, sDB2Manager.GetHotfixCount()); Hotfixes.resize(hotfixCount); for (int32& hotfixId : Hotfixes) diff --git a/src/server/game/Server/Packets/ItemPacketsCommon.cpp b/src/server/game/Server/Packets/ItemPacketsCommon.cpp index 71463b5944f..3134436d02a 100644 --- a/src/server/game/Server/Packets/ItemPacketsCommon.cpp +++ b/src/server/game/Server/Packets/ItemPacketsCommon.cpp @@ -140,7 +140,7 @@ ByteBuffer& operator>>(ByteBuffer& data, ItemBonuses& itemBonusInstanceData) uint32 bonusListIdSize; data >> bonusListIdSize; if (bonusListIdSize > 32) - throw PacketArrayMaxCapacityException(bonusListIdSize, 32); + OnInvalidArraySize(bonusListIdSize, 32); itemBonusInstanceData.BonusListIDs.resize(bonusListIdSize); diff --git a/src/server/game/Server/Packets/PacketUtilities.cpp b/src/server/game/Server/Packets/PacketUtilities.cpp index 044a8c5113f..4227833e6b0 100644 --- a/src/server/game/Server/Packets/PacketUtilities.cpp +++ b/src/server/game/Server/Packets/PacketUtilities.cpp @@ -57,6 +57,11 @@ bool WorldPackets::Strings::NoHyperlinks::Validate(std::string_view value) return true; } +void WorldPackets::OnInvalidArraySize(std::size_t requestedSize, std::size_t sizeLimit) +{ + throw PacketArrayMaxCapacityException(requestedSize, sizeLimit); +} + WorldPackets::PacketArrayMaxCapacityException::PacketArrayMaxCapacityException(std::size_t requestedSize, std::size_t sizeLimit) : ByteBufferException(Trinity::StringFormat("Attempted to read more array elements from packet {} than allowed {}", requestedSize, sizeLimit)) { diff --git a/src/server/game/Server/Packets/PacketUtilities.h b/src/server/game/Server/Packets/PacketUtilities.h index 99c8ddaaac1..2917d2d8d25 100644 --- a/src/server/game/Server/Packets/PacketUtilities.h +++ b/src/server/game/Server/Packets/PacketUtilities.h @@ -153,6 +153,8 @@ namespace WorldPackets PacketArrayMaxCapacityException(std::size_t requestedSize, std::size_t sizeLimit); }; + [[noreturn]] void OnInvalidArraySize(std::size_t requestedSize, std::size_t sizeLimit); + /** * Utility class for automated prevention of loop counter spoofing in client packets */ @@ -200,6 +202,8 @@ namespace WorldPackets Array& operator=(Array&& other) noexcept = delete; + ~Array() = default; + iterator begin() { return _storage.begin(); } const_iterator begin() const { return _storage.begin(); } @@ -218,7 +222,7 @@ namespace WorldPackets void resize(size_type newSize) { if (newSize > max_capacity::value) - throw PacketArrayMaxCapacityException(newSize, max_capacity::value); + OnInvalidArraySize(newSize, max_capacity::value); _storage.resize(newSize); } @@ -226,7 +230,7 @@ namespace WorldPackets void push_back(value_type const& value) { if (_storage.size() >= max_capacity::value) - throw PacketArrayMaxCapacityException(_storage.size() + 1, max_capacity::value); + OnInvalidArraySize(_storage.size() + 1, max_capacity::value); _storage.push_back(value); } @@ -234,7 +238,7 @@ namespace WorldPackets void push_back(value_type&& value) { if (_storage.size() >= max_capacity::value) - throw PacketArrayMaxCapacityException(_storage.size() + 1, max_capacity::value); + OnInvalidArraySize(_storage.size() + 1, max_capacity::value); _storage.push_back(std::forward<value_type>(value)); } diff --git a/src/server/game/Server/Packets/QueryPackets.cpp b/src/server/game/Server/Packets/QueryPackets.cpp index 046bc7755c8..f34eb0ee001 100644 --- a/src/server/game/Server/Packets/QueryPackets.cpp +++ b/src/server/game/Server/Packets/QueryPackets.cpp @@ -398,6 +398,9 @@ void QuestPOIQuery::Read() { _worldPacket >> MissingQuestCount; + if (MissingQuestCount > std::ssize(MissingQuestPOIs)) + OnInvalidArraySize(MissingQuestCount, MissingQuestPOIs.size()); + for (std::size_t i = 0; i < MissingQuestPOIs.size(); ++i) _worldPacket >> MissingQuestPOIs[i]; } diff --git a/src/server/game/Server/Packets/QuestPackets.cpp b/src/server/game/Server/Packets/QuestPackets.cpp index 6143165f2d5..444dd65a6b5 100644 --- a/src/server/game/Server/Packets/QuestPackets.cpp +++ b/src/server/game/Server/Packets/QuestPackets.cpp @@ -889,6 +889,9 @@ ByteBuffer& operator>>(ByteBuffer& data, SpawnTrackingRequestInfo& spawnTracking void SpawnTrackingUpdate::Read() { uint32 requests = _worldPacket.read<uint32>(); + if (requests > 10000) + OnInvalidArraySize(requests, 10000); + SpawnTrackingRequests.resize(requests); for (SpawnTrackingRequestInfo& spawnTrackingRequestInfo : SpawnTrackingRequests) _worldPacket >> spawnTrackingRequestInfo; diff --git a/src/server/game/Server/Packets/TraitPacketsCommon.cpp b/src/server/game/Server/Packets/TraitPacketsCommon.cpp index aaacc02d53b..3b871552f2e 100644 --- a/src/server/game/Server/Packets/TraitPacketsCommon.cpp +++ b/src/server/game/Server/Packets/TraitPacketsCommon.cpp @@ -84,7 +84,7 @@ ByteBuffer& operator>>(ByteBuffer& data, TraitSubTreeCache& traitSubTreeCache) data >> traitSubTreeCache.TraitSubTreeID; uint32 entriesSize = data.read<uint32>(); if (entriesSize > 100) - throw PacketArrayMaxCapacityException(entriesSize, 100); + OnInvalidArraySize(entriesSize, 100); traitSubTreeCache.Entries.resize(entriesSize); for (TraitEntry& traitEntry : traitSubTreeCache.Entries) @@ -115,13 +115,13 @@ ByteBuffer& operator>>(ByteBuffer& data, TraitConfig& traitConfig) data >> As<int32>(traitConfig.Type); uint32 entriesSize = data.read<uint32>(); if (entriesSize > 100) - throw PacketArrayMaxCapacityException(entriesSize, 100); + OnInvalidArraySize(entriesSize, 100); traitConfig.Entries.resize(entriesSize); uint32 subtreesSize = data.read<uint32>(); if (subtreesSize > 10) - throw PacketArrayMaxCapacityException(subtreesSize, 10); + OnInvalidArraySize(subtreesSize, 10); traitConfig.SubTrees.resize(subtreesSize); diff --git a/src/server/game/Server/Packets/WardenPackets.cpp b/src/server/game/Server/Packets/WardenPackets.cpp index 1f092403be1..5f767660020 100644 --- a/src/server/game/Server/Packets/WardenPackets.cpp +++ b/src/server/game/Server/Packets/WardenPackets.cpp @@ -23,6 +23,10 @@ namespace WorldPackets::Warden void WardenData::Read() { uint32 requestedSize = _worldPacket.read<uint32>(); + std::size_t pos = _worldPacket.rpos(); + std::size_t remainingSize = _worldPacket.size() - pos; + if (requestedSize > remainingSize) + OnInvalidArraySize(requestedSize, remainingSize); Data.resize(requestedSize); _worldPacket.read(Data.data(), requestedSize); diff --git a/src/server/shared/Packets/ByteBuffer.cpp b/src/server/shared/Packets/ByteBuffer.cpp index 8811a2a6c0c..f49c36a1cc0 100644 --- a/src/server/shared/Packets/ByteBuffer.cpp +++ b/src/server/shared/Packets/ByteBuffer.cpp @@ -199,6 +199,11 @@ void ByteBuffer::hexlike() const sLog->OutMessageTo(networkLogger, "network", LOG_LEVEL_TRACE, "STORAGE_SIZE: {} {}", size(), o.view()); } +void ByteBuffer::OnInvalidPosition(size_t pos, size_t valueSize) const +{ + throw ByteBufferPositionException(pos, _storage.size(), valueSize); +} + template TC_SHARED_API uint8 ByteBuffer::read<uint8>(); template TC_SHARED_API uint16 ByteBuffer::read<uint16>(); template TC_SHARED_API uint32 ByteBuffer::read<uint32>(); diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 8f3e437f04f..f61a72f3664 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -442,15 +442,15 @@ class TC_SHARED_API ByteBuffer uint8& operator[](size_t const pos) { - if (pos >= size()) - throw ByteBufferPositionException(pos, 1, size()); + if (pos >= _storage.size()) + OnInvalidPosition(pos, 1); return _storage[pos]; } uint8 const& operator[](size_t const pos) const { - if (pos >= size()) - throw ByteBufferPositionException(pos, 1, size()); + if (pos >= _storage.size()) + OnInvalidPosition(pos, 1); return _storage[pos]; } @@ -490,8 +490,8 @@ class TC_SHARED_API ByteBuffer void read_skip(size_t skip) { - if (_rpos + skip > size()) - throw ByteBufferPositionException(_rpos, skip, size()); + if (_rpos + skip > _storage.size()) + OnInvalidPosition(_rpos, skip); ResetBitPos(); _rpos += skip; @@ -509,8 +509,9 @@ class TC_SHARED_API ByteBuffer template <typename T> T read(size_t pos) const { - if (pos + sizeof(T) > size()) - throw ByteBufferPositionException(pos, sizeof(T), size()); + if (pos + sizeof(T) > _storage.size()) + OnInvalidPosition(pos, sizeof(T)); + T val; std::memcpy(&val, &_storage[pos], sizeof(T)); EndianConvert(val); @@ -530,8 +531,8 @@ class TC_SHARED_API ByteBuffer void read(uint8* dest, size_t len) { - if (_rpos + len > size()) - throw ByteBufferPositionException(_rpos, len, size()); + if (_rpos + len > _storage.size()) + OnInvalidPosition(_rpos, len); ResetBitPos(); std::memcpy(dest, &_storage[_rpos], len); @@ -626,6 +627,8 @@ class TC_SHARED_API ByteBuffer void hexlike() const; protected: + [[noreturn]] void OnInvalidPosition(size_t pos, size_t valueSize) const; + size_t _rpos, _wpos; uint8 _bitpos; uint8 _curbitval; |