java-topology/whitepaper/outreach/openxcom-0001.md
russell@unturf.com 652608142a feat: close outreach doc gap — 276 docs (batches 11-16)
All projects with patches now have outreach docs. 276 new docs covering
CWE-407, CWE-312, CWE-362 across C, C++, Java, Python, Go, Rust, C#,
PHP, Ruby, JavaScript, Dart, Erlang, R, and more.

Outreach gap: 276 -> 0.
2026-04-15 13:57:42 -04:00

2.7 KiB
Raw Blame History

OpenXcom — CWE-407 Disclosure Brief (openxcom-0001)

2026-04-13 · Patch available — awaiting upstream merge

Finding

O(N²) membership tests in AIModule where std::find scans _reachable and _reachableWithAttack vectors (both vector<int>) for every tile evaluated during AI decision-making. Fires per alien unit per AI turn.

The Defect

openxcom-0001 (PATCHED — HIGH): src/Battlescape/AIModule.cpp

std::vector<int> _reachable, _reachableWithAttack;

// Called multiple times per AI evaluation — O(T) per call:
if (std::find(_reachable.begin(), _reachable.end(),
    _save->getTileIndex(checkPath)) == _reachable.end())
    ...

if (std::find(_reachableWithAttack.begin(), _reachableWithAttack.end(),
    _save->getTileIndex(pos)) == _reachableWithAttack.end())
    ...

Multiple call sites throughout AI evaluation (lines 612, 902, 1165, 1462, 2096) scan these vectors. With T reachable tiles per unit and U units per AI turn, total cost is O(U × calls × T).

Complexity Proof

At T=2,000 reachable tiles per unit and 5 std::find call sites:

  • Defective: 5 × 2,000 = 10,000 comparisons per unit per evaluation cycle
  • Fixed: 5 hash lookups per unit
  • ~2,000× op reduction per unit per evaluation cycle.

Impact

OpenXcom reimplements X-COM: UFO Defense. AI turns process every alien unit, each evaluating reachable tiles for movement and attack decisions. Large battlescape maps (Terror missions, base assaults) with 20+ alien units and thousands of reachable tiles per unit make AI turns visibly slow. The original game supported fewer simultaneous AI units, but OpenXcom mods expand enemy counts significantly.

The Fix

Replace vector<int> with unordered_set<int> for _reachable and _reachableWithAttack. Convert findReachable() results from vector to set at assignment:

std::unordered_set<int> _reachable, _reachableWithAttack;
// ...
std::vector<int> rv = _save->getPathfinding()->findReachable(...);
_reachable = std::unordered_set<int>(rv.begin(), rv.end());
// ...
_reachable.count(_save->getTileIndex(checkPath)) == 0  // O(1)

Patch

Fix available: defects/openxcom-0001/patch/openxcom-0001.patch

Two-file patch across AIModule.h and AIModule.cpp.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a GitHub issue reference (OpenXcom/OpenXcom).
  2. Assess severity — fires per alien unit per AI turn, compounds with map size and unit count.
  3. Coordinate a disclosure date — we target 90 days from first contact.
  4. We will credit the OpenXcom team in the public disclosure. Preferred acknowledgment format welcome.

Contact: see cover email. This brief is confidential until coordinated disclosure.