java-topology/defects/0ad-0001/patch/0ad-0001.patch
russell@unturf.com 223ccb3fee 0ad: 4 defects, 5-MOAD scan across pathfinding/visibility/templates/lobby
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
2026-03-31 11:58:37 -04:00

73 lines
3.4 KiB
Diff

# UNDF: UNDF-2026-000000956
--- a/source/simulation2/components/CCmpObstructionManager.cpp
+++ b/source/simulation2/components/CCmpObstructionManager.cpp
@@ -1,6 +1,7 @@
// CWE-407: CCmpObstructionManager dirty shape tracking uses std::vector with
// std::find for dedup, causing O(N*D) per-frame cost where N = nearby shapes
// and D = dirty list size. In large battles (200v200), hundreds of shapes
// move per frame, making this O(N^2). Fix: use std::unordered_set for O(1) lookup.
+#include <unordered_set>
// --- Declaration change ---
@@ -525,8 +526,8 @@
// Dynamic updates for the long-range pathfinder
GridUpdateInformation m_UpdateInformations;
// These vectors might contain shapes that were deleted
- std::vector<u32> m_DirtyStaticShapes;
- std::vector<u32> m_DirtyUnitShapes;
+ std::unordered_set<u32> m_DirtyStaticShapes;
+ std::unordered_set<u32> m_DirtyUnitShapes;
// --- MakeDirtyStatic ---
@@ -584,8 +585,7 @@
- if (std::find(m_DirtyStaticShapes.begin(), m_DirtyStaticShapes.end(), index) == m_DirtyStaticShapes.end())
- m_DirtyStaticShapes.push_back(index);
+ m_DirtyStaticShapes.insert(index);
// All shapes overlapping the updated part of the grid should be dirtied too.
@@ -599,12 +599,10 @@
std::vector<u32> staticsNear;
m_StaticSubdivision.GetInRange(staticsNear, center - hbox - expand*2, center + hbox + expand*2);
for (u32& staticId : staticsNear)
- if (std::find(m_DirtyStaticShapes.begin(), m_DirtyStaticShapes.end(), staticId) == m_DirtyStaticShapes.end())
- m_DirtyStaticShapes.push_back(staticId);
+ m_DirtyStaticShapes.insert(staticId);
std::vector<u32> unitsNear;
m_UnitSubdivision.GetInRange(unitsNear, center - hbox - expand*2, center + hbox + expand*2);
for (u32& unitId : unitsNear)
- if (std::find(m_DirtyUnitShapes.begin(), m_DirtyUnitShapes.end(), unitId) == m_DirtyUnitShapes.end())
- m_DirtyUnitShapes.push_back(unitId);
+ m_DirtyUnitShapes.insert(unitId);
// --- MakeDirtyUnit ---
@@ -624,8 +622,7 @@
- if (std::find(m_DirtyUnitShapes.begin(), m_DirtyUnitShapes.end(), index) == m_DirtyUnitShapes.end())
- m_DirtyUnitShapes.push_back(index);
+ m_DirtyUnitShapes.insert(index);
@@ -637,12 +634,10 @@
std::vector<u32> staticsNear;
m_StaticSubdivision.GetNear(staticsNear, center, shape.clearance + m_MaxClearance*2);
for (u32& staticId : staticsNear)
- if (std::find(m_DirtyStaticShapes.begin(), m_DirtyStaticShapes.end(), staticId) == m_DirtyStaticShapes.end())
- m_DirtyStaticShapes.push_back(staticId);
+ m_DirtyStaticShapes.insert(staticId);
std::vector<u32> unitsNear;
m_UnitSubdivision.GetNear(unitsNear, center, shape.clearance + m_MaxClearance*2);
for (u32& unitId : unitsNear)
- if (std::find(m_DirtyUnitShapes.begin(), m_DirtyUnitShapes.end(), unitId) == m_DirtyUnitShapes.end())
- m_DirtyUnitShapes.push_back(unitId);
+ m_DirtyUnitShapes.insert(unitId);
// --- RasterizeHelper ---
@@ -1116,7 +1111,7 @@
- if (!fullUpdate && std::find(m_DirtyStaticShapes.begin(), m_DirtyStaticShapes.end(), pair.first) == m_DirtyStaticShapes.end())
+ if (!fullUpdate && m_DirtyStaticShapes.find(pair.first) == m_DirtyStaticShapes.end())
continue;
@@ -1139,7 +1134,7 @@
- if (!fullUpdate && std::find(m_DirtyUnitShapes.begin(), m_DirtyUnitShapes.end(), pair.first) == m_DirtyUnitShapes.end())
+ if (!fullUpdate && m_DirtyUnitShapes.find(pair.first) == m_DirtyUnitShapes.end())
continue;