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,24 +380,38 @@ 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 Simulation::flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype)
{ {
int x1, x2, i, dy = 1; int i, x1, x2, dy = 1;
int did_something = 0;
int r = pmap[y][x];
if (!r)
r = photons[y][x];
if (!r)
return 0;
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; x1 = x2 = x;
while (x1>=CELL) while (x1>=CELL)
{ {
if (!FloodFillPmapCheck(x1-1, y, parttype) || bitmap[(y*XRES)+x1-1]) if (!FloodFillPmapCheck(x1-1, y, parttype) || bitmap[(y*XRES)+x1-1])
{
break; break;
}
x1--; x1--;
} }
while (x2<XRES-CELL) while (x2<XRES-CELL)
{ {
if (!FloodFillPmapCheck(x2+1, y, parttype) || bitmap[(y*XRES)+x2+1]) if (!FloodFillPmapCheck(x2+1, y, parttype) || bitmap[(y*XRES)+x2+1])
{
break; break;
}
x2++; x2++;
} }
for (x=x1; x<=x2; x++) for (x=x1; x<=x2; x++)
@ -424,33 +439,26 @@ int Simulation::flood_prop_2(int x, int y, size_t propoffset, PropertyValue prop
break; break;
} }
bitmap[(y*XRES)+x] = 1; bitmap[(y*XRES)+x] = 1;
did_something = 1;
} }
if (y>=CELL+dy) if (y>=CELL+dy)
for (x=x1; x<=x2; x++) for (x=x1; x<=x2; x++)
if (FloodFillPmapCheck(x, y-dy, parttype) && !bitmap[((y-dy)*XRES)+x]) if (FloodFillPmapCheck(x, y-dy, parttype) && !bitmap[((y-dy)*XRES)+x])
if (!flood_prop_2(x, y-dy, propoffset, propvalue, proptype, parttype, bitmap)) cs.push(x, y-dy);
return 0;
if (y<YRES-CELL-dy) if (y<YRES-CELL-dy)
for (x=x1; x<=x2; x++) for (x=x1; x<=x2; x++)
if (FloodFillPmapCheck(x, y+dy, parttype) && !bitmap[((y+dy)*XRES)+x]) if (FloodFillPmapCheck(x, y+dy, parttype) && !bitmap[((y+dy)*XRES)+x])
if (!flood_prop_2(x, y+dy, propoffset, propvalue, proptype, parttype, bitmap)) cs.push(x, y+dy);
return 0; } while (cs.getSize()>0);
return 1; }
} catch (std::exception& e)
{
int Simulation::flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype) std::cerr << e.what() << std::endl;
{
int r = 0;
char * bitmap = (char *)malloc(XRES*YRES); //Bitmap for checking
memset(bitmap, 0, XRES*YRES);
r = pmap[y][x];
if (!r)
r = photons[y][x];
if (!r)
return 1;
flood_prop_2(x, y, propoffset, propvalue, proptype, r&0xFF, bitmap);
free(bitmap); free(bitmap);
return 0; return -1;
}
free(bitmap);
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);