Fix crash when trying to read empty replay files
It was crashing because it tried to seek 8 bytes before the end of a file that was empty (zero length). I also added a few more checks and another try/catch to prevent any more crashes related to damaged files.
This commit is contained in:
@@ -46,8 +46,8 @@ namespace OpenRA.FileFormats
|
|||||||
if (version != MetaVersion)
|
if (version != MetaVersion)
|
||||||
throw new NotSupportedException("Metadata version {0} is not supported".F(version));
|
throw new NotSupportedException("Metadata version {0} is not supported".F(version));
|
||||||
|
|
||||||
// Read game info
|
// Read game info (max 100K limit as a safeguard against corrupted files)
|
||||||
string data = ReadUtf8String(reader);
|
string data = ReadUtf8String(reader, 1024 * 100);
|
||||||
GameInfo = GameInformation.Deserialize(data);
|
GameInfo = GameInformation.Deserialize(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,13 +87,18 @@ namespace OpenRA.FileFormats
|
|||||||
if (!fs.CanSeek)
|
if (!fs.CanSeek)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
if (fs.Length < 20)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
fs.Seek(-(4 + 4), SeekOrigin.End);
|
fs.Seek(-(4 + 4), SeekOrigin.End);
|
||||||
using (var reader = new BinaryReader(fs))
|
using (var reader = new BinaryReader(fs))
|
||||||
{
|
{
|
||||||
var dataLength = reader.ReadInt32();
|
var dataLength = reader.ReadInt32();
|
||||||
if (reader.ReadInt32() == MetaEndMarker)
|
if (reader.ReadInt32() == MetaEndMarker)
|
||||||
{
|
{
|
||||||
// go back end marker + length storage + data + version + start marker
|
// go back by (end marker + length storage + data + version + start marker) bytes
|
||||||
fs.Seek(-(4 + 4 + dataLength + 4 + 4), SeekOrigin.Current);
|
fs.Seek(-(4 + 4 + dataLength + 4 + 4), SeekOrigin.Current);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -109,6 +114,11 @@ namespace OpenRA.FileFormats
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
Log.Write("debug", ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -128,9 +138,13 @@ namespace OpenRA.FileFormats
|
|||||||
return 4 + bytes.Length;
|
return 4 + bytes.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static string ReadUtf8String(BinaryReader reader)
|
static string ReadUtf8String(BinaryReader reader, int maxLength)
|
||||||
{
|
{
|
||||||
return Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadInt32()));
|
var length = reader.ReadInt32();
|
||||||
|
if (length > maxLength)
|
||||||
|
throw new InvalidOperationException("The length of the string ({0}) is longer than the maximum allowed ({1}).".F(length, maxLength));
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(reader.ReadBytes(length));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user