Fix TNT floodfill crash

This commit is contained in:
jacksonmj 2014-05-22 15:27:18 +01:00
parent 91b4d1bf23
commit 5e02073a2f
3 changed files with 148 additions and 67 deletions

View File

@ -0,0 +1,74 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Simulation_CoordStack_h
#define Simulation_CoordStack_h
#include "Config.h" // for XRES and YRES
#include <exception>
class CoordStackOverflowException: public std::exception
{
public:
CoordStackOverflowException() { }
virtual const char* what() const throw()
{
return "Maximum number of entries in the coordinate stack was exceeded";
}
~CoordStackOverflowException() throw() {};
};
class CoordStack
{
private:
unsigned short (*stack)[2];
int stack_size;
const static int stack_limit = XRES*YRES;
public:
CoordStack() :
stack(NULL),
stack_size(0)
{
stack = (unsigned short(*)[2])(malloc(sizeof(unsigned short)*2*stack_limit));
}
~CoordStack()
{
if (stack) free(stack);
}
void push(int x, int y)
{
if (stack_size>=stack_limit)
throw CoordStackOverflowException();
stack[stack_size][0] = x;
stack[stack_size][1] = y;
stack_size++;
}
void pop(int& x, int& y)
{
stack_size--;
x = stack[stack_size][0];
y = stack[stack_size][1];
}
int getSize() const
{
return stack_size;
}
void clear()
{
stack_size = 0;
}
};
#endif

View File

@ -13,6 +13,7 @@
#include "Air.h" #include "Air.h"
#include "Gravity.h" #include "Gravity.h"
#include "elements/Element.h" #include "elements/Element.h"
#include "CoordStack.h"
//#include "graphics/Renderer.h" //#include "graphics/Renderer.h"
//#include "graphics/Graphics.h" //#include "graphics/Graphics.h"
@ -379,78 +380,85 @@ bool Simulation::FloodFillPmapCheck(int x, int y, int type)
return (pmap[y][x]&0xFF) == type; return (pmap[y][x]&0xFF) == type;
} }
int Simulation::flood_prop_2(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype, int parttype, char * bitmap)
{
int x1, x2, i, dy = 1;
x1 = x2 = x;
while (x1>=CELL)
{
if (!FloodFillPmapCheck(x1-1, y, parttype) || bitmap[(y*XRES)+x1-1])
{
break;
}
x1--;
}
while (x2<XRES-CELL)
{
if (!FloodFillPmapCheck(x2+1, y, parttype) || bitmap[(y*XRES)+x2+1])
{
break;
}
x2++;
}
for (x=x1; x<=x2; x++)
{
i = pmap[y][x];
if (!i)
i = photons[y][x];
if (!i)
continue;
switch (proptype) {
case StructProperty::Float:
*((float*)(((char*)&parts[i>>8])+propoffset)) = propvalue.Float;
break;
case StructProperty::ParticleType:
case StructProperty::Integer:
*((int*)(((char*)&parts[i>>8])+propoffset)) = propvalue.Integer;
break;
case StructProperty::UInteger:
*((unsigned int*)(((char*)&parts[i>>8])+propoffset)) = propvalue.UInteger;
break;
default:
break;
}
bitmap[(y*XRES)+x] = 1;
}
if (y>=CELL+dy)
for (x=x1; x<=x2; x++)
if (FloodFillPmapCheck(x, y-dy, parttype) && !bitmap[((y-dy)*XRES)+x])
if (!flood_prop_2(x, y-dy, propoffset, propvalue, proptype, parttype, bitmap))
return 0;
if (y<YRES-CELL-dy)
for (x=x1; x<=x2; x++)
if (FloodFillPmapCheck(x, y+dy, parttype) && !bitmap[((y+dy)*XRES)+x])
if (!flood_prop_2(x, y+dy, propoffset, propvalue, proptype, parttype, bitmap))
return 0;
return 1;
}
int Simulation::flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype) int Simulation::flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype)
{ {
int r = 0; int i, x1, x2, dy = 1;
char * bitmap = (char *)malloc(XRES*YRES); //Bitmap for checking int did_something = 0;
memset(bitmap, 0, XRES*YRES); int r = pmap[y][x];
r = pmap[y][x];
if (!r) if (!r)
r = photons[y][x]; r = photons[y][x];
if (!r) if (!r)
return 1; return 0;
flood_prop_2(x, y, propoffset, propvalue, proptype, r&0xFF, bitmap); int parttype = (r&0xFF);
char * bitmap = (char*)malloc(XRES*YRES); //Bitmap for checking
if (!bitmap) return -1;
memset(bitmap, 0, XRES*YRES);
try
{
CoordStack cs;
cs.push(x, y);
do
{
cs.pop(x, y);
x1 = x2 = x;
x1 = x2 = x;
while (x1>=CELL)
{
if (!FloodFillPmapCheck(x1-1, y, parttype) || bitmap[(y*XRES)+x1-1])
break;
x1--;
}
while (x2<XRES-CELL)
{
if (!FloodFillPmapCheck(x2+1, y, parttype) || bitmap[(y*XRES)+x2+1])
break;
x2++;
}
for (x=x1; x<=x2; x++)
{
i = pmap[y][x];
if (!i)
i = photons[y][x];
if (!i)
continue;
switch (proptype) {
case StructProperty::Float:
*((float*)(((char*)&parts[i>>8])+propoffset)) = propvalue.Float;
break;
case StructProperty::ParticleType:
case StructProperty::Integer:
*((int*)(((char*)&parts[i>>8])+propoffset)) = propvalue.Integer;
break;
case StructProperty::UInteger:
*((unsigned int*)(((char*)&parts[i>>8])+propoffset)) = propvalue.UInteger;
break;
default:
break;
}
bitmap[(y*XRES)+x] = 1;
did_something = 1;
}
if (y>=CELL+dy)
for (x=x1; x<=x2; x++)
if (FloodFillPmapCheck(x, y-dy, parttype) && !bitmap[((y-dy)*XRES)+x])
cs.push(x, y-dy);
if (y<YRES-CELL-dy)
for (x=x1; x<=x2; x++)
if (FloodFillPmapCheck(x, y+dy, parttype) && !bitmap[((y+dy)*XRES)+x])
cs.push(x, y+dy);
} while (cs.getSize()>0);
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
free(bitmap);
return -1;
}
free(bitmap); free(bitmap);
return 0; return did_something;
} }
SimulationSample Simulation::GetSample(int x, int y) SimulationSample Simulation::GetSample(int x, int y)

View File

@ -135,7 +135,6 @@ public:
void kill_part(int i); void kill_part(int i);
bool FloodFillPmapCheck(int x, int y, int type); bool FloodFillPmapCheck(int x, int y, int type);
int flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype); int flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype);
int flood_prop_2(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype, int parttype, char * bitmap);
int flood_water(int x, int y, int i, int originaly, int check); int flood_water(int x, int y, int i, int originaly, int check);
int FloodINST(int x, int y, int fullc, int cm); int FloodINST(int x, int y, int fullc, int cm);
void detach(int i); void detach(int i);