From 2ad18e2d8bb734f4b160af5df39b70cc9b22a1c5 Mon Sep 17 00:00:00 2001 From: DawnFire42 Date: Mon, 15 Jun 2026 11:12:36 -0400 Subject: [PATCH] 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+. --- .../network/server/remote/game/server_player.cpp | 3 ++- .../libcockatrice/utility/counter_ids.h | 16 ++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp index 893420890..bb86be9b1 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_player.cpp @@ -74,7 +74,8 @@ int Server_Player::newCounterId() const 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() diff --git a/libcockatrice_utility/libcockatrice/utility/counter_ids.h b/libcockatrice_utility/libcockatrice/utility/counter_ids.h index 80571b554..7472f7328 100644 --- a/libcockatrice_utility/libcockatrice/utility/counter_ids.h +++ b/libcockatrice_utility/libcockatrice/utility/counter_ids.h @@ -16,20 +16,16 @@ * Reserved counter IDs for system counters: * IDs 0-7: Standard player counters (life, mana colors, storm) * 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, - * so these reserved IDs won't conflict as long as they're created first - * 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. + * newCounterId() always returns >= FirstUserId to prevent user counters + * from colliding with reserved IDs, even in non-Commander games. */ namespace CounterIds { -constexpr int CommanderTax = 8; -constexpr int PartnerTax = 9; +constexpr int CommanderTax = 8; ///< Primary commander tax counter +constexpr int PartnerTax = 9; ///< Partner commander tax counter +constexpr int FirstUserId = 10; ///< First ID available for user-created counters inline bool isTaxCounter(int id) {