aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-05-22 23:17:01 +0200
committerShauren <shauren.trinity@gmail.com>2025-05-22 23:17:01 +0200
commit5bebf0520968665af288d1d3619f1c42a7322ccb (patch)
tree26db7a76b581566ced3da9517701bee1ec3d0d40 /src
parentfde4ba92f6540df1b9e4c3b9722c9341ed9febed (diff)
Core/PacketIO: Mark packet parsing exception throwing code paths as [[noreturn]]
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Server/Packets/AuctionHousePackets.cpp2
-rw-r--r--src/server/game/Server/Packets/BattlenetPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/ClientConfigPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/HotfixPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/ItemPacketsCommon.cpp2
-rw-r--r--src/server/game/Server/Packets/PacketUtilities.cpp5
-rw-r--r--src/server/game/Server/Packets/PacketUtilities.h10
-rw-r--r--src/server/game/Server/Packets/QueryPackets.cpp3
-rw-r--r--src/server/game/Server/Packets/QuestPackets.cpp3
-rw-r--r--src/server/game/Server/Packets/TraitPacketsCommon.cpp6
-rw-r--r--src/server/game/Server/Packets/WardenPackets.cpp4
-rw-r--r--src/server/shared/Packets/ByteBuffer.cpp5
-rw-r--r--src/server/shared/Packets/ByteBuffer.h23
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;