Skip to content

Commit 93b4a9c

Browse files
committed
fix(data): Sanitize GlobalData values after reading INI data
Clamp m_numGlobalLights to [0, MAX_GLOBAL_LIGHTS] and floor allocation-size fields to prevent out-of-bounds array access and undefined behavior from bad INI values. Closes #2517
1 parent 2d13736 commit 93b4a9c

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

Generals/Code/GameEngine/Source/Common/GlobalData.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,22 @@ void GlobalData::parseGameDataDefinition( INI* ini )
11711171
// parse the ini weapon definition
11721172
ini->initFromINI( TheWritableGlobalData, s_GlobalDataFieldParseTable );
11731173

1174+
// TheSuperHackers @fix Sanitize values that are used as loop bounds or allocation sizes.
1175+
TheWritableGlobalData->m_numGlobalLights = std::clamp(TheWritableGlobalData->m_numGlobalLights, 0, MAX_GLOBAL_LIGHTS);
1176+
TheWritableGlobalData->m_maxVisibleTranslucentObjects = std::max(TheWritableGlobalData->m_maxVisibleTranslucentObjects, 0);
1177+
TheWritableGlobalData->m_maxVisibleOccluderObjects = std::max(TheWritableGlobalData->m_maxVisibleOccluderObjects, 0);
1178+
TheWritableGlobalData->m_maxVisibleOccludeeObjects = std::max(TheWritableGlobalData->m_maxVisibleOccludeeObjects, 0);
1179+
TheWritableGlobalData->m_maxVisibleNonOccluderOrOccludeeObjects = std::max(TheWritableGlobalData->m_maxVisibleNonOccluderOrOccludeeObjects, 0);
1180+
TheWritableGlobalData->m_maxLineBuildObjects = std::max(TheWritableGlobalData->m_maxLineBuildObjects, 0);
1181+
TheWritableGlobalData->m_maxRoadSegments = std::max(TheWritableGlobalData->m_maxRoadSegments, 0);
1182+
TheWritableGlobalData->m_maxRoadVertex = std::max(TheWritableGlobalData->m_maxRoadVertex, 0);
1183+
TheWritableGlobalData->m_maxRoadIndex = std::max(TheWritableGlobalData->m_maxRoadIndex, 0);
1184+
TheWritableGlobalData->m_maxRoadTypes = std::max(TheWritableGlobalData->m_maxRoadTypes, 0);
1185+
TheWritableGlobalData->m_maxTankTrackEdges = std::max(TheWritableGlobalData->m_maxTankTrackEdges, 1);
1186+
TheWritableGlobalData->m_networkFPSHistoryLength = std::max(TheWritableGlobalData->m_networkFPSHistoryLength, 1u);
1187+
TheWritableGlobalData->m_networkLatencyHistoryLength = std::max(TheWritableGlobalData->m_networkLatencyHistoryLength, 1u);
1188+
TheWritableGlobalData->m_networkCushionHistoryLength = std::max(TheWritableGlobalData->m_networkCushionHistoryLength, 1u);
1189+
11741190
TheWritableGlobalData->m_userDataDir.clear();
11751191
TheWritableGlobalData->m_userDataDir = BuildUserDataPathFromIni();
11761192
CreateDirectory(TheWritableGlobalData->m_userDataDir.str(), nullptr);

GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,21 @@ void GlobalData::parseGameDataDefinition( INI* ini )
11811181
// parse the ini weapon definition
11821182
ini->initFromINI( TheWritableGlobalData, s_GlobalDataFieldParseTable );
11831183

1184+
// TheSuperHackers @fix Sanitize values that are used as loop bounds or allocation sizes.
1185+
TheWritableGlobalData->m_numGlobalLights = std::clamp(TheWritableGlobalData->m_numGlobalLights, 0, MAX_GLOBAL_LIGHTS);
1186+
TheWritableGlobalData->m_maxVisibleTranslucentObjects = std::max(TheWritableGlobalData->m_maxVisibleTranslucentObjects, 0);
1187+
TheWritableGlobalData->m_maxVisibleOccluderObjects = std::max(TheWritableGlobalData->m_maxVisibleOccluderObjects, 0);
1188+
TheWritableGlobalData->m_maxVisibleOccludeeObjects = std::max(TheWritableGlobalData->m_maxVisibleOccludeeObjects, 0);
1189+
TheWritableGlobalData->m_maxVisibleNonOccluderOrOccludeeObjects = std::max(TheWritableGlobalData->m_maxVisibleNonOccluderOrOccludeeObjects, 0);
1190+
TheWritableGlobalData->m_maxLineBuildObjects = std::max(TheWritableGlobalData->m_maxLineBuildObjects, 0);
1191+
TheWritableGlobalData->m_maxRoadSegments = std::max(TheWritableGlobalData->m_maxRoadSegments, 0);
1192+
TheWritableGlobalData->m_maxRoadVertex = std::max(TheWritableGlobalData->m_maxRoadVertex, 0);
1193+
TheWritableGlobalData->m_maxRoadIndex = std::max(TheWritableGlobalData->m_maxRoadIndex, 0);
1194+
TheWritableGlobalData->m_maxRoadTypes = std::max(TheWritableGlobalData->m_maxRoadTypes, 0);
1195+
TheWritableGlobalData->m_maxTankTrackEdges = std::max(TheWritableGlobalData->m_maxTankTrackEdges, 1);
1196+
TheWritableGlobalData->m_networkFPSHistoryLength = std::max(TheWritableGlobalData->m_networkFPSHistoryLength, 1u);
1197+
TheWritableGlobalData->m_networkLatencyHistoryLength = std::max(TheWritableGlobalData->m_networkLatencyHistoryLength, 1u);
1198+
TheWritableGlobalData->m_networkCushionHistoryLength = std::max(TheWritableGlobalData->m_networkCushionHistoryLength, 1u);
11841199

11851200
// override INI values with user preferences
11861201
OptionPreferences optionPref;

0 commit comments

Comments
 (0)