diff options
| author | Shauren <shauren.trinity@gmail.com> | 2015-07-29 00:04:37 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2015-07-29 00:04:37 +0200 |
| commit | 3604025bb7e1e1e7803a44b0f13931b88fcd26ac (patch) | |
| tree | fac7e151b4f4b2982cf6e7393e61fea44c69195d /src/server/game/Server/Packets | |
| parent | 0ada9ae513506fc0dc0c1729b9e385857401514f (diff) | |
Core/PacketIO: Added utility packet array class to handle loop counter limiting in packets received from the client
Diffstat (limited to 'src/server/game/Server/Packets')
7 files changed, 126 insertions, 52 deletions
diff --git a/src/server/game/Server/Packets/CalendarPackets.cpp b/src/server/game/Server/Packets/CalendarPackets.cpp index 655d33da73d..ca80093ba00 100644 --- a/src/server/game/Server/Packets/CalendarPackets.cpp +++ b/src/server/game/Server/Packets/CalendarPackets.cpp @@ -97,30 +97,37 @@ void WorldPackets::Calendar::CalendarGuildFilter::Read() _worldPacket >> MaxRankOrder; } -void WorldPackets::Calendar::CalendarAddEvent::Read() +ByteBuffer& operator>>(ByteBuffer& buffer, WorldPackets::Calendar::CalendarAddEventInviteInfo& invite) { - uint8 titleLength = _worldPacket.ReadBits(8); - uint16 descriptionLength = _worldPacket.ReadBits(11); + buffer >> invite.Guid; + buffer >> invite.Status; + buffer >> invite.Moderator; + return buffer; +} - _worldPacket >> EventInfo.EventType; - _worldPacket >> EventInfo.TextureID; - EventInfo.Time = _worldPacket.ReadPackedTime(); - _worldPacket >> EventInfo.Flags; - uint32 count = _worldPacket.read<uint32>(); +ByteBuffer& operator>>(ByteBuffer& buffer, WorldPackets::Calendar::CalendarAddEventInfo& addEventInfo) +{ + uint8 titleLength = buffer.ReadBits(8); + uint16 descriptionLength = buffer.ReadBits(11); - EventInfo.Title = _worldPacket.ReadString(titleLength); - EventInfo.Description = _worldPacket.ReadString(descriptionLength); + buffer >> addEventInfo.EventType; + buffer >> addEventInfo.TextureID; + addEventInfo.Time = buffer.ReadPackedTime(); + buffer >> addEventInfo.Flags; + addEventInfo.Invites.resize(buffer.read<uint32>()); - for (uint32 i = 0; i < count && i < CALENDAR_MAX_INVITES; i++) - { - WorldPackets::Calendar::CalendarAddEventInviteInfo invite; - _worldPacket >> invite.Guid; - _worldPacket >> invite.Status; - _worldPacket >> invite.Moderator; + addEventInfo.Title = buffer.ReadString(titleLength); + addEventInfo.Description = buffer.ReadString(descriptionLength); - EventInfo.Invites.push_back(invite); - } + for (WorldPackets::Calendar::CalendarAddEventInviteInfo& invite : addEventInfo.Invites) + buffer >> invite; + + return buffer; +} +void WorldPackets::Calendar::CalendarAddEvent::Read() +{ + _worldPacket >> EventInfo; _worldPacket >> MaxSize; } diff --git a/src/server/game/Server/Packets/CalendarPackets.h b/src/server/game/Server/Packets/CalendarPackets.h index 023041d427f..d753113e816 100644 --- a/src/server/game/Server/Packets/CalendarPackets.h +++ b/src/server/game/Server/Packets/CalendarPackets.h @@ -14,28 +14,14 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ #ifndef CalendarPackets_h__ #define CalendarPackets_h__ #include "ObjectGuid.h" #include "Packet.h" +#include "PacketUtilities.h" +#include "CalendarMgr.h" namespace WorldPackets { @@ -86,7 +72,7 @@ namespace WorldPackets int32 TextureID = 0; time_t Time = time_t(0); uint32 Flags = 0; - std::vector<CalendarAddEventInviteInfo> Invites; + Array<CalendarAddEventInviteInfo, CALENDAR_MAX_INVITES> Invites; }; class CalendarAddEvent final : public ClientPacket diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp index 9c6bb07f56e..afeb3e2a6b6 100644 --- a/src/server/game/Server/Packets/CharacterPackets.cpp +++ b/src/server/game/Server/Packets/CharacterPackets.cpp @@ -316,10 +316,15 @@ WorldPacket const* WorldPackets::Character::GenerateRandomCharacterNameResult::W return &_worldPacket; } +WorldPackets::Character::ReorderCharacters::ReorderCharacters(WorldPacket&& packet) : ClientPacket(CMSG_REORDER_CHARACTERS, std::move(packet)), + Entries(sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM)) +{ + +} + void WorldPackets::Character::ReorderCharacters::Read() { - uint32 count = std::min<uint32>(_worldPacket.ReadBits(9), sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM)); - Entries.resize(count); + Entries.resize(_worldPacket.ReadBits(9)); for (ReorderInfo& reorderInfo : Entries) { _worldPacket >> reorderInfo.PlayerGUID; diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h index 10f1053f8ee..018564350b0 100644 --- a/src/server/game/Server/Packets/CharacterPackets.h +++ b/src/server/game/Server/Packets/CharacterPackets.h @@ -20,6 +20,7 @@ #include "Packet.h" #include "Player.h" +#include "PacketUtilities.h" namespace WorldPackets { @@ -351,11 +352,11 @@ namespace WorldPackets uint8 NewPosition = 0; }; - ReorderCharacters(WorldPacket&& packet) : ClientPacket(CMSG_REORDER_CHARACTERS, std::move(packet)) { } + ReorderCharacters(WorldPacket&& packet); void Read() override; - std::list<ReorderInfo> Entries; + Array<ReorderInfo> Entries; }; class UndeleteCharacter final : public ClientPacket diff --git a/src/server/game/Server/Packets/PacketUtilities.h b/src/server/game/Server/Packets/PacketUtilities.h index f92d949d1be..d620938194c 100644 --- a/src/server/game/Server/Packets/PacketUtilities.h +++ b/src/server/game/Server/Packets/PacketUtilities.h @@ -21,6 +21,7 @@ #include "ByteBuffer.h" #include <G3D/Vector2.h> #include <G3D/Vector3.h> +#include <sstream> inline ByteBuffer& operator<<(ByteBuffer& data, G3D::Vector2 const& v) { @@ -48,6 +49,85 @@ inline ByteBuffer& operator>>(ByteBuffer& data, G3D::Vector3& v) namespace WorldPackets { + class PacketArrayMaxCapacityException : public ByteBufferException + { + public: + PacketArrayMaxCapacityException(std::size_t requestedSize, std::size_t sizeLimit) + { + std::ostringstream builder; + builder << "Attempted to read more array elements from packet " << requestedSize << " than allowed " << sizeLimit; + message().assign(builder.str()); + } + }; + + /** + * Utility class for automated prevention of loop counter spoofing in client packets + */ + template<typename T, std::size_t N = 1000 /*select a sane default limit*/> + class Array + { + typedef std::vector<T> storage_type; + + typedef typename storage_type::value_type value_type; + typedef typename storage_type::size_type size_type; + typedef typename storage_type::reference reference; + typedef typename storage_type::const_reference const_reference; + typedef typename storage_type::iterator iterator; + typedef typename storage_type::const_iterator const_iterator; + + public: + Array() : _limit(N) { } + Array(size_type limit) : _limit(limit) { } + + iterator begin() { return _storage.begin(); } + const_iterator begin() const { return _storage.begin(); } + + iterator end() { return _storage.end(); } + const_iterator end() const { return _storage.end(); } + + size_type size() const { return _storage.size(); } + bool empty() const { return _storage.empty(); } + + reference operator[](size_type i) { return _storage[i]; } + const_reference operator[](size_type i) const { return _storage[i]; } + + void resize(size_type newSize) + { + if (newSize > _limit) + throw PacketArrayMaxCapacityException(newSize, _limit); + + _storage.resize(newSize); + } + + void reserve(size_type newSize) + { + if (newSize > _limit) + throw PacketArrayMaxCapacityException(newSize, _limit); + + _storage.reserve(newSize); + } + + void push_back(value_type const& value) + { + if (_storage.size() >= _limit) + throw PacketArrayMaxCapacityException(newSize, _limit); + + _storage.push_back(value); + } + + void push_back(value_type&& value) + { + if (_storage.size() >= _limit) + throw PacketArrayMaxCapacityException(newSize, _limit); + + _storage.push_back(std::forward<value_type>(value)); + } + + private: + storage_type _storage; + size_type _limit; + }; + template <typename T> class CompactArray { diff --git a/src/server/game/Server/Packets/VoidStoragePackets.cpp b/src/server/game/Server/Packets/VoidStoragePackets.cpp index a635d57666d..43a1f070d8d 100644 --- a/src/server/game/Server/Packets/VoidStoragePackets.cpp +++ b/src/server/game/Server/Packets/VoidStoragePackets.cpp @@ -65,17 +65,14 @@ WorldPacket const* WorldPackets::VoidStorage::VoidStorageContents::Write() void WorldPackets::VoidStorage::VoidStorageTransfer::Read() { _worldPacket >> Npc; - _worldPacket >> DepositsCount; - _worldPacket >> WithdrawalsCount; + Deposits.resize(_worldPacket.read<uint32>()); + Withdrawals.resize(_worldPacket.read<uint32>()); - if (WithdrawalsCount > VOID_STORAGE_MAX_WITHDRAW || DepositsCount > VOID_STORAGE_MAX_DEPOSIT) - return; + for (ObjectGuid& deposit : Deposits) + _worldPacket >> deposit; - for (uint32 i = 0; i < DepositsCount; ++i) - _worldPacket >> Deposits[i]; - - for (uint32 i = 0; i < WithdrawalsCount; ++i) - _worldPacket >> Withdrawals[i]; + for (ObjectGuid& withdrawal : Withdrawals) + _worldPacket >> withdrawal; } WorldPacket const* WorldPackets::VoidStorage::VoidStorageTransferChanges::Write() diff --git a/src/server/game/Server/Packets/VoidStoragePackets.h b/src/server/game/Server/Packets/VoidStoragePackets.h index 9790b328e72..b84f0cf2678 100644 --- a/src/server/game/Server/Packets/VoidStoragePackets.h +++ b/src/server/game/Server/Packets/VoidStoragePackets.h @@ -90,10 +90,8 @@ namespace WorldPackets void Read() override; - std::array<ObjectGuid, VOID_STORAGE_MAX_WITHDRAW> Withdrawals; - uint32 WithdrawalsCount = 0; - std::array<ObjectGuid, VOID_STORAGE_MAX_DEPOSIT> Deposits; - uint32 DepositsCount = 0; + Array<ObjectGuid, VOID_STORAGE_MAX_WITHDRAW> Withdrawals; + Array<ObjectGuid, VOID_STORAGE_MAX_DEPOSIT> Deposits; ObjectGuid Npc; }; |
