From e4a2d43a47aadf62e38771fa46ecb58950b5c55c Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 1 Nov 2008 21:18:36 +0300 Subject: [PATCH] Better check client inventory pos data received in some client packets to skip invalid cases. --- src/game/ItemHandler.cpp | 42 +++++++++++++++++++++++ src/game/Level2.cpp | 6 ++++ src/game/Player.cpp | 72 ++++++++++++++++++++++++++++++++++++++++ src/game/Player.h | 2 ++ 4 files changed, 122 insertions(+) diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 3a6083b0d..f76e4ad2e 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -47,6 +47,18 @@ void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data ) if (count==0) return; //check count - if zero it's fake packet + if(!_player->IsValidPos(srcbag,srcslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if(!_player->IsValidPos(dstbag,dstslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + _player->SplitItem( src, dst, count ); } @@ -64,6 +76,18 @@ void WorldSession::HandleSwapInvItemOpcode( WorldPacket & recv_data ) if(srcslot==dstslot) return; + if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + uint16 src = ( (INVENTORY_SLOT_BAG_0 << 8) | srcslot ); uint16 dst = ( (INVENTORY_SLOT_BAG_0 << 8) | dstslot ); @@ -107,6 +131,18 @@ void WorldSession::HandleSwapItem( WorldPacket & recv_data ) if(src==dst) return; + if(!_player->IsValidPos(srcbag,srcslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if(!_player->IsValidPos(dstbag,dstslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + _player->SwapItem( src, dst ); } @@ -751,6 +787,12 @@ void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data ) if( !pItem ) return; + if(!_player->IsValidPos(dstbag,NULL_SLOT)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + uint16 src = pItem->GetPos(); // check unequip potability for equipped items and bank bags diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 7ffe2bcae..e120e3fca 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -862,6 +862,12 @@ bool ChatHandler::HandleItemMoveCommand(const char* args) if(srcslot==dstslot) return true; + if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + return false; + + if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + return false; + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 96d0464cd..324573aba 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -8323,6 +8323,78 @@ bool Player::IsBagPos( uint16 pos ) return false; } +bool Player::IsValidPos( uint8 bag, uint8 slot ) +{ + // post selected + if(bag == NULL_BAG) + return true; + + if (bag == INVENTORY_SLOT_BAG_0) + { + // any post selected + if (slot == NULL_SLOT) + return true; + + // equipment + if (slot < EQUIPMENT_SLOT_END) + return true; + + // bag equip slots + if (slot >= INVENTORY_SLOT_BAG_START && slot < INVENTORY_SLOT_BAG_END) + return true; + + // backpack slots + if (slot >= INVENTORY_SLOT_ITEM_START && slot < INVENTORY_SLOT_ITEM_END) + return true; + + // keyring slots + if (slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END) + return true; + + // bank main slots + if (slot >= BANK_SLOT_ITEM_START && slot < BANK_SLOT_ITEM_END) + return true; + + // bank bag slots + if (slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END) + return true; + + return false; + } + + // bag content slots + if (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END) + { + Bag* pBag = (Bag*)GetItemByPos (INVENTORY_SLOT_BAG_0, bag); + if(!pBag) + return false; + + // any post selected + if (slot == NULL_SLOT) + return true; + + return slot < pBag->GetBagSize(); + } + + // bank bag content slots + if( bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END ) + { + Bag* pBag = (Bag*)GetItemByPos (INVENTORY_SLOT_BAG_0, bag); + if(!pBag) + return false; + + // any post selected + if (slot == NULL_SLOT) + return true; + + return slot < pBag->GetBagSize(); + } + + // where this? + return false; +} + + bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const { uint32 tempcount = 0; diff --git a/src/game/Player.h b/src/game/Player.h index 09462b537..50b464293 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1063,6 +1063,8 @@ class MANGOS_DLL_SPEC Player : public Unit static bool IsBagPos( uint16 pos ); static bool IsBankPos( uint16 pos ) { return IsBankPos(pos >> 8,pos & 255); } static bool IsBankPos( uint8 bag, uint8 slot ); + bool IsValidPos( uint16 pos ) { return IsBankPos(pos >> 8,pos & 255); } + bool IsValidPos( uint8 bag, uint8 slot ); bool HasBankBagSlot( uint8 slot ) const; bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const; bool HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem = NULL);