Prevent user counter IDs from colliding with reserved range

In non-Commander games, newCounterId() could return 8 or 9, colliding
  with reserved commander tax counter IDs. A malicious client could
  exploit this via cmd_set_counter_active. Now user counters always
  start at ID 10+.
This commit is contained in:
DawnFire42 2026-06-15 11:12:36 -04:00
parent eddf2c3072
commit 2ad18e2d8b
No known key found for this signature in database
GPG key ID: 24BB855EE2911B33
2 changed files with 8 additions and 11 deletions

View file

@ -74,7 +74,8 @@ int Server_Player::newCounterId() const
id = c->getId(); id = c->getId();
} }
} }
return id + 1; // Skip reserved IDs 0-9 even in non-Commander games to prevent collision
return std::max(id + 1, CounterIds::FirstUserId);
} }
void Server_Player::setupZones() void Server_Player::setupZones()

View file

@ -16,20 +16,16 @@
* Reserved counter IDs for system counters: * Reserved counter IDs for system counters:
* IDs 0-7: Standard player counters (life, mana colors, storm) * IDs 0-7: Standard player counters (life, mana colors, storm)
* IDs 8-9: Commander tax counters * IDs 8-9: Commander tax counters
* IDs 10+: Available for user-created counters * IDs 10+: Available for user-created counters (FirstUserId)
* *
* The server's newCounterId() starts from the highest existing ID + 1, * newCounterId() always returns >= FirstUserId to prevent user counters
* so these reserved IDs won't conflict as long as they're created first * from colliding with reserved IDs, even in non-Commander games.
* during setupZones(). See server_player.cpp::setupZones() for the
* authoritative list of reserved IDs.
*
* To find all files referencing these IDs, grep for CounterIds::CommanderTax
* and CounterIds::PartnerTax across the codebase.
*/ */
namespace CounterIds namespace CounterIds
{ {
constexpr int CommanderTax = 8; constexpr int CommanderTax = 8; ///< Primary commander tax counter
constexpr int PartnerTax = 9; constexpr int PartnerTax = 9; ///< Partner commander tax counter
constexpr int FirstUserId = 10; ///< First ID available for user-created counters
inline bool isTaxCounter(int id) inline bool isTaxCounter(int id)
{ {