java-topology/whitepaper/outreach/netpanzer-0002.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.6 KiB
Raw Blame History

NetPanzer — CWE-407 Disclosure Brief (netpanzer-0002)

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

Finding

One O(B × U) defect in NetPanzer's unit bucket array lookup. Patched. getUnitBucketIndex() scans all buckets and all units within each bucket to find a unit by ID, producing O(B × U) per lookup.

The Defect

netpanzer-0002 (PATCHED — HIGH): src/NetPanzer/Units/UnitBucketArray.cpp:119

// In getUnitBucketIndex() — fires per unit position query:
long UnitBucketArray::getUnitBucketIndex(UnitID unit_id) {
    for (unsigned long bucket_index = 0; bucket_index < size; bucket_index++) {
        UnitBucketPointer *traversal_ptr = array[bucket_index].getFront();
        while (traversal_ptr != 0) {
            if (traversal_ptr->unit->id == unit_id) return (long)bucket_index;
            traversal_ptr = traversal_ptr->next;
        }
    }
    return -1;
}

Scans every bucket and every unit pointer in every bucket. With B buckets and U total units, cost is O(B + U) per call (amortized O(U) since units are spread across buckets). Called during unit movement, collision, and targeting.

Complexity Proof

At U=1,000 units across B=256 buckets:

  • Defective: up to 1,000 unit pointer comparisons per lookup (worst case: unit in last bucket)
  • Fixed: O(1) hash map lookup
  • ~500× op reduction average case.

Impact

NetPanzer is an open-source multiplayer tank battle game. The bucket array spatial index supports collision detection, targeting, and movement. Every unit movement triggers bucket lookups. With 1,000+ units in a multiplayer game, the quadratic bucket scanning degrades server tick rate.

The Fix

Maintain an unordered_map<UnitID, unsigned long> mapping unit IDs to bucket indices:

// Before: O(B*U) full scan
for (bucket_index = 0; bucket_index < size; bucket_index++) { ... }

// After: O(1) hash lookup
auto it = unitBucketMap.find(unit_id);
return (it != unitBucketMap.end()) ? (long)it->second : -1;

Patch

Fix available: defects/netpanzer-0002/patch/

Touches UnitBucketArray.hpp and UnitBucketArray.cpp. Maintains hash map on add/move/delete. ~500× speedup at 1,000 units.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a GitHub issue reference.
  2. Assess severity — fires on every unit movement and targeting query.
  3. Coordinate a disclosure date — we are targeting 90 days from first contact.
  4. We will credit the NetPanzer team in the public disclosure. Preferred acknowledgment format welcome.

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