You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have searched for similar issues and confirmed this is not a duplicate
Game Version
Command & Conquer Generals
Command & Conquer Generals: Zero Hour
Bug Description
On non-Windows builds a save game cannot be loaded. The load reads the save, throws while reading the CHUNK_GameStateMap block, and GameState::loadGame returns SC_INVALID_DATA, so the game returns to the shell instead of entering the save.
GameState::portableMapPathToRealMapPath builds the real path, validates it, and then lowercases the result before returning it:
portable save\defcon6.map
returned /home/user/.local/share/command and conquer generals zero hour data/save/defcon6.map
GameStateMap::xfer then passes that lowercased path to GameState::isInSaveDirectory, which compares it against the real Save directory:
save dir /home/user/.local/share/Command and Conquer Generals Zero Hour Data/Save/
The first validation inside portableMapPathToRealMapPath succeeds, because it runs before the lowercasing. The later check in GameStateMap::xfer fails, because Save is not save on a case sensitive file system, and the block throws.
This is a regression from #1058. Before that change isInSaveDirectory compared case insensitively:
#1058 replaced that with FileSystem::isPathInDirectory, which compares case insensitively only on Windows. The lowercasing in portableMapPathToRealMapPath and the check in GameStateMap::xfer are both original code and unchanged since the initial commit.
The failure is silent in a release build, because loadGame catches the exception with catch( ... ) and the DEBUG_CRASH that names the failing block is compiled out.
Reproduction Steps
On a non-Windows build, start a mission or skirmish and save the game.
Load that save from the in-game load menu.
Observe the game does not enter the save and returns to the shell.
Repeat on a Windows build. The save loads.
Additional Context
The default user data directory name is mixed case (GlobalData.cpp, leaf name Command and Conquer Generals Zero Hour Data), so this affects a default installation rather than only unusual paths.
isInSaveDirectory is also used by the restart path and by map name checks in GameLogic, which receive the same lowercased name.
Prerequisites
Game Version
Bug Description
On non-Windows builds a save game cannot be loaded. The load reads the save, throws while reading the
CHUNK_GameStateMapblock, andGameState::loadGamereturnsSC_INVALID_DATA, so the game returns to the shell instead of entering the save.GameState::portableMapPathToRealMapPathbuilds the real path, validates it, and then lowercases the result before returning it:GameStateMap::xferthen passes that lowercased path toGameState::isInSaveDirectory, which compares it against the real Save directory:The first validation inside
portableMapPathToRealMapPathsucceeds, because it runs before the lowercasing. The later check inGameStateMap::xferfails, becauseSaveis notsaveon a case sensitive file system, and the block throws.This is a regression from #1058. Before that change
isInSaveDirectorycompared case insensitively:#1058 replaced that with
FileSystem::isPathInDirectory, which compares case insensitively only on Windows. The lowercasing inportableMapPathToRealMapPathand the check inGameStateMap::xferare both original code and unchanged since the initial commit.The failure is silent in a release build, because
loadGamecatches the exception withcatch( ... )and theDEBUG_CRASHthat names the failing block is compiled out.Reproduction Steps
Additional Context
GlobalData.cpp, leaf nameCommand and Conquer Generals Zero Hour Data), so this affects a default installation rather than only unusual paths.isInSaveDirectoryis also used by the restart path and by map name checks inGameLogic, which receive the same lowercased name.FileSystem::isPathInDirectoryitself should stay case sensitive off Windows. [GEN][ZH] Fix security issue in map transfer by validating file paths when creating real paths from portable paths #1058 added it to validate network supplied portable paths before a transferred file is written, so relaxing it globally would weaken that check.