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)] [DllImport("kernel32.dll", EntryPoint = "RtlZeroMemory", SetLastError = false)]
internal static extern void ZeroMemory(IntPtr dest, int size); internal static extern void ZeroMemory(IntPtr dest, int size);
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)] //[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
internal static extern unsafe void CopyMemory(void* dst, void* src, uint length); //internal static extern unsafe void CopyMemory(void* dst, void* src, uint length);
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true, CallingConvention = CallingConvention.StdCall)] [DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern int SendMessage(IntPtr hwnd, uint Msg, int wParam, int lParam); 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 { WriteLogLine(exceptionmsg); } catch { }
// Try displaying it to the user... // 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(); } finally { Process.GetCurrentProcess().Kill(); }
} }
} }
@ -2202,7 +2202,7 @@ namespace CodeImp.DoomBuilder
try { WriteLogLine(exceptionmsg); } catch {} try { WriteLogLine(exceptionmsg); } catch {}
// Try displaying it to the user... // 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(); } finally { Process.GetCurrentProcess().Kill(); }
} }
} }

View file

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

View file

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

View file

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