Skip to content

Commit b346b26

Browse files
RankPoints: Add safety checks for potentially corrupted TheGameSpyConfig pointer
1 parent eee5799 commit b346b26

3 files changed

Lines changed: 44 additions & 14 deletions

File tree

Generals/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,12 @@ class GameSpyConfigInterface
7979

8080
extern GameSpyConfigInterface *TheGameSpyConfig;
8181

82+
// Helper function to safely check if TheGameSpyConfig pointer is valid
83+
// Protects against both NULL and corrupted pointer values (e.g., small integers like 0x4)
84+
inline bool IsGameSpyConfigValid()
85+
{
86+
// A valid pointer on Windows should be >= 0x10000 (64KB) to avoid accessing low memory
87+
return (TheGameSpyConfig != NULL) && ((uintptr_t)TheGameSpyConfig >= 0x10000);
88+
}
89+
8290
#endif // __GSCONFIG_H__

Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupPlayerInfo.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -246,22 +246,36 @@ void GetAdditionalDisconnectsFromUserFile(PSPlayerStats *stats)
246246
RankPoints::RankPoints(void)
247247
{
248248
m_ranks[RANK_PRIVATE] = 0;
249-
// Use default values if TheGameSpyConfig is NULL (can happen if called during teardown)
250-
if (TheGameSpyConfig != NULL)
251-
{
252-
m_ranks[RANK_CORPORAL] = TheGameSpyConfig->getPointsForRank(RANK_CORPORAL); // 5
253-
m_ranks[RANK_SERGEANT] = TheGameSpyConfig->getPointsForRank(RANK_SERGEANT); // 10
254-
m_ranks[RANK_LIEUTENANT] = TheGameSpyConfig->getPointsForRank(RANK_LIEUTENANT); // 20
255-
m_ranks[RANK_CAPTAIN] = TheGameSpyConfig->getPointsForRank(RANK_CAPTAIN); // 50
256-
m_ranks[RANK_MAJOR] = TheGameSpyConfig->getPointsForRank(RANK_MAJOR); // 100
257-
m_ranks[RANK_COLONEL] = TheGameSpyConfig->getPointsForRank(RANK_COLONEL); // 200
258-
m_ranks[RANK_BRIGADIER_GENERAL] = TheGameSpyConfig->getPointsForRank(RANK_BRIGADIER_GENERAL); // 500
259-
m_ranks[RANK_GENERAL] = TheGameSpyConfig->getPointsForRank(RANK_GENERAL); // 1000
260-
m_ranks[RANK_COMMANDER_IN_CHIEF] = TheGameSpyConfig->getPointsForRank(RANK_COMMANDER_IN_CHIEF); // 2000
249+
250+
// Validate TheGameSpyConfig pointer before use using helper function
251+
Bool isValidPointer = IsGameSpyConfigValid();
252+
253+
if (isValidPointer)
254+
{
255+
// Additional safety: wrap in try-catch to handle any remaining access violations
256+
try
257+
{
258+
m_ranks[RANK_CORPORAL] = TheGameSpyConfig->getPointsForRank(RANK_CORPORAL); // 5
259+
m_ranks[RANK_SERGEANT] = TheGameSpyConfig->getPointsForRank(RANK_SERGEANT); // 10
260+
m_ranks[RANK_LIEUTENANT] = TheGameSpyConfig->getPointsForRank(RANK_LIEUTENANT); // 20
261+
m_ranks[RANK_CAPTAIN] = TheGameSpyConfig->getPointsForRank(RANK_CAPTAIN); // 50
262+
m_ranks[RANK_MAJOR] = TheGameSpyConfig->getPointsForRank(RANK_MAJOR); // 100
263+
m_ranks[RANK_COLONEL] = TheGameSpyConfig->getPointsForRank(RANK_COLONEL); // 200
264+
m_ranks[RANK_BRIGADIER_GENERAL] = TheGameSpyConfig->getPointsForRank(RANK_BRIGADIER_GENERAL); // 500
265+
m_ranks[RANK_GENERAL] = TheGameSpyConfig->getPointsForRank(RANK_GENERAL); // 1000
266+
m_ranks[RANK_COMMANDER_IN_CHIEF] = TheGameSpyConfig->getPointsForRank(RANK_COMMANDER_IN_CHIEF); // 2000
267+
}
268+
catch (...)
269+
{
270+
// If any exception occurs (e.g., access violation), fall back to default values
271+
DEBUG_LOG(("RankPoints::RankPoints() - Exception accessing TheGameSpyConfig (possibly corrupted pointer), using defaults"));
272+
isValidPointer = false;
273+
}
261274
}
262-
else
275+
276+
if (!isValidPointer)
263277
{
264-
// Use default hardcoded values when TheGameSpyConfig is not available
278+
// Use default hardcoded values when TheGameSpyConfig is not available or corrupted
265279
m_ranks[RANK_CORPORAL] = 5;
266280
m_ranks[RANK_SERGEANT] = 10;
267281
m_ranks[RANK_LIEUTENANT] = 20;

GeneralsMD/Code/GameEngine/Include/GameNetwork/GameSpy/GSConfig.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,12 @@ class GameSpyConfigInterface
7070

7171
extern GameSpyConfigInterface *TheGameSpyConfig;
7272

73+
// Helper function to safely check if TheGameSpyConfig pointer is valid
74+
// Protects against both NULL and corrupted pointer values (e.g., small integers like 0x4)
75+
inline bool IsGameSpyConfigValid()
76+
{
77+
// A valid pointer on Windows should be >= 0x10000 (64KB) to avoid accessing low memory
78+
return (TheGameSpyConfig != NULL) && ((uintptr_t)TheGameSpyConfig >= 0x10000);
79+
}
80+
7381
#endif // __GSCONFIG_H__

0 commit comments

Comments
 (0)