diff --git a/DXMainClient/Domain/SavedGame.cs b/DXMainClient/Domain/SavedGame.cs index 911ba183a..672f6a82a 100644 --- a/DXMainClient/Domain/SavedGame.cs +++ b/DXMainClient/Domain/SavedGame.cs @@ -14,6 +14,7 @@ namespace DTAClient.Domain public class SavedGame { const string SAVED_GAME_PATH = "Saved Games/"; + const int MAX_SCENARIO_DESCRIPTION_BYTES = 1024 * 1024; public SavedGame(string fileName) { @@ -36,15 +37,40 @@ public bool ParseInfo() FileInfo savedGameFileInfo = SafePath.GetFile(ProgramConstants.GamePath, SAVED_GAME_PATH, FileName); using (Stream file = savedGameFileInfo.Open(FileMode.Open, FileAccess.Read)) + using (RootStorage root = RootStorage.Open(file)) { - var cf = new CompoundFile(file); + using (CfbStream scenarioDescStream = root.OpenStream("Scenario Description")) + { + if (scenarioDescStream.Length > MAX_SCENARIO_DESCRIPTION_BYTES) + throw new InvalidDataException($"Scenario Description stream was unexpectedly large: {scenarioDescStream.Length} bytes."); + + int scenarioDescLength = checked((int)scenarioDescStream.Length); + byte[] scenarioDescData = new byte[scenarioDescLength]; + int bytesRead = 0; + while (bytesRead < scenarioDescLength) + { + int readCount = scenarioDescStream.Read(scenarioDescData, bytesRead, scenarioDescLength - bytesRead); + if (readCount == 0) + throw new EndOfStreamException("Unexpected end of stream while reading Scenario Description."); + + bytesRead += readCount; + } + + GUIName = System.Text.Encoding.Unicode.GetString(scenarioDescData).TrimEnd(['\0']); + } - GUIName = System.Text.Encoding.Unicode.GetString(cf.RootStorage.GetStream("Scenario Description").GetData()).TrimEnd(['\0']); - try + if (root.TryOpenStream("CustomMissionID", out CfbStream? customMissionIdStream)) { - CustomMissionID = BinaryPrimitives.ReadInt32LittleEndian(cf.RootStorage.GetStream("CustomMissionID").GetData()); + using (customMissionIdStream) + { + byte[] customMissionIdData = new byte[sizeof(int)]; + int bytesRead = customMissionIdStream.Read(customMissionIdData, 0, customMissionIdData.Length); + CustomMissionID = bytesRead < customMissionIdData.Length + ? throw new EndOfStreamException("Unexpected end of stream while reading CustomMissionID.") + : BinaryPrimitives.ReadInt32LittleEndian(customMissionIdData); + } } - catch (CFItemNotFound) + else { CustomMissionID = 0; } diff --git a/Directory.Packages.props b/Directory.Packages.props index 6dc351d0c..13ad80dd9 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,7 +15,7 @@ - +