Skip to content

Commit d5f4af1

Browse files
MohabCodeXDutchman101FileEX
authored
Fixes #3655 - prevent duplicate command registration (#4313)
- Prevent duplicate command handlers --------- Co-authored-by: Dutchman101 <[email protected]> Co-authored-by: FileEX <[email protected]>
1 parent ea3362a commit d5f4af1

File tree

14 files changed

+106
-13
lines changed

14 files changed

+106
-13
lines changed

Client/mods/deathmatch/logic/CClientGame.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ CClientGame::CClientGame(bool bLocalPlay) : m_ServerInfo(new CServerInfo())
120120

121121
m_bCursorEventsEnabled = false;
122122
m_bInitiallyFadedOut = true;
123+
m_allowMultiCommandHandlers = MultiCommandHandlerPolicy::WARN;
123124

124125
m_bIsPlayingBack = false;
125126
m_bFirstPlaybackFrame = false;
@@ -409,7 +410,7 @@ CClientGame::~CClientGame()
409410
m_bBeingDeleted = true;
410411
// Remove active projectile references to local player
411412
if (auto pLocalPlayer = g_pClientGame->GetLocalPlayer())
412-
g_pGame->GetProjectileInfo()->RemoveEntityReferences(pLocalPlayer->GetGameEntity());
413+
g_pGame->GetProjectileInfo()->RemoveEntityReferences(pLocalPlayer->GetGameEntity());
413414

414415
// Stop all explosions. Unfortunately this doesn't fix the crash
415416
// if a vehicle is destroyed while it explodes.
@@ -1024,7 +1025,7 @@ void CClientGame::DoPulsePostFrame()
10241025
}
10251026

10261027
auto taskManager = pLocalPlayer->GetTaskManager();
1027-
auto task = taskManager->GetActiveTask();
1028+
auto task = taskManager->GetActiveTask();
10281029
auto pVehicle = pLocalPlayer->GetOccupiedVehicle();
10291030
bool useZoneName = true;
10301031

@@ -1078,7 +1079,7 @@ void CClientGame::DoPulsePostFrame()
10781079

10791080
discordState = taskState.strState;
10801081
useZoneName = taskState.bUseZone;
1081-
}
1082+
}
10821083

10831084
if (useZoneName)
10841085
{

Client/mods/deathmatch/logic/CClientGame.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ class CClientGame
193193
QUIT_CONNECTION_DESYNC,
194194
QUIT_TIMEOUT,
195195
};
196+
196197
enum
197198
{
198199
GLITCH_QUICKRELOAD,
@@ -470,6 +471,9 @@ class CClientGame
470471
void ReinitMarkers();
471472

472473
void OnWindowFocusChange(bool state);
474+
475+
void SetAllowMultiCommandHandlers(MultiCommandHandlerPolicy policy) noexcept { m_allowMultiCommandHandlers = policy; }
476+
MultiCommandHandlerPolicy GetAllowMultiCommandHandlers() const noexcept { return m_allowMultiCommandHandlers; }
473477

474478
private:
475479
// CGUI Callbacks
@@ -873,6 +877,8 @@ class CClientGame
873877
// Key is the task and value is the CClientPed*
874878
RunNamedAnimTask_type m_mapOfRunNamedAnimTasks;
875879

880+
MultiCommandHandlerPolicy m_allowMultiCommandHandlers;
881+
876882
long long m_timeLastDiscordStateUpdate;
877883
};
878884

Client/mods/deathmatch/logic/CPacketHandler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5490,6 +5490,10 @@ void CPacketHandler::Packet_SyncSettings(NetBitStreamInterface& bitStream)
54905490
uchar ucAllowShotgunDamageFix = 0;
54915491
bitStream.Read(ucAllowShotgunDamageFix);
54925492

5493+
uchar allowMultiCommandHandlers = 1;
5494+
bitStream.Read(allowMultiCommandHandlers);
5495+
g_pClientGame->SetAllowMultiCommandHandlers(static_cast<MultiCommandHandlerPolicy>(allowMultiCommandHandlers));
5496+
54935497
SMiscGameSettings miscGameSettings;
54945498
miscGameSettings.bUseAltPulseOrder = (ucUseAltPulseOrder != 0);
54955499
miscGameSettings.bAllowFastSprintFix = (ucAllowFastSprintFix != 0);

Client/mods/deathmatch/logic/CRegisteredCommands.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*****************************************************************************/
1010

1111
#include "StdInc.h"
12+
#include "CClientGame.h"
1213

1314
using std::list;
1415

@@ -27,6 +28,26 @@ bool CRegisteredCommands::AddCommand(CLuaMain* pLuaMain, const char* szKey, cons
2728
assert(pLuaMain);
2829
assert(szKey);
2930

31+
if (CommandExists(szKey, nullptr))
32+
{
33+
const MultiCommandHandlerPolicy allowMultiHandlers = g_pClientGame->GetAllowMultiCommandHandlers();
34+
35+
switch (allowMultiHandlers)
36+
{
37+
case MultiCommandHandlerPolicy::BLOCK:
38+
g_pClientGame->GetScriptDebugging()->LogError(pLuaMain->GetVM(), "addCommandHandler: Duplicate command registration blocked for '%s' (multiple handlers disabled)", szKey);
39+
return false;
40+
41+
case MultiCommandHandlerPolicy::WARN:
42+
g_pClientGame->GetScriptDebugging()->LogWarning(pLuaMain->GetVM(), "addCommandHandler: Attempt to register duplicate command '%s'", szKey);
43+
break;
44+
45+
case MultiCommandHandlerPolicy::ALLOW:
46+
default:
47+
break;
48+
}
49+
}
50+
3051
// Check if we already have this key and handler
3152
SCommand* pCommand = GetCommand(szKey, pLuaMain);
3253
if (pCommand)
@@ -126,7 +147,7 @@ bool CRegisteredCommands::CommandExists(const char* szKey, CLuaMain* pLuaMain)
126147
{
127148
assert(szKey);
128149

129-
return GetCommand(szKey, pLuaMain) != NULL;
150+
return GetCommand(szKey, pLuaMain) != nullptr;
130151
}
131152

132153
bool CRegisteredCommands::ProcessCommand(const char* szKey, const char* szArguments)
@@ -183,7 +204,7 @@ CRegisteredCommands::SCommand* CRegisteredCommands::GetCommand(const char* szKey
183204
}
184205

185206
// Doesn't exist
186-
return NULL;
207+
return nullptr;
187208
}
188209

189210
void CRegisteredCommands::CallCommandHandler(CLuaMain* pLuaMain, const CLuaFunctionRef& iLuaFunction, const char* szKey, const char* szArguments)
@@ -204,7 +225,7 @@ void CRegisteredCommands::CallCommandHandler(CLuaMain* pLuaMain, const CLuaFunct
204225
while (arg)
205226
{
206227
Arguments.PushString(arg);
207-
arg = strtok(NULL, " ");
228+
arg = strtok(nullptr, " ");
208229
}
209230
delete[] szTempArguments;
210231
}

Client/mods/deathmatch/logic/CRegisteredCommands.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,20 @@
1010

1111
#pragma once
1212

13+
#include <cstdint>
1314
#include <list>
1415
#include <unordered_set>
1516

1617
#define MAX_REGISTERED_COMMAND_LENGTH 64
1718
#define MAX_REGISTERED_COMMANDHANDLER_LENGTH 64
1819

20+
enum class MultiCommandHandlerPolicy : std::uint8_t
21+
{
22+
BLOCK = 0,
23+
WARN = 1,
24+
ALLOW = 2
25+
};
26+
1927
class CRegisteredCommands
2028
{
2129
struct SCommand

Server/mods/deathmatch/logic/CGame.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4718,9 +4718,10 @@ void CGame::SendSyncSettings(CPlayer* pPlayer)
47184718
uchar ucAllowFastSprintFix = true;
47194719
uchar ucAllowDrivebyAnimFix = true;
47204720
uchar ucAllowShotgunDamageFix = true;
4721+
std::uint8_t multiCommandHandlerPolicy = static_cast<std::uint8_t>(m_pMainConfig->GetAllowMultiCommandHandlers());
47214722

47224723
CSyncSettingsPacket packet(weaponTypesUsingBulletSync, ucVehExtrapolateEnabled, sVehExtrapolateBaseMs, sVehExtrapolatePercent, sVehExtrapolateMaxMs,
4723-
ucUseAltPulseOrder, ucAllowFastSprintFix, ucAllowDrivebyAnimFix, ucAllowShotgunDamageFix);
4724+
ucUseAltPulseOrder, ucAllowFastSprintFix, ucAllowDrivebyAnimFix, ucAllowShotgunDamageFix, multiCommandHandlerPolicy);
47244725
if (pPlayer)
47254726
pPlayer->Send(packet);
47264727
else

Server/mods/deathmatch/logic/CMainConfig.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ CMainConfig::CMainConfig(CConsole* pConsole) : CXMLConfig(NULL)
8282
m_bSyncMapElementData = true;
8383
m_elementDataWhitelisted = false;
8484
m_checkDuplicateSerials = true;
85+
m_allowMultiCommandHandlers = 1;
8586
}
8687

8788
bool CMainConfig::Load()
@@ -540,6 +541,8 @@ bool CMainConfig::Load()
540541

541542
GetBoolean(m_pRootNode, "elementdata_whitelisted", m_elementDataWhitelisted);
542543
GetBoolean(m_pRootNode, "check_duplicate_serials", m_checkDuplicateSerials);
544+
GetInteger(m_pRootNode, "allow_multi_command_handlers", m_allowMultiCommandHandlers);
545+
m_allowMultiCommandHandlers = Clamp(0, m_allowMultiCommandHandlers, 2);
543546

544547
ApplyNetOptions();
545548

@@ -1531,6 +1534,7 @@ const std::vector<SIntSetting>& CMainConfig::GetIntSettingList()
15311534
{true, true, 50, 1000, 5000, "player_triggered_event_interval", &m_iPlayerTriggeredEventIntervalMs, &CMainConfig::OnPlayerTriggeredEventIntervalChange},
15321535
{true, true, 1, 100, 1000, "max_player_triggered_events_per_interval", &m_iMaxPlayerTriggeredEventsPerInterval, &CMainConfig::OnPlayerTriggeredEventIntervalChange},
15331536
{true, true, 0, 1, 1, "resource_client_file_checks", &m_checkResourceClientFiles, nullptr},
1537+
{true, true, 0, 1, 2, "allow_multi_command_handlers", &m_allowMultiCommandHandlers, &CMainConfig::OnAllowMultiCommandHandlersChange},
15341538
};
15351539

15361540
static std::vector<SIntSetting> settingsList;
@@ -1580,6 +1584,11 @@ void CMainConfig::OnPlayerTriggeredEventIntervalChange()
15801584
g_pGame->ApplyPlayerTriggeredEventIntervalChange();
15811585
}
15821586

1587+
void CMainConfig::OnAllowMultiCommandHandlersChange()
1588+
{
1589+
g_pGame->SendSyncSettings();
1590+
}
1591+
15831592
void CGame::ApplyPlayerTriggeredEventIntervalChange()
15841593
{
15851594
m_iClientTriggeredEventsIntervalMs = m_pMainConfig->GetPlayerTriggeredEventInterval();

Server/mods/deathmatch/logic/CMainConfig.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,11 @@ class CMainConfig : public CXMLConfig
147147
void OnTickRateChange();
148148
void OnAseSettingChange();
149149
void OnPlayerTriggeredEventIntervalChange();
150+
void OnAllowMultiCommandHandlersChange();
150151

151152
int GetPlayerTriggeredEventInterval() const { return m_iPlayerTriggeredEventIntervalMs; }
152153
int GetMaxPlayerTriggeredEventsPerInterval() const { return m_iMaxPlayerTriggeredEventsPerInterval; }
154+
int GetAllowMultiCommandHandlers() const noexcept { return m_allowMultiCommandHandlers; }
153155

154156
private:
155157
void RegisterCommand(const char* szName, FCommandHandler* pFunction, bool bRestricted, const char* szConsoleHelpText);
@@ -235,4 +237,5 @@ class CMainConfig : public CXMLConfig
235237
bool m_elementDataWhitelisted;
236238
bool m_checkDuplicateSerials;
237239
int m_checkResourceClientFiles;
240+
int m_allowMultiCommandHandlers;
238241
};

Server/mods/deathmatch/logic/CRegisteredCommands.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include "CClient.h"
1919
#include "CConsoleClient.h"
2020
#include "CPlayer.h"
21+
#include "CGame.h"
22+
#include "CScriptDebugging.h"
23+
#include "CMainConfig.h"
2124

2225
CRegisteredCommands::CRegisteredCommands(CAccessControlListManager* pACLManager)
2326
{
@@ -35,6 +38,26 @@ bool CRegisteredCommands::AddCommand(CLuaMain* pLuaMain, const char* szKey, cons
3538
assert(pLuaMain);
3639
assert(szKey);
3740

41+
if (CommandExists(szKey, nullptr))
42+
{
43+
auto policy = static_cast<MultiCommandHandlerPolicy>(g_pGame->GetConfig()->GetAllowMultiCommandHandlers());
44+
45+
switch (policy)
46+
{
47+
case MultiCommandHandlerPolicy::BLOCK:
48+
g_pGame->GetScriptDebugging()->LogError(pLuaMain->GetVM(), "addCommandHandler: Duplicate command registration blocked for '%s' (multiple handlers disabled)", szKey);
49+
return false;
50+
51+
case MultiCommandHandlerPolicy::WARN:
52+
g_pGame->GetScriptDebugging()->LogWarning(pLuaMain->GetVM(), "Attempt to register duplicate command '%s'", szKey);
53+
break;
54+
55+
case MultiCommandHandlerPolicy::ALLOW:
56+
default:
57+
break;
58+
}
59+
}
60+
3861
// Check if we already have this key and handler
3962
SCommand* pCommand = GetCommand(szKey, pLuaMain);
4063

@@ -139,7 +162,7 @@ bool CRegisteredCommands::CommandExists(const char* szKey, CLuaMain* pLuaMain)
139162
{
140163
assert(szKey);
141164

142-
return GetCommand(szKey, pLuaMain) != NULL;
165+
return GetCommand(szKey, pLuaMain) != nullptr;
143166
}
144167

145168
bool CRegisteredCommands::ProcessCommand(const char* szKey, const char* szArguments, CClient* pClient)
@@ -203,7 +226,7 @@ CRegisteredCommands::SCommand* CRegisteredCommands::GetCommand(const char* szKey
203226
}
204227

205228
// Doesn't exist
206-
return NULL;
229+
return nullptr;
207230
}
208231

209232
void CRegisteredCommands::CallCommandHandler(CLuaMain* pLuaMain, const CLuaFunctionRef& iLuaFunction, const char* szKey, const char* szArguments,
@@ -253,7 +276,7 @@ void CRegisteredCommands::CallCommandHandler(CLuaMain* pLuaMain, const CLuaFunct
253276
while (arg)
254277
{
255278
Arguments.PushString(arg);
256-
arg = strtok(NULL, " ");
279+
arg = strtok(nullptr, " ");
257280
}
258281

259282
delete[] szTempArguments;

Server/mods/deathmatch/logic/CRegisteredCommands.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,20 @@
1212
#pragma once
1313

1414
#include "lua/CLuaFunctionRef.h"
15+
#include <cstdint>
1516
#include <list>
1617
#include <unordered_set>
1718

1819
#define MAX_REGISTERED_COMMAND_LENGTH 64
1920
#define MAX_REGISTERED_COMMANDHANDLER_LENGTH 64
2021

22+
enum class MultiCommandHandlerPolicy : std::uint8_t
23+
{
24+
BLOCK = 0,
25+
WARN = 1,
26+
ALLOW = 2
27+
};
28+
2129
class CRegisteredCommands
2230
{
2331
struct SCommand

0 commit comments

Comments
 (0)