Fixed the editor crashing/locking up when trying to read TEXTUREX patch containing invalid data.

This commit is contained in:
MaxED 2016-10-28 21:07:33 +00:00
parent 3e132f1cf2
commit 8570922d0d
5 changed files with 42 additions and 116 deletions

View file

@ -60,8 +60,8 @@ namespace CodeImp.DoomBuilder
[DllImport("kernel32.dll", EntryPoint = "RtlZeroMemory", SetLastError = false)]
internal static extern void ZeroMemory(IntPtr dest, int size);
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
internal static extern unsafe void CopyMemory(void* dst, void* src, uint length);
//[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
//internal static extern unsafe void CopyMemory(void* dst, void* src, uint length);
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern int SendMessage(IntPtr hwnd, uint Msg, int wParam, int lParam);
@ -2168,7 +2168,7 @@ namespace CodeImp.DoomBuilder
try { WriteLogLine(exceptionmsg); } catch { }
// Try displaying it to the user...
try { MessageBox.Show("Fatal Windows Forms Error", exceptionmsg, MessageBoxButtons.OK, MessageBoxIcon.Stop); }
try { MessageBox.Show(exceptionmsg, "Fatal Windows Forms Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); }
finally { Process.GetCurrentProcess().Kill(); }
}
}
@ -2202,7 +2202,7 @@ namespace CodeImp.DoomBuilder
try { WriteLogLine(exceptionmsg); } catch {}
// Try displaying it to the user...
try { MessageBox.Show("Fatal Windows Forms Error", exceptionmsg, MessageBoxButtons.OK, MessageBoxIcon.Stop); }
try { MessageBox.Show(exceptionmsg, "Fatal Non-UI Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); }
finally { Process.GetCurrentProcess().Kill(); }
}
}

View file

@ -83,7 +83,7 @@ namespace CodeImp.DoomBuilder.IO
int width, height;
// Read pixel data
PixelColorBlock pixeldata = ReadAsPixelData(stream, out width, out height);
PixelColor[] pixeldata = ReadAsPixelData(stream, out width, out height);
if(pixeldata != null)
{
try
@ -93,8 +93,10 @@ namespace CodeImp.DoomBuilder.IO
BitmapData bitmapdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
PixelColor* targetdata = (PixelColor*)bitmapdata.Scan0.ToPointer();
// Copy the pixels
General.CopyMemory(targetdata, pixeldata.Pointer, (uint)(width * height * sizeof(PixelColor)));
//mxd. Copy the pixels
int size = pixeldata.Length - 1;
for(PixelColor* cp = targetdata + size; cp >= targetdata; cp--)
*cp = pixeldata[size--];
// Done
bmp.UnlockBits(bitmapdata);
@ -151,7 +153,7 @@ namespace CodeImp.DoomBuilder.IO
// This creates pixel color data from the given data
// Returns null on failure
private unsafe PixelColorBlock ReadAsPixelData(Stream stream, out int width, out int height)
private PixelColor[] ReadAsPixelData(Stream stream, out int width, out int height)
{
// Image will be 128x128
width = 128;
@ -163,8 +165,7 @@ namespace CodeImp.DoomBuilder.IO
#endif
// Allocate memory
PixelColorBlock pixeldata = new PixelColorBlock(width, height);
pixeldata.Clear();
PixelColor[] pixeldata = new PixelColor[width * height];
// Read flat bytes from stream
byte[] bytes = new byte[width * height];
@ -189,11 +190,11 @@ namespace CodeImp.DoomBuilder.IO
// We make the borders slightly brighter and darker
if((py == 0) || (px == 0))
pixeldata.Pointer[p] = bc1;
pixeldata[p] = bc1;
else if((py == 7) || (px == 7))
pixeldata.Pointer[p] = bc2;
pixeldata[p] = bc2;
else
pixeldata.Pointer[p] = bc;
pixeldata[p] = bc;
}
}
}

View file

@ -83,7 +83,7 @@ namespace CodeImp.DoomBuilder.IO
Bitmap bmp;
// Read pixel data
PixelColorBlock pixeldata = ReadAsPixelData(stream, out width, out height);
PixelColor[] pixeldata = ReadAsPixelData(stream, out width, out height);
if(pixeldata != null)
{
try
@ -93,8 +93,10 @@ namespace CodeImp.DoomBuilder.IO
BitmapData bitmapdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
PixelColor* targetdata = (PixelColor*)bitmapdata.Scan0.ToPointer();
// Copy the pixels
General.CopyMemory(targetdata, pixeldata.Pointer, (uint)(width * height * sizeof(PixelColor)));
//mxd. Copy the pixels
int size = pixeldata.Length - 1;
for(PixelColor* cp = targetdata + size; cp >= targetdata; cp--)
*cp = pixeldata[size--];
// Done
bmp.UnlockBits(bitmapdata);
@ -153,7 +155,7 @@ namespace CodeImp.DoomBuilder.IO
// This creates pixel color data from the given data
// Returns null on failure
private PixelColorBlock ReadAsPixelData(Stream stream, out int width, out int height)
private PixelColor[] ReadAsPixelData(Stream stream, out int width, out int height)
{
// Check if the flat is square
float sqrlength = (float)Math.Sqrt(stream.Length);
@ -187,15 +189,14 @@ namespace CodeImp.DoomBuilder.IO
if((width <= 0) || (height <= 0)) return null;
// Allocate memory
PixelColorBlock pixeldata = new PixelColorBlock(width, height);
pixeldata.Clear();
PixelColor[] pixeldata = new PixelColor[width * height];
// Read flat bytes from stream
byte[] bytes = new byte[width * height];
stream.Read(bytes, 0, width * height);
// Convert bytes with palette
for(uint i = 0; i < width * height; i++) pixeldata.Pointer[i] = palette[bytes[i]];
for(uint i = 0; i < width * height; i++) pixeldata[i] = palette[bytes[i]];
// Return pointer
return pixeldata;

View file

@ -102,7 +102,7 @@ namespace CodeImp.DoomBuilder.IO
Bitmap bmp;
// Read pixel data
PixelColorBlock pixeldata = ReadAsPixelData(stream, out width, out height, out offsetx, out offsety);
PixelColor[] pixeldata = ReadAsPixelData(stream, out width, out height, out offsetx, out offsety);
if(pixeldata != null)
{
// Create bitmap and lock pixels
@ -112,8 +112,10 @@ namespace CodeImp.DoomBuilder.IO
BitmapData bitmapdata = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
PixelColor* targetdata = (PixelColor*)bitmapdata.Scan0.ToPointer();
// Copy the pixels
General.CopyMemory(targetdata, pixeldata.Pointer, (uint)(width * height * sizeof(PixelColor)));
//mxd. Copy the pixels
int size = pixeldata.Length - 1;
for(PixelColor* cp = targetdata + size; cp >= targetdata; cp--)
*cp = pixeldata[size--];
// Done
bmp.UnlockBits(bitmapdata);
@ -142,7 +144,7 @@ namespace CodeImp.DoomBuilder.IO
int width, height, ox, oy;
// Read pixel data
PixelColorBlock pixeldata = ReadAsPixelData(stream, out width, out height, out ox, out oy);
PixelColor[] pixeldata = ReadAsPixelData(stream, out width, out height, out ox, out oy);
if(pixeldata != null)
{
// Go for all source pixels
@ -152,22 +154,26 @@ namespace CodeImp.DoomBuilder.IO
for(oy = 0; oy < height; oy++)
{
// Copy this pixel?
if(pixeldata.Pointer[oy * width + ox].a > 0.5f)
if(pixeldata[oy * width + ox].a > 0.5f)
{
// Calculate target pixel and copy when within bounds
int tx = x + ox;
int ty = y + oy;
if((tx >= 0) && (tx < targetwidth) && (ty >= 0) && (ty < targetheight))
target[ty * targetwidth + tx] = pixeldata.Pointer[oy * width + ox];
target[ty * targetwidth + tx] = pixeldata[oy * width + ox];
}
}
}
}
else
{
throw new InvalidDataException("Failed to read pixeldata"); //mxd. Let's throw exception on failure
}
}
// This creates pixel color data from the given data
// Returns null on failure
private PixelColorBlock ReadAsPixelData(Stream stream, out int width, out int height, out int offsetx, out int offsety)
private PixelColor[] ReadAsPixelData(Stream stream, out int width, out int height, out int offsetx, out int offsety)
{
BinaryReader reader = new BinaryReader(stream);
@ -200,8 +206,7 @@ namespace CodeImp.DoomBuilder.IO
for(int x = 0; x < width; x++) columns[x] = reader.ReadInt32();
// Allocate memory
PixelColorBlock pixeldata = new PixelColorBlock(width, height);
pixeldata.Clear();
PixelColor[] pixeldata = new PixelColor[width * height];
// Go for all columns
for(int x = 0; x < width; x++)
@ -228,8 +233,12 @@ namespace CodeImp.DoomBuilder.IO
// Read pixel color index
int p = reader.ReadByte();
//mxd. Sanity check required...
int offset = (y + yo) * width + x;
if(offset > pixeldata.Length - 1) return null;
// Draw pixel
pixeldata.Pointer[(y + yo) * width + x] = palette[p];
pixeldata[offset] = palette[p];
}
// Skip unused pixel
@ -237,7 +246,7 @@ namespace CodeImp.DoomBuilder.IO
// Read next post start
read_y = reader.ReadByte();
if(read_y < y || (height > 255 && read_y == y)) y += read_y; else y = read_y; //mxd. Fix for tall patches higher than 508 pixels
if(read_y < y || (height > 256 && read_y == y)) y += read_y; else y = read_y; //mxd. Fix for tall patches higher than 508 pixels
}
}

View file

@ -1,85 +0,0 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Runtime.InteropServices;
#endregion
namespace CodeImp.DoomBuilder.Rendering
{
public unsafe class PixelColorBlock
{
#region ================== Variables
private int width;
private int height;
private int memorysize;
private PixelColor* memory;
#endregion
#region ================== Properties
public int Width { get { return width; } }
public int Height { get { return height; } }
public int Length { get { return memorysize; } }
public PixelColor this[int index] { get { return memory[index]; } set { memory[index] = value; } }
public PixelColor* Pointer { get { return memory; } }
#endregion
#region ================== Constructor / Destructor
// Constructor
public PixelColorBlock(int width, int height)
{
// Check input
if((width <= 0) || (height <= 0)) throw new ArgumentException("Cannot allocate a memory block of zero size!");
// Initialize
this.width = width;
this.height = height;
this.memorysize = width * height * sizeof(PixelColor);
this.memory = (PixelColor*)Marshal.AllocCoTaskMem(memorysize);
if(this.memory == (PixelColor*)0) throw new OutOfMemoryException();
GC.AddMemoryPressure(memorysize);
}
// Destructor
~PixelColorBlock()
{
// Terminate
Marshal.FreeCoTaskMem(new IntPtr(memory));
GC.RemoveMemoryPressure(memorysize);
memorysize = 0;
}
#endregion
#region ================== Methods
// This clears the memory black
public void Clear()
{
if(memorysize > 0) General.ZeroMemory(new IntPtr(memory), memorysize);
}
#endregion
}
}