From bd0e8c774f935dc735667264694d95f1bded5389 Mon Sep 17 00:00:00 2001 From: H0zen Date: Tue, 29 Mar 2016 14:14:20 +0300 Subject: [PATCH] Fix warden crash for NYI builds --- src/game/Warden/WardenCheckMgr.cpp | 95 +++++++++++++----------------- src/game/Warden/WardenCheckMgr.h | 16 ++--- src/game/Warden/WardenWin.cpp | 44 +++++++------- 3 files changed, 69 insertions(+), 86 deletions(-) diff --git a/src/game/Warden/WardenCheckMgr.cpp b/src/game/Warden/WardenCheckMgr.cpp index 443074ba..50dba7d3 100644 --- a/src/game/Warden/WardenCheckMgr.cpp +++ b/src/game/Warden/WardenCheckMgr.cpp @@ -32,23 +32,15 @@ #include "WardenCheckMgr.h" #include "Warden.h" -WardenCheckMgr::WardenCheckMgr() { } +WardenCheckMgr::WardenCheckMgr() : m_lock(0), CheckStore(), CheckResultStore() { } WardenCheckMgr::~WardenCheckMgr() { for (CheckMap::iterator it = CheckStore.begin(); it != CheckStore.end(); ++it) - { - for (CheckContainer::iterator itr = it->second->begin(); itr != it->second->end(); ++itr) - delete itr->second; delete it->second; - } for (CheckResultMap::iterator it = CheckResultStore.begin(); it != CheckResultStore.end(); ++it) - { - for (CheckResultContainer::iterator itr = it->second->begin(); itr != it->second->end(); ++itr) - delete itr->second; delete it->second; - } } void WardenCheckMgr::LoadWardenChecks() @@ -60,7 +52,8 @@ void WardenCheckMgr::LoadWardenChecks() return; } - QueryResult *result = WorldDatabase.Query("SELECT DISTINCT build FROM warden"); + // 0 1 2 3 4 5 6 7 8 + QueryResult *result = WorldDatabase.Query("SELECT id, build, type, data, result, address, length, str, comment FROM warden ORDER BY build ASC, id ASC"); if (!result) { @@ -68,26 +61,8 @@ void WardenCheckMgr::LoadWardenChecks() return; } - Field* fields; - - do - { - fields = result->Fetch(); - uint16 build = fields[0].GetUInt16(); - CheckContainer* ck = new CheckContainer(); - CheckResultContainer* ckr = new CheckResultContainer(); - CheckStore[build] = ck; - CheckResultStore[build] = ckr; - - } while (result->NextRow()); - - delete result; - - // 0 1 2 3 4 5 6 7 8 - result = WorldDatabase.Query("SELECT id, build, type, data, result, address, length, str, comment FROM warden ORDER BY build ASC, id ASC"); - // no need to check. done in SELECT DISTINCT before - uint32 count = 0; + Field* fields; do { @@ -125,11 +100,6 @@ void WardenCheckMgr::LoadWardenChecks() } } - if (checkType == MEM_CHECK || checkType == MODULE_CHECK) - MemChecksIdPool.push_back(id); - else - OtherChecksIdPool.push_back(id); - if (checkType == MEM_CHECK || checkType == PAGE_CHECK_A || checkType == PAGE_CHECK_B || checkType == PROC_CHECK) { wardenCheck->Address = address; @@ -140,11 +110,12 @@ void WardenCheckMgr::LoadWardenChecks() if (checkType == MEM_CHECK || checkType == MPQ_CHECK || checkType == LUA_STR_CHECK || checkType == DRIVER_CHECK || checkType == MODULE_CHECK) wardenCheck->Str = str; - CheckStore[build]->insert(std::pair(id, wardenCheck)); + CheckStore.insert(std::pair(build, wardenCheck)); if (checkType == MPQ_CHECK || checkType == MEM_CHECK) { WardenCheckResult* wr = new WardenCheckResult(); + wr->Id = id; wr->Result.SetHexStr(checkResult.c_str()); int len = checkResult.size() / 2; if (wr->Result.GetNumBytes() < len) @@ -156,7 +127,7 @@ void WardenCheckMgr::LoadWardenChecks() wr->Result.SetBinary((uint8*)temp, len); delete[] temp; } - CheckResultStore[build]->insert(std::pair(id,wr)); + CheckResultStore.insert(std::pair(build, wr)); } if (comment.empty()) @@ -192,7 +163,7 @@ void WardenCheckMgr::LoadWardenOverrides() uint32 count = 0; - ACE_WRITE_GUARD(ACE_RW_Mutex, g, _checkStoreLock); + ACE_WRITE_GUARD(ACE_RW_Mutex, g, m_lock); do { @@ -204,21 +175,20 @@ void WardenCheckMgr::LoadWardenOverrides() // Check if action value is in range (0-2, see WardenActions enum) if (action > WARDEN_ACTION_BAN) sLog.outWarden("Warden check override action out of range (ID: %u, action: %u)", checkId, action); - - // Check if check actually exists before accessing the CheckStore vector else { + bool found = false; for (CheckMap::iterator it = CheckStore.begin(); it != CheckStore.end(); ++it) { - CheckContainer::iterator ir = it->second->find(checkId); - if (ir == it->second->end()) - sLog.outWarden("Warden check action override for non-existing check (ID: %u, action: %u), skipped", checkId, action); - else + if (it->second->CheckId == checkId) { - ir->second->Action = WardenActions(action); + it->second->Action = WardenActions(action); ++count; + found = true; } } + if (!found) + sLog.outWarden("Warden check action override for non-existing check (ID: %u, action: %u), skipped", checkId, action); } } while (result->NextRow()); @@ -229,12 +199,12 @@ void WardenCheckMgr::LoadWardenOverrides() WardenCheck* WardenCheckMgr::GetWardenDataById(uint16 build, uint16 id) { WardenCheck* result = NULL; - CheckMap::iterator it = CheckStore.find(build); - if (it != CheckStore.end()) + + ACE_READ_GUARD_RETURN(ACE_RW_Mutex, g, m_lock, result) + for (CheckMap::iterator it = CheckStore.lower_bound(build); it != CheckStore.upper_bound(build); ++it) { - CheckContainer::iterator ir = it->second->find(id); - if (ir != it->second->end()) - result = ir->second; + if (it->second->CheckId == id) + result = it->second; } return result; @@ -243,13 +213,30 @@ WardenCheck* WardenCheckMgr::GetWardenDataById(uint16 build, uint16 id) WardenCheckResult* WardenCheckMgr::GetWardenResultById(uint16 build, uint16 id) { WardenCheckResult* result = NULL; - CheckResultMap::iterator it = CheckResultStore.find(build); - if (it != CheckResultStore.end()) + + ACE_READ_GUARD_RETURN(ACE_RW_Mutex, g, m_lock, result) + for (CheckResultMap::iterator it = CheckResultStore.lower_bound(build); it != CheckResultStore.upper_bound(build); ++it) { - CheckResultContainer::iterator ir = it->second->find(id); - if (ir != it->second->end()) - result = ir->second; + if (it->second->Id == id) + result = it->second; } return result; } + +void WardenCheckMgr::GetWardenCheckIds(bool isMemCheck, uint16 build, std::list& idl) +{ + idl.clear(); //just to be sure + + ACE_READ_GUARD(ACE_RW_Mutex, g, m_lock); + for (CheckMap::iterator it = CheckStore.lower_bound(build); it != CheckStore.upper_bound(build); ++it) + { + if (isMemCheck) + { + if ((it->second->Type == MEM_CHECK) || (it->second->Type == MODULE_CHECK)) + idl.push_back(it->second->CheckId); + } + else + idl.push_back(it->second->CheckId); + } +} \ No newline at end of file diff --git a/src/game/Warden/WardenCheckMgr.h b/src/game/Warden/WardenCheckMgr.h index f9dc51fb..b5cf5e59 100644 --- a/src/game/Warden/WardenCheckMgr.h +++ b/src/game/Warden/WardenCheckMgr.h @@ -50,6 +50,7 @@ struct WardenCheck struct WardenCheckResult { + uint16 Id; BigNumber Result; // MEM_CHECK }; @@ -68,22 +69,15 @@ class WardenCheckMgr WardenCheck* GetWardenDataById(uint16 /*build*/, uint16 /*id*/); WardenCheckResult* GetWardenResultById(uint16 /*build*/, uint16 /*id*/); - - std::vector MemChecksIdPool; - std::vector OtherChecksIdPool; + void GetWardenCheckIds(bool isMemCheck /* true = MEM */, uint16 build, std::list& list); void LoadWardenChecks(); void LoadWardenOverrides(); - ACE_RW_Mutex _checkStoreLock; - private: - // We have a linear key without any gaps, so we use vector for fast access - typedef std::map< uint16, WardenCheck* > CheckContainer; - typedef std::map< uint16, WardenCheckResult* > CheckResultContainer; - - typedef std::map< uint16 /*build*/, CheckContainer* > CheckMap; - typedef std::map< uint16 /*build*/, CheckResultContainer* > CheckResultMap; + ACE_RW_Mutex m_lock; + typedef std::multimap< uint16, WardenCheck* > CheckMap; + typedef std::multimap< uint16, WardenCheckResult* > CheckResultMap; CheckMap CheckStore; CheckResultMap CheckResultStore; diff --git a/src/game/Warden/WardenWin.cpp b/src/game/Warden/WardenWin.cpp index c8f83a89..2eb7015d 100644 --- a/src/game/Warden/WardenWin.cpp +++ b/src/game/Warden/WardenWin.cpp @@ -163,18 +163,20 @@ void WardenWin::RequestData() { sLog.outWarden("Request data"); + uint16 build = _session->GetClientBuild(); + uint16 id = 0; + uint8 type = 0; + WardenCheck* wd = NULL; + // If all checks were done, fill the todo list again if (_memChecksTodo.empty()) - _memChecksTodo.assign(sWardenCheckMgr->MemChecksIdPool.begin(), sWardenCheckMgr->MemChecksIdPool.end()); + sWardenCheckMgr->GetWardenCheckIds(true, build, _memChecksTodo); if (_otherChecksTodo.empty()) - _otherChecksTodo.assign(sWardenCheckMgr->OtherChecksIdPool.begin(), sWardenCheckMgr->OtherChecksIdPool.end()); + sWardenCheckMgr->GetWardenCheckIds(false, build, _otherChecksTodo); _serverTicks = WorldTimer::getMSTime(); - uint16 id; - uint8 type; - WardenCheck* wd; _currentChecks.clear(); // Build check request @@ -195,8 +197,6 @@ void WardenWin::RequestData() ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); - ACE_READ_GUARD(ACE_RW_Mutex, g, sWardenCheckMgr->_checkStoreLock); - for (uint16 i = 0; i < sWorld.getConfig(CONFIG_UINT32_WARDEN_NUM_OTHER_CHECKS); ++i) { // If todo list is done break loop (will be filled on next Update() run) @@ -210,18 +210,22 @@ void WardenWin::RequestData() // Add the id to the list sent in this cycle _currentChecks.push_back(id); - wd = sWardenCheckMgr->GetWardenDataById(_session->GetClientBuild(), id); - - switch (wd->Type) + // if we are here, the function is guaranteed to not return NULL + // but ... who knows + wd = sWardenCheckMgr->GetWardenDataById(build, id); + if (wd) { - case MPQ_CHECK: - case LUA_STR_CHECK: - case DRIVER_CHECK: - buff << uint8(wd->Str.size()); - buff.append(wd->Str.c_str(), wd->Str.size()); - break; - default: - break; + switch (wd->Type) + { + case MPQ_CHECK: + case LUA_STR_CHECK: + case DRIVER_CHECK: + buff << uint8(wd->Str.size()); + buff.append(wd->Str.c_str(), wd->Str.size()); + break; + default: + break; + } } } @@ -235,7 +239,7 @@ void WardenWin::RequestData() for (std::list::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) { - wd = sWardenCheckMgr->GetWardenDataById(_session->GetClientBuild(), *itr); + wd = sWardenCheckMgr->GetWardenDataById(build, *itr); type = wd->Type; buff << uint8(type ^ xorByte); @@ -356,8 +360,6 @@ void WardenWin::HandleData(ByteBuffer &buff) uint8 type; uint16 checkFailed = 0; - ACE_READ_GUARD(ACE_RW_Mutex, g, sWardenCheckMgr->_checkStoreLock); - for (std::list::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) { rd = sWardenCheckMgr->GetWardenDataById(_session->GetClientBuild(), *itr);