Fixes to StreamExts.
- Almost all calls to Stream.Read were broken. These have been patched to all go through ReadBytes which itself has been fixed to function correctly. The key thing to note is that Stream.Read is very much allowed to return less than the requested number of bytes. If this happens and you're not checking the return result, you'll be working with partially initialized arrays and really bad stuff happens when you do that. - Call CopyTo rather than copying between streams manually. - Peek and ReadUInt8 have been changed to avoid a pointless array allocation which is significant overhead for such simple calls.
This commit is contained in:
@@ -105,10 +105,7 @@ namespace OpenRA.FileFormats
|
|||||||
|
|
||||||
// Actually, far too big. There's no length field with the correct length though :(
|
// Actually, far too big. There's no length field with the correct length though :(
|
||||||
var compressedLength = (int)(stream.Length - stream.Position);
|
var compressedLength = (int)(stream.Length - stream.Position);
|
||||||
var compressedBytes = new byte[compressedLength];
|
return stream.ReadBytes(compressedLength);
|
||||||
stream.Read(compressedBytes, 0, compressedLength);
|
|
||||||
|
|
||||||
return compressedBytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decompress(Stream stream, ImageHeader h)
|
void Decompress(Stream stream, ImageHeader h)
|
||||||
|
|||||||
@@ -81,7 +81,8 @@ namespace OpenRA.FileFormats
|
|||||||
for (var j = 0; j < f.Size.Height; j++)
|
for (var j = 0; j < f.Size.Height; j++)
|
||||||
{
|
{
|
||||||
var length = stream.ReadUInt16() - 2;
|
var length = stream.ReadUInt16() - 2;
|
||||||
stream.Read(f.Data, f.Size.Width * j, length);
|
var offset = f.Size.Width * j;
|
||||||
|
stream.ReadBytes(f.Data, offset, length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,10 +56,7 @@ namespace OpenRA.FileSystem
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
s.Seek(e.Offset, SeekOrigin.Begin);
|
s.Seek(e.Offset, SeekOrigin.Begin);
|
||||||
var data = new byte[e.Length];
|
return new MemoryStream(s.ReadBytes((int)e.Length));
|
||||||
s.Read(data, 0, (int)e.Length);
|
|
||||||
|
|
||||||
return new MemoryStream(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream GetContent(string filename)
|
public Stream GetContent(string filename)
|
||||||
|
|||||||
@@ -230,8 +230,7 @@ namespace OpenRA.FileSystem
|
|||||||
if (Exists(filename))
|
if (Exists(filename))
|
||||||
using (var s = Open(filename))
|
using (var s = Open(filename))
|
||||||
{
|
{
|
||||||
var buf = new byte[s.Length];
|
var buf = s.ReadBytes((int)s.Length);
|
||||||
s.Read(buf, 0, buf.Length);
|
|
||||||
a = Assembly.Load(buf);
|
a = Assembly.Load(buf);
|
||||||
assemblyCache.Add(filename, a);
|
assemblyCache.Add(filename, a);
|
||||||
return a;
|
return a;
|
||||||
|
|||||||
@@ -103,8 +103,7 @@ namespace OpenRA.FileSystem
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
s.Seek(dataStart + e.Offset, SeekOrigin.Begin);
|
s.Seek(dataStart + e.Offset, SeekOrigin.Begin);
|
||||||
var data = new byte[e.Length];
|
var data = s.ReadBytes((int)e.Length);
|
||||||
s.Read(data, 0, (int)e.Length);
|
|
||||||
|
|
||||||
return new MemoryStream(Blast.Decompress(data));
|
return new MemoryStream(Blast.Decompress(data));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,8 +157,7 @@ namespace OpenRA.FileSystem
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
s.Seek(dataStart + e.Offset, SeekOrigin.Begin);
|
s.Seek(dataStart + e.Offset, SeekOrigin.Begin);
|
||||||
var data = new byte[e.Length];
|
var data = s.ReadBytes((int)e.Length);
|
||||||
s.Read(data, 0, (int)e.Length);
|
|
||||||
return new MemoryStream(data);
|
return new MemoryStream(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,8 +59,7 @@ namespace OpenRA.FileSystem
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
stream.Seek(entry.Offset, SeekOrigin.Begin);
|
stream.Seek(entry.Offset, SeekOrigin.Begin);
|
||||||
var data = new byte[entry.Length];
|
var data = stream.ReadBytes((int)entry.Length);
|
||||||
stream.Read(data, 0, (int)entry.Length);
|
|
||||||
return new MemoryStream(data);
|
return new MemoryStream(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,11 +60,7 @@ namespace OpenRA.FileSystem
|
|||||||
using (var z = pkg.GetInputStream(pkg.GetEntry(filename)))
|
using (var z = pkg.GetInputStream(pkg.GetEntry(filename)))
|
||||||
{
|
{
|
||||||
var ms = new MemoryStream();
|
var ms = new MemoryStream();
|
||||||
int bufSize = 2048;
|
z.CopyTo(ms);
|
||||||
byte[] buf = new byte[bufSize];
|
|
||||||
while ((bufSize = z.Read(buf, 0, buf.Length)) > 0)
|
|
||||||
ms.Write(buf, 0, bufSize);
|
|
||||||
|
|
||||||
ms.Seek(0, SeekOrigin.Begin);
|
ms.Seek(0, SeekOrigin.Begin);
|
||||||
return ms;
|
return ms;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,12 +122,7 @@ namespace OpenRA
|
|||||||
extracted.Add(path);
|
extracted.Add(path);
|
||||||
|
|
||||||
using (var f = File.Create(path))
|
using (var f = File.Create(path))
|
||||||
{
|
z.CopyTo(f);
|
||||||
int bufSize = 2048;
|
|
||||||
byte[] buf = new byte[bufSize];
|
|
||||||
while ((bufSize = z.Read(buf, 0, buf.Length)) > 0)
|
|
||||||
f.Write(buf, 0, bufSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
z.Close();
|
z.Close();
|
||||||
|
|||||||
@@ -21,27 +21,38 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
throw new ArgumentOutOfRangeException("count", "Non-negative number required.");
|
throw new ArgumentOutOfRangeException("count", "Non-negative number required.");
|
||||||
|
var buffer = new byte[count];
|
||||||
|
s.ReadBytes(buffer, 0, count);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
var buf = new byte[count];
|
public static void ReadBytes(this Stream s, byte[] buffer, int offset, int count)
|
||||||
if (s.Read(buf, 0, count) < count)
|
{
|
||||||
throw new EndOfStreamException();
|
while (count > 0)
|
||||||
|
{
|
||||||
return buf;
|
int bytesRead;
|
||||||
|
if ((bytesRead = s.Read(buffer, offset, count)) == 0)
|
||||||
|
throw new EndOfStreamException();
|
||||||
|
offset += bytesRead;
|
||||||
|
count -= bytesRead;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Peek(this Stream s)
|
public static int Peek(this Stream s)
|
||||||
{
|
{
|
||||||
var buf = new byte[1];
|
var b = s.ReadByte();
|
||||||
if (s.Read(buf, 0, 1) == 0)
|
if (b == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
s.Seek(-1, SeekOrigin.Current);
|
||||||
s.Seek(s.Position - 1, SeekOrigin.Begin);
|
return (byte)b;
|
||||||
return buf[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte ReadUInt8(this Stream s)
|
public static byte ReadUInt8(this Stream s)
|
||||||
{
|
{
|
||||||
return s.ReadBytes(1)[0];
|
var b = s.ReadByte();
|
||||||
|
if (b == -1)
|
||||||
|
throw new EndOfStreamException();
|
||||||
|
return (byte)b;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ushort ReadUInt16(this Stream s)
|
public static ushort ReadUInt16(this Stream s)
|
||||||
@@ -87,19 +98,9 @@ namespace OpenRA
|
|||||||
public static string ReadASCIIZ(this Stream s)
|
public static string ReadASCIIZ(this Stream s)
|
||||||
{
|
{
|
||||||
var bytes = new List<byte>();
|
var bytes = new List<byte>();
|
||||||
var buf = new byte[1];
|
byte b;
|
||||||
|
while ((b = s.ReadUInt8()) != 0)
|
||||||
for (;;)
|
bytes.Add(b);
|
||||||
{
|
|
||||||
if (s.Read(buf, 0, 1) < 1)
|
|
||||||
throw new EndOfStreamException();
|
|
||||||
|
|
||||||
if (buf[0] == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
bytes.Add(buf[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new string(Encoding.ASCII.GetChars(bytes.ToArray()));
|
return new string(Encoding.ASCII.GetChars(bytes.ToArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,11 +114,7 @@ namespace OpenRA
|
|||||||
public static byte[] ReadAllBytes(this Stream s)
|
public static byte[] ReadAllBytes(this Stream s)
|
||||||
{
|
{
|
||||||
using (s)
|
using (s)
|
||||||
{
|
return s.ReadBytes((int)(s.Length - s.Position));
|
||||||
var data = new byte[s.Length - s.Position];
|
|
||||||
s.Read(data, 0, data.Length);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Write(this Stream s, byte[] data)
|
public static void Write(this Stream s, byte[] data)
|
||||||
|
|||||||
Reference in New Issue
Block a user