java-topology/defects/spring-rts-0001/patch/spring-rts-0001.patch
russell@unturf.com d3746b98c9 spring-rts: 2 defects (CWE-407 + CWE-312), MOAD 0002-0005 CLEAN
spring-rts-0001: CWeapon::HasIncomingProjectile std::find on vector O(I)
  called from InterceptHandler::Update() O(W*P) nested loop = O(W*P*I).
  Fix: std::unordered_set<int> for O(1) lookup. 3x measured at W=10 P=200 I=100.

spring-rts-0002: GameServer logs passwords verbatim (CWE-312).
  Two LOG() calls in adduser command handler emit pwd.c_str() to log output.
  Fix: remove password values from log format strings.

MOAD-0002 (intertangle): pervasive global state (gs, gu, handlers) but
  architectural, not patchable per-defect.
MOAD-0003 (leaked context): thread_local in Threading.cpp is infrastructure,
  not request-scoped identity. CLEAN.
MOAD-0004: spring-rts-0002 covers this.
MOAD-0005 (thundering herd): simulation is single-threaded for determinism.
  No unsynchronized cache patterns. CLEAN.
2026-03-31 12:43:28 -04:00

38 lines
1.5 KiB
Diff

--- a/rts/Sim/Weapons/Weapon.h
+++ b/rts/Sim/Weapons/Weapon.h
@@ -1,6 +1,7 @@
#ifndef WEAPON_H
#define WEAPON_H
+#include <unordered_set>
#include <functional>
#include <vector>
@@ -46,8 +47,8 @@
virtual const float3& GetAimFromPos(bool useMuzzle = false) const { return (useMuzzle? weaponMuzzlePos: aimFromPos); }
- bool HasIncomingProjectile(int projID) const { return (std::find(incomingProjectileIDs.begin(), incomingProjectileIDs.end(), projID) != incomingProjectileIDs.end()); }
- void AddIncomingProjectile(int projID) { incomingProjectileIDs.push_back(projID); }
+ bool HasIncomingProjectile(int projID) const { return (incomingProjectileIDs.find(projID) != incomingProjectileIDs.end()); }
+ void AddIncomingProjectile(int projID) { incomingProjectileIDs.insert(projID); }
public:
/// test if the weapon is able to attack an enemy/mapspot just by its properties (no range check, no FreeLineOfFire check, ...)
@@ -203,7 +204,7 @@
float3 salvoError;
float3 errorVector;
- std::vector<int> incomingProjectileIDs;
+ std::unordered_set<int> incomingProjectileIDs;
protected:
SWeaponTarget currentTarget;
--- a/rts/Sim/Weapons/Weapon.cpp
+++ b/rts/Sim/Weapons/Weapon.cpp
@@ -724,7 +724,7 @@
// NOTE: DependentDied is called from ~CObject-->Detach, object is just barely valid
if (weaponDef->interceptor || weaponDef->isShield) {
- spring::VectorErase(incomingProjectileIDs, static_cast<CWeaponProjectile*>(o)->id);
+ incomingProjectileIDs.erase(static_cast<CWeaponProjectile*>(o)->id);
}
}