diff --git a/src/game/AuctionHouseHandler.cpp b/src/game/AuctionHouseHandler.cpp index d1ccc19f3..80b3dee84 100644 --- a/src/game/AuctionHouseHandler.cpp +++ b/src/game/AuctionHouseHandler.cpp @@ -576,6 +576,8 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory; recv_data >> quality >> usable; + recv_data.read_skip(16); // unknown 16 bytes: 00 07 01 00 00 01 05 00 06 00 09 01 08 00 03 00 + Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { @@ -618,7 +620,8 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) void WorldSession::HandleAuctionListPendingSales( WorldPacket & recv_data ) { sLog.outDebug("CMSG_AUCTION_LIST_PENDING_SALES"); - recv_data.hexlike(); + + recv_data.read_skip(); // auctioner guid uint32 count = 0; diff --git a/src/game/CalendarHandler.cpp b/src/game/CalendarHandler.cpp index b7a7ca6a4..944197dee 100644 --- a/src/game/CalendarHandler.cpp +++ b/src/game/CalendarHandler.cpp @@ -96,6 +96,7 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_ADD_EVENT"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //std::string unk1, unk2; //recv_data >> (std::string)unk1; @@ -131,6 +132,7 @@ void WorldSession::HandleCalendarUpdateEvent(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_UPDATE_EVENT"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 @@ -149,6 +151,7 @@ void WorldSession::HandleCalendarRemoveEvent(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_REMOVE_EVENT"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 @@ -160,6 +163,7 @@ void WorldSession::HandleCalendarCopyEvent(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_COPY_EVENT"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 @@ -171,6 +175,7 @@ void WorldSession::HandleCalendarEventInvite(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_INVITE"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 @@ -184,6 +189,7 @@ void WorldSession::HandleCalendarEventRsvp(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_RSVP"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 @@ -195,6 +201,7 @@ void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_REMOVE_INVITE"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data.readPackGUID(guid) //recv_data >> uint64 @@ -206,6 +213,7 @@ void WorldSession::HandleCalendarEventStatus(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_STATUS"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data.readPackGUID(guid) //recv_data >> uint64 @@ -218,6 +226,7 @@ void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_MODERATOR_STATUS"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data.readPackGUID(guid) //recv_data >> uint64 @@ -230,6 +239,7 @@ void WorldSession::HandleCalendarComplain(WorldPacket &recv_data) { sLog.outDebug("WORLD: CMSG_CALENDAR_COMPLAIN"); recv_data.hexlike(); + recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam //recv_data >> uint64 //recv_data >> uint64 diff --git a/src/game/GMTicketHandler.cpp b/src/game/GMTicketHandler.cpp index b046a69c8..ffdfae504 100644 --- a/src/game/GMTicketHandler.cpp +++ b/src/game/GMTicketHandler.cpp @@ -84,15 +84,15 @@ void WorldSession::HandleGMTicketCreateOpcode( WorldPacket & recv_data ) uint32 map; float x, y, z; std::string ticketText = ""; - uint32 unk1, unk2; recv_data >> map >> x >> y >> z; // last check 2.4.3 recv_data >> ticketText; - recv_data >> unk1 >> unk2; - // note: the packet might contain more data, but the exact structure of that is unknown + recv_data.read_skip(); // unk1, 0 + recv_data.read_skip(); // unk2, 1 + recv_data.read_skip(); // unk3, 0 - sLog.outDebug("TicketCreate: map %u, x %f, y %f, z %f, text %s, unk1 %u, unk2 %u", map, x, y, z, ticketText.c_str(), unk1, unk2); + sLog.outDebug("TicketCreate: map %u, x %f, y %f, z %f, text %s", map, x, y, z, ticketText.c_str()); if(ticketmgr.GetGMTicket(GetPlayer()->GetGUIDLow())) { diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index b950a80eb..393b8a08f 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -614,12 +614,14 @@ void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket) guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if(!guild) { + recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); return; } else if(GetPlayer()->GetGUID() != guild->GetLeader()) { + recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); return; } @@ -1026,9 +1028,14 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data ) uint64 GoGuid; uint8 BankToBank; - uint8 BankTab, BankTabSlot, AutoStore, AutoStoreCount, PlayerSlot, PlayerBag, SplitedAmount = 0; - uint8 BankTabDst, BankTabSlotDst, unk2, ToChar = 1; + uint8 BankTab, BankTabSlot, AutoStore; + uint8 PlayerSlot = NULL_SLOT; + uint8 PlayerBag = NULL_BAG; + uint8 BankTabDst, BankTabSlotDst, unk2; + uint8 ToChar = 1; uint32 ItemEntry, unk1; + uint32 AutoStoreCount = 0; + uint32 SplitedAmount = 0; recv_data >> GoGuid >> BankToBank; if (BankToBank) @@ -1042,10 +1049,11 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data ) recv_data >> unk2; // always 0 recv_data >> SplitedAmount; - if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS) - return; - if (BankTabDst == BankTab && BankTabSlotDst == BankTabSlot) + if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS || BankTabDst == BankTab && BankTabSlotDst == BankTabSlot) + { + recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet return; + } } else { @@ -1056,17 +1064,22 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data ) if (AutoStore) { recv_data >> AutoStoreCount; + recv_data.read_skip(); // ToChar (?), always and expected to be 1 (autostore only triggered in guild->ToChar) + recv_data.read_skip(); // unknown, always 0 } - recv_data >> PlayerBag; - recv_data >> PlayerSlot; - if (!AutoStore) + else { + recv_data >> PlayerBag; + recv_data >> PlayerSlot; recv_data >> ToChar; recv_data >> SplitedAmount; } if (BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF) + { + recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet return; + } } if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK)) @@ -1201,14 +1214,6 @@ void WorldSession::HandleGuildBankSwapItems( WorldPacket & recv_data ) // Player <-> Bank - // char->bank autostore click return BankTabSlot = 255 = NULL_SLOT - // do similar for bank->char - if(AutoStore && ToChar) - { - PlayerBag = NULL_BAG; - PlayerSlot = NULL_SLOT; - } - // allow work with inventory only if(!Player::IsInventoryPos(PlayerBag,PlayerSlot) && !(PlayerBag == NULL_BAG && PlayerSlot == NULL_SLOT) ) { diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 3de5a326f..c5635225f 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -30,7 +30,8 @@ void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data ) { //sLog.outDebug("WORLD: CMSG_SPLIT_ITEM"); - uint8 srcbag, srcslot, dstbag, dstslot, count; + uint8 srcbag, srcslot, dstbag, dstslot; + uint32 count; recv_data >> srcbag >> srcslot >> dstbag >> dstslot >> count; //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u, dstbag = %u, dstslot = %u, count = %u", srcbag, srcslot, dstbag, dstslot, count); @@ -488,12 +489,9 @@ void WorldSession::HandleSellItemOpcode( WorldPacket & recv_data ) { sLog.outDebug( "WORLD: Received CMSG_SELL_ITEM" ); uint64 vendorguid, itemguid; - uint8 _count; + uint32 count; - recv_data >> vendorguid >> itemguid >> _count; - - // prevent possible overflow, as mangos uses uint32 for item count - uint32 count = _count; + recv_data >> vendorguid >> itemguid >> count; if(!itemguid) return; @@ -969,6 +967,8 @@ void WorldSession::HandleItemNameQueryOpcode(WorldPacket & recv_data) { uint32 itemid; recv_data >> itemid; + recv_data.read_skip(); // guid + sLog.outDebug("WORLD: CMSG_ITEM_NAME_QUERY %u", itemid); ItemPrototype const *pProto = objmgr.GetItemPrototype( itemid ); if( pProto ) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 46a892c2c..7da6fbad3 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -878,6 +878,7 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) if(decompressedSize > 0xFFFF) { + recv_data.rpos(recv_data.wpos()); // unnneded warning spam in this case sLog.outError("UAD: Account data packet too big, size %u", decompressedSize); return; } @@ -888,10 +889,13 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) uLongf realSize = decompressedSize; if(uncompress(const_cast(dest.contents()), &realSize, const_cast(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK) { + recv_data.rpos(recv_data.wpos()); // unnneded warning spam in this case sLog.outError("UAD: Failed to decompress account data"); return; } + recv_data.rpos(recv_data.wpos()); // uncompress read (recv_data.size() - recv_data.rpos()) + std::string adata; dest >> adata; @@ -997,7 +1001,8 @@ void WorldSession::HandleMoveTimeSkippedOpcode( WorldPacket & recv_data ) /* WorldSession::Update( getMSTime() );*/ DEBUG_LOG( "WORLD: Time Lag/Synchronization Resent/Update" ); - recv_data.read_skip2(); + recv_data.read_skip(); + recv_data.read_skip(); /* uint64 guid; uint32 time_skipped; diff --git a/src/game/VoiceChatHandler.cpp b/src/game/VoiceChatHandler.cpp index 3fc23ffcf..b799f0a18 100644 --- a/src/game/VoiceChatHandler.cpp +++ b/src/game/VoiceChatHandler.cpp @@ -26,7 +26,8 @@ void WorldSession::HandleVoiceSessionEnableOpcode( WorldPacket & recv_data ) { sLog.outDebug("WORLD: CMSG_VOICE_SESSION_ENABLE"); // uint8 isVoiceEnabled, uint8 isMicrophoneEnabled - recv_data.read_skip2(); + recv_data.read_skip(); + recv_data.read_skip(); recv_data.hexlike(); } diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 85ba69609..b6c0d3563 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -141,7 +141,7 @@ void WorldSession::QueuePacket(WorldPacket* new_packet) } /// Logging helper for unexpected opcodes -void WorldSession::logUnexpectedOpcode(WorldPacket* packet, const char *reason) +void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char *reason) { sLog.outError( "SESSION: received unexpected opcode %s (0x%.4X) %s", LookupOpcodeName(packet->GetOpcode()), @@ -149,6 +149,15 @@ void WorldSession::logUnexpectedOpcode(WorldPacket* packet, const char *reason) reason); } +/// Logging helper for unexpected opcodes +void WorldSession::LogUnprocessedTail(WorldPacket *packet) +{ + sLog.outError( "SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)", + LookupOpcodeName(packet->GetOpcode()), + packet->GetOpcode(), + packet->rpos(),packet->wpos()); +} + /// Update the WorldSession (triggered by World update) bool WorldSession::Update(uint32 /*diff*/) { @@ -182,30 +191,40 @@ bool WorldSession::Update(uint32 /*diff*/) { // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets if(!m_playerRecentlyLogout) - logUnexpectedOpcode(packet, "the player has not logged in yet"); + LogUnexpectedOpcode(packet, "the player has not logged in yet"); } else if(_player->IsInWorld()) + { (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + } // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer break; case STATUS_TRANSFER: if(!_player) - logUnexpectedOpcode(packet, "the player has not logged in yet"); + LogUnexpectedOpcode(packet, "the player has not logged in yet"); else if(_player->IsInWorld()) - logUnexpectedOpcode(packet, "the player is still in world"); + LogUnexpectedOpcode(packet, "the player is still in world"); else + { (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); + } break; case STATUS_AUTHED: // prevent cheating with skip queue wait if(m_inQueue) { - logUnexpectedOpcode(packet, "the player not pass queue yet"); + LogUnexpectedOpcode(packet, "the player not pass queue yet"); break; } m_playerRecentlyLogout = false; (this->*opHandle.handler)(*packet); + if (sLog.IsOutDebug() && packet->rpos() < packet->wpos()) + LogUnprocessedTail(packet); break; case STATUS_NEVER: sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)", @@ -214,7 +233,7 @@ bool WorldSession::Update(uint32 /*diff*/) break; } } - catch(ByteBufferException &exception) + catch(ByteBufferException &) { sLog.outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 4b963b75a..e2aa4aa33 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -714,7 +714,8 @@ class MANGOS_DLL_SPEC WorldSession void moveItems(Item* myItems[], Item* hisItems[]); // logging helper - void logUnexpectedOpcode(WorldPacket *packet, const char * reason); + void LogUnexpectedOpcode(WorldPacket *packet, const char * reason); + void LogUnprocessedTail(WorldPacket *packet); Player *_player; WorldSocket *m_Socket; diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index b2af3aa0d..560da60e1 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -732,7 +732,7 @@ int WorldSocket::ProcessIncoming (WorldPacket* new_pct) } } } - catch(ByteBufferException &exception) + catch(ByteBufferException &) { sLog.outError("WorldSocket::ProcessIncoming ByteBufferException occured while parsing an instant handled packet (opcode: %u) from client %s, accountid=%i. Disconnected client.", opcode, GetRemoteAddress().c_str(), m_Session?m_Session->GetAccountId():-1); diff --git a/src/shared/ByteBuffer.h b/src/shared/ByteBuffer.h index 373d28c23..b40539402 100644 --- a/src/shared/ByteBuffer.h +++ b/src/shared/ByteBuffer.h @@ -263,9 +263,6 @@ class ByteBuffer template void read_skip() { read_skip(sizeof(T)); } - template - void read_skip2() { read_skip(sizeof(T1)+sizeof(T2)); } - void read_skip(size_t skip) { if(_rpos + skip > size()) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 547a90e49..c428f9f73 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8388" + #define REVISION_NR "8389" #endif // __REVISION_NR_H__