java-topology/defects/megaglest-0002/patch/megaglest-0002.patch
russell@unturf.com 7d80c6a0e6 megaglest: 2 CWE-407 defects, MOAD 0002-0005 CLEAN
megaglest-0001: Unit::updateAttackBoostProgress() std::find on
  currentAttackBoostUnits vector<int> inside per-frame candidate loop
  O(C*B), plus reverse lookup on candidateValidIdList O(B*C).
  Fix: unordered_set<int> for O(1) membership. MEDIUM, 8.3x at N=2000.

megaglest-0002: UnitUpdater::findUnitsForCell() linear dedup scan
  of units vector inside findUnitsInRange grid loop O(R^2 * U).
  Fix: unordered_set<int> seenIds for O(1) dedup. HIGH, 9.1x at
  cells=5000, units=500.

MOAD-0002 (Intertangle): CLEAN, standard game engine singletons.
MOAD-0003 (Leaked Context): CLEAN, no thread_local usage.
MOAD-0004 (Logged Secret): FTP password logged in miniftpclient.cpp
  lines 358, 360, 968, 975 via szBuf containing ftp://user:pass@host
  URL. CWE-312 confirmed but in bundled third-party FTP client code.
MOAD-0005 (Thundering Herd): CLEAN, single-threaded game logic.

4/4 unit tests PASS.
2026-03-31 12:45:31 -04:00

62 lines
2.1 KiB
Diff

--- a/source/glest_game/world/unit_updater.h
+++ b/source/glest_game/world/unit_updater.h
@@ -1,6 +1,7 @@
#ifndef _GLEST_GAME_UNITUPDATER_H_
#define _GLEST_GAME_UNITUPDATER_H_
+#include <unordered_set>
#include <vector>
...
@@ -127,7 +128,7 @@
vector<Unit *> findUnitsInRange(const Unit *unit, int radius);
private:
- void findUnitsForCell(Cell *cell, vector<Unit *> &units);
+ void findUnitsForCell(Cell *cell, vector<Unit *> &units, std::unordered_set<int> &seenIds);
--- a/source/glest_game/world/unit_updater.cpp
+++ b/source/glest_game/world/unit_updater.cpp
@@ -3461,13 +3461,10 @@
-void UnitUpdater::findUnitsForCell(Cell *cell, vector<Unit *> &units) {
+void UnitUpdater::findUnitsForCell(Cell *cell, vector<Unit *> &units, std::unordered_set<int> &seenIds) {
// all fields
if (cell != NULL) {
for (int k = 0; k < fieldCount; k++) {
Field f = static_cast<Field>(k);
// check field
Unit *cellUnit = cell->getUnit(f);
if (cellUnit != NULL && cellUnit->isAlive()) {
- // check if unit already is in list
- bool found = false;
- for (unsigned int i = 0; i < units.size(); ++i) {
- Unit *unitInList = units[i];
- if (unitInList->getId() == cellUnit->getId()) {
- found = true;
- break;
- }
- }
- if (found == false) {
+ // O(1) dedup via hash set instead of O(U) linear scan
+ if (seenIds.insert(cellUnit->getId()).second) {
units.push_back(cellUnit);
}
}
@@ -3492,6 +3489,8 @@
vector<Unit *> UnitUpdater::findUnitsInRange(const Unit *unit, int radius) {
int range = radius;
vector<Unit *> units;
+ std::unordered_set<int> seenIds;
// aux vars
int size = unit->getType()->getSize();
@@ -3507,7 +3506,7 @@
#endif
Cell *cell = map->getCell(i, j);
- findUnitsForCell(cell, units);
+ findUnitsForCell(cell, units, seenIds);
}
}
}