0ad-0001 CCmpObstructionManager dirty shapes vector+std::find O(N*D) HIGH 4.1x 0ad-0002 CCmpRangeManager m_ModifiedEntities vector+std::find O(E*M) HIGH 25.8x 0ad-0003 CCmpTemplateManager FindUsedTemplates vector+std::find O(T^2) MEDIUM 5.9x 0ad-0004 XmppClient+NetServer lobby auth token logged verbatim CWE-312 MEDIUM MOAD-0002 (Intertangle): g_ globals are deliberate single-thread game arch, CLEAN MOAD-0003 (Leaked Context): thread_local properly scoped, CLEAN MOAD-0005 (Thundering Herd): single-threaded sim, no cache stampede, CLEAN 4/4 unit tests PASS, UNDF 956-959
47 lines
2 KiB
Diff
47 lines
2 KiB
Diff
# UNDF: UNDF-2026-000000957
|
|
--- a/source/simulation2/components/CCmpRangeManager.cpp
|
|
+++ b/source/simulation2/components/CCmpRangeManager.cpp
|
|
@@ -1,6 +1,8 @@
|
|
// CWE-407: CCmpRangeManager m_ModifiedEntities uses std::vector with std::find
|
|
// for dedup. RequestVisibilityUpdate is called per-entity, and GetLosVisibility
|
|
// scans the vector per-entity per-player. With E entities and M modified,
|
|
// this is O(E*M) per frame. Fix: use std::unordered_set for O(1) membership test.
|
|
+#include <unordered_set>
|
|
|
|
// --- Declaration change ---
|
|
@@ -409,7 +411,7 @@
|
|
- std::vector<entity_id_t> m_ModifiedEntities;
|
|
+ std::unordered_set<entity_id_t> m_ModifiedEntities;
|
|
|
|
// --- Serialization: convert set to vector for serialization ---
|
|
@@ -488,7 +490,10 @@
|
|
- Serializer(serialize, "modified entities", m_ModifiedEntities);
|
|
+ // Serialize as vector for backward compatibility
|
|
+ std::vector<entity_id_t> modifiedVec(m_ModifiedEntities.begin(), m_ModifiedEntities.end());
|
|
+ Serializer(serialize, "modified entities", modifiedVec);
|
|
+ // On deserialize, rebuild set from vector
|
|
+ if (!serialize)
|
|
+ m_ModifiedEntities = std::unordered_set<entity_id_t>(modifiedVec.begin(), modifiedVec.end());
|
|
|
|
// --- GetLosVisibility: O(1) lookup instead of O(M) ---
|
|
@@ -1777,7 +1782,7 @@
|
|
- if (std::find(m_ModifiedEntities.begin(), m_ModifiedEntities.end(), entId) != m_ModifiedEntities.end())
|
|
+ if (m_ModifiedEntities.count(entId))
|
|
return ComputeLosVisibility(ent, player);
|
|
|
|
// --- UpdateVisibilityData: iterate set, pop via iterator ---
|
|
@@ -1877,8 +1882,11 @@
|
|
while (!m_ModifiedEntities.empty())
|
|
{
|
|
- entity_id_t ent = m_ModifiedEntities.back();
|
|
- m_ModifiedEntities.pop_back();
|
|
+ auto it = m_ModifiedEntities.begin();
|
|
+ entity_id_t ent = *it;
|
|
+ m_ModifiedEntities.erase(it);
|
|
|
|
// --- RequestVisibilityUpdate: O(1) insert instead of O(M) find ---
|
|
@@ -1891,8 +1899,7 @@
|
|
- if (std::find(m_ModifiedEntities.begin(), m_ModifiedEntities.end(), ent) == m_ModifiedEntities.end())
|
|
- m_ModifiedEntities.push_back(ent);
|
|
+ m_ModifiedEntities.insert(ent);
|
|
}
|