forked from fte/fteqw
1
0
Fork 0

Added support for MST_PATCH_FIXED=256 for fixed-tessellation patches.

Also enforce some sanity limits for bsp lump sizes, to avoid int overflows.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5462 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2019-05-23 19:06:04 +00:00
parent 3c5518afa8
commit 81b3749a71
3 changed files with 261 additions and 95 deletions

View File

@ -32,13 +32,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//FIXME: make sure that any 16bit indexes are bounded properly //FIXME: make sure that any 16bit indexes are bounded properly
//FIXME: ensure that we don't get any count*size overflows //FIXME: ensure that we don't get any count*size overflows
#define SANITY_MAX_MAP_PLANES 65536*64 //sanity #define SANITY_LIMIT(t) ((unsigned int)(0x7fffffffu/sizeof(t))) //sanity limit for the array, to ensure a 32bit value cannot overflow us.
#define SANITY_MAX_MAP_NODES 65536*64 //sanity //#define SANITY_MAX_MAP_PLANES 65536*64 //sanity
//#define SANITY_MAX_MAP_NODES 65536*64 //sanity
//#define SANITY_MAX_MAP_CLIPNODES 65536*64 //sanity //#define SANITY_MAX_MAP_CLIPNODES 65536*64 //sanity
//#define MAX_MAP_LEAFS 1 //pvs buffer size. not sanity. //#define MAX_MAP_LEAFS 1 //pvs buffer size. not sanity.
#define SANITY_MAX_MAP_LEAFS 65536*64 //too many leafs results in massive amounts of ram used for pvs/phs caches. //#define SANITY_MAX_MAP_LEAFS 65536*64 //too many leafs results in massive amounts of ram used for pvs/phs caches.
//#define SANITY_MAX_MAP_VERTS 65536 //sanity //#define SANITY_MAX_MAP_VERTS 65536 //sanity
#define SANITY_MAX_MAP_FACES 65536*64 //sanity //#define SANITY_MAX_MAP_FACES 65536*64 //sanity
//#define MAX_MAP_MARKSURFACES 65536 //sanity //#define MAX_MAP_MARKSURFACES 65536 //sanity
//#define MAX_MAP_TEXINFO 4096 //sanity //#define MAX_MAP_TEXINFO 4096 //sanity
//#define MAX_MAP_EDGES 256000 //#define MAX_MAP_EDGES 256000
@ -838,7 +839,9 @@ enum q3surfacetype
MST_PLANAR=1, MST_PLANAR=1,
MST_PATCH=2, MST_PATCH=2,
MST_TRIANGLE_SOUP=3, MST_TRIANGLE_SOUP=3,
MST_FLARE=4 MST_FLARE=4,
MST_FOLIAGE=5, //added in wolf/et
MST_PATCH_FIXED=256 //fte, fixed tessellation. Uses high parts of surf->patchwidth/height. if 0 then uses exact CPs instead.
}; };
typedef struct typedef struct

View File

@ -589,6 +589,13 @@ static void Patch_Evaluate( const vec_t *p, const unsigned short *numcp, const i
const vec_t *pv[3][3]; const vec_t *pv[3][3];
vec4_t v1, v2, v3; vec4_t v1, v2, v3;
if (!tess[0] || !tess[1])
{ //not really a patch
for( i = 0; i < comp*numcp[1]*numcp[0]; i++ )
dest[i] = p[i];
return;
}
num_patches[0] = numcp[0] / 2; num_patches[0] = numcp[0] / 2;
num_patches[1] = numcp[1] / 2; num_patches[1] = numcp[1] / 2;
dstpitch = ( num_patches[0] * tess[0] + 1 ) * comp; dstpitch = ( num_patches[0] * tess[0] + 1 ) * comp;
@ -861,16 +868,36 @@ static void CM_CreatePatch(model_t *loadmodel, q3cpatch_t *patch, q2mapsurface_t
vec3_t tverts[4]; vec3_t tverts[4];
qbyte *data; qbyte *data;
mplane_t *brushplanes; mplane_t *brushplanes;
float subdivlevel;
patch->surface = shaderref; patch->surface = shaderref;
if (patch_subdiv)
{ //fixed
step[0] = patch_subdiv[0];
step[1] = patch_subdiv[1];
}
else
{
// find the degree of subdivision in the u and v directions // find the degree of subdivision in the u and v directions
Patch_GetFlatness( cm_subdivlevel, verts, sizeof(vecV_t)/sizeof(vec_t), patch_cp, flat ); subdivlevel = cm_subdivlevel;//r_subdivisions.value;
if ( subdivlevel < 1 )
subdivlevel = 1;
Patch_GetFlatness( subdivlevel, verts, sizeof(vecV_t)/sizeof(vec_t), patch_cp, flat );
step[0] = 1 << flat[0]; step[0] = 1 << flat[0];
step[1] = 1 << flat[1]; step[1] = 1 << flat[1];
}
if (!step[0] || !step[1])
{
size[0] = patch_cp[0];
size[1] = patch_cp[1];
}
else
{
size[0] = ( patch_cp[0] >> 1 ) * step[0] + 1; size[0] = ( patch_cp[0] >> 1 ) * step[0] + 1;
size[1] = ( patch_cp[1] >> 1 ) * step[1] + 1; size[1] = ( patch_cp[1] >> 1 ) * step[1] + 1;
}
if( size[0] <= 0 || size[1] <= 0 ) if( size[0] <= 0 || size[1] <= 0 )
return; return;
@ -1052,6 +1079,7 @@ static qboolean CM_CreatePatchForFace (model_t *loadmodel, cminfo_t *prv, mleaf_
break; break;
case MST_PATCH: case MST_PATCH:
case MST_PATCH_FIXED:
if (face->patch.cp[0] <= 0 || face->patch.cp[1] <= 0) if (face->patch.cp[0] <= 0 || face->patch.cp[1] <= 0)
return true; return true;
@ -1089,7 +1117,7 @@ static qboolean CM_CreatePatchForFace (model_t *loadmodel, cminfo_t *prv, mleaf_
checkout[facenum] = prv->numpatches++; checkout[facenum] = prv->numpatches++;
//gcc warns without this cast //gcc warns without this cast
CM_CreatePatch (loadmodel, patch, surf, (const vec_t *)(prv->verts + face->firstvert), face->patch.cp, face->patch.fixedres ); CM_CreatePatch (loadmodel, patch, surf, (const vec_t *)(prv->verts + face->firstvert), face->patch.cp, (face->facetype==MST_PATCH_FIXED)?face->patch.fixedres:NULL );
} }
leaf->contents |= patch->surface->c.value; leaf->contents |= patch->surface->c.value;
leaf->numleafpatches++; leaf->numleafpatches++;
@ -1689,7 +1717,7 @@ static qboolean CModQ2_LoadNodes (model_t *mod, qbyte *mod_base, lump_t *l)
Con_Printf (CON_ERROR "Map has no nodes\n"); Con_Printf (CON_ERROR "Map has no nodes\n");
return false; return false;
} }
if (count > SANITY_MAX_MAP_NODES) if (count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "Map has too many nodes\n"); Con_Printf (CON_ERROR "Map has too many nodes\n");
return false; return false;
@ -1803,7 +1831,7 @@ static qboolean CModQ2_LoadLeafs (model_t *mod, qbyte *mod_base, lump_t *l)
return false; return false;
} }
// need to save space for box planes // need to save space for box planes
if (count > SANITY_MAX_MAP_LEAFS) if (count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "Map has too many leafs\n"); Con_Printf (CON_ERROR "Map has too many leafs\n");
return false; return false;
@ -1880,7 +1908,7 @@ static qboolean CModQ2_LoadPlanes (model_t *mod, qbyte *mod_base, lump_t *l)
return false; return false;
} }
// need to save space for box planes // need to save space for box planes
if (count >= SANITY_MAX_MAP_PLANES) if (count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "Map has too many planes (%i)\n", count); Con_Printf (CON_ERROR "Map has too many planes (%i)\n", count);
return false; return false;
@ -2484,7 +2512,7 @@ static qboolean CModQ3_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l)
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count > SANITY_MAX_MAP_FACES) if (count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "Map has too many faces\n"); Con_Printf (CON_ERROR "Map has too many faces\n");
return false; return false;
@ -2502,10 +2530,14 @@ static qboolean CModQ3_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l)
out->numverts = LittleLong ( in->num_vertices ); out->numverts = LittleLong ( in->num_vertices );
out->firstvert = LittleLong ( in->firstvertex ); out->firstvert = LittleLong ( in->firstvertex );
if (out->facetype == MST_PATCH) if (out->facetype == MST_PATCH || out->facetype == MST_PATCH_FIXED)
{ {
out->patch.cp[0] = LittleLong ( in->patchwidth ); unsigned int pw = LittleLong ( in->patchwidth );
out->patch.cp[1] = LittleLong ( in->patchheight ); unsigned int ph = LittleLong ( in->patchheight );
out->patch.cp[0] = pw&0xffff;
out->patch.cp[1] = ph&0xffff;
out->patch.fixedres[0] = pw>>16;
out->patch.fixedres[1] = ph>>16;
} }
else else
{ {
@ -2535,7 +2567,7 @@ static qboolean CModRBSP_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l)
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count > SANITY_MAX_MAP_FACES) if (count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "Map has too many faces\n"); Con_Printf (CON_ERROR "Map has too many faces\n");
return false; return false;
@ -2553,14 +2585,14 @@ static qboolean CModRBSP_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l)
out->numverts = LittleLong ( in->num_vertices ); out->numverts = LittleLong ( in->num_vertices );
out->firstvert = LittleLong ( in->firstvertex ); out->firstvert = LittleLong ( in->firstvertex );
if (out->facetype == MST_PATCH) if (out->facetype == MST_PATCH || out->facetype == MST_PATCH_FIXED)
{ {
unsigned int w = LittleLong ( in->patchwidth ); unsigned int pw = LittleLong ( in->patchwidth );
unsigned int h = LittleLong ( in->patchheight ); unsigned int ph = LittleLong ( in->patchheight );
out->patch.cp[0] = w&0xffff; out->patch.cp[0] = pw&0xffff;
out->patch.cp[1] = h&0xffff; out->patch.cp[1] = ph&0xffff;
out->patch.fixedres[0]=w>>16; out->patch.fixedres[0] = pw>>16;
out->patch.fixedres[1]=h>>16; out->patch.fixedres[1] = ph>>16;
} }
else else
{ {
@ -2661,14 +2693,38 @@ mfog_t *Mod_FogForOrigin(model_t *wmodel, vec3_t org)
static index_t tempIndexesArray[MAX_ARRAY_VERTS*6]; static index_t tempIndexesArray[MAX_ARRAY_VERTS*6];
static void GL_SizePatchFixed(mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert, cminfo_t *prv)
{
unsigned short patch_cp[2];
int step[2], size[2];
patch_cp[0] = patchwidth&0xffff;
patch_cp[1] = patchheight&0xffff;
if (patch_cp[0] <= 0 || patch_cp[1] <= 0 )
{
mesh->numindexes = 0;
mesh->numvertexes = 0;
return;
}
// allocate space for mesh
step[0] = 2;//patchwidth>>16;
step[1] = 2;//patchheight>>16;
size[0] = (patch_cp[0] / 2) * step[0] + 1;
size[1] = (patch_cp[1] / 2) * step[1] + 1;
mesh->numvertexes = size[0] * size[1];
mesh->numindexes = (size[0]-1) * (size[1]-1) * 6;
}
static void GL_SizePatch(mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert, cminfo_t *prv) static void GL_SizePatch(mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert, cminfo_t *prv)
{ {
unsigned short patch_cp[2]; unsigned short patch_cp[2];
int step[2], size[2], flat[2]; int step[2], size[2], flat[2];
float subdivlevel; float subdivlevel;
patch_cp[0] = patchwidth&0xffff; patch_cp[0] = patchwidth;
patch_cp[1] = patchheight&0xffff; patch_cp[1] = patchheight;
if (patch_cp[0] <= 0 || patch_cp[1] <= 0 ) if (patch_cp[0] <= 0 || patch_cp[1] <= 0 )
{ {
@ -2704,8 +2760,8 @@ static void GL_CreateMeshForPatch (model_t *mod, mesh_t *mesh, int patchwidth, i
float subdivlevel; float subdivlevel;
int sty; int sty;
patch_cp[0] = patchwidth&0xffff; patch_cp[0] = patchwidth;
patch_cp[1] = patchheight&0xffff; patch_cp[1] = patchheight;
if (patch_cp[0] <= 0 || patch_cp[1] <= 0 ) if (patch_cp[0] <= 0 || patch_cp[1] <= 0 )
{ {
@ -2799,6 +2855,114 @@ static void GL_CreateMeshForPatch (model_t *mod, mesh_t *mesh, int patchwidth, i
memcpy (mesh->indexes, tempIndexesArray, numindexes * sizeof(index_t) ); memcpy (mesh->indexes, tempIndexesArray, numindexes * sizeof(index_t) );
} }
static void GL_CreateMeshForPatchFixed (model_t *mod, mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert)
{
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
int numindexes, step[2], size[2], i, u, v, p;
unsigned short patch_cp[2];
index_t *indexes;
float subdivlevel;
int sty;
patch_cp[0] = patchwidth&0xffff;
patch_cp[1] = patchheight&0xffff;
if (patch_cp[0] <= 0 || patch_cp[1] <= 0 )
{
mesh->numindexes = 0;
mesh->numvertexes = 0;
return;
}
subdivlevel = r_subdivisions.value;
if ( subdivlevel < 1 )
subdivlevel = 1;
// allocate space for mesh
step[0] = patchwidth>>16;
step[1] = patchheight>>16;
if (!step[0] || !step[1])
{
size[0] = patch_cp[0];
size[1] = patch_cp[0];
}
else
{
size[0] = (patch_cp[0] / 2) * step[0] + 1;
size[1] = (patch_cp[1] / 2) * step[1] + 1;
}
numverts = size[0] * size[1];
if ( numverts < 0 || numverts > MAX_ARRAY_VERTS )
{
mesh->numindexes = 0;
mesh->numvertexes = 0;
return;
}
if (mesh->numvertexes != numverts)
{
mesh->numindexes = 0;
mesh->numvertexes = 0;
return;
}
// fill in
Patch_Evaluate ( prv->verts[firstvert], patch_cp, step, mesh->xyz_array[0], sizeof(vecV_t)/sizeof(vec_t));
for (sty = 0; sty < MAXRLIGHTMAPS; sty++)
{
if (mesh->colors4f_array[sty])
Patch_Evaluate ( prv->colors4f_array[sty][firstvert], patch_cp, step, mesh->colors4f_array[sty][0], 4 );
}
Patch_Evaluate ( prv->normals_array[firstvert], patch_cp, step, mesh->normals_array[0], 3 );
Patch_Evaluate ( prv->vertstmexcoords[firstvert], patch_cp, step, mesh->st_array[0], 2 );
for (sty = 0; sty < MAXRLIGHTMAPS; sty++)
{
if (mesh->lmst_array[sty])
Patch_Evaluate ( prv->vertlstmexcoords[sty][firstvert], patch_cp, step, mesh->lmst_array[sty][0], 2 );
}
// compute new indexes avoiding adding invalid triangles
numindexes = 0;
indexes = tempIndexesArray;
for (v = 0, i = 0; v < size[1]-1; v++)
{
for (u = 0; u < size[0]-1; u++, i += 6)
{
indexes[0] = p = v * size[0] + u;
indexes[1] = p + size[0];
indexes[2] = p + 1;
// if ( !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[1]]) &&
// !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[2]]) &&
// !VectorEquals(mesh->xyz_array[indexes[1]], mesh->xyz_array[indexes[2]]) )
{
indexes += 3;
numindexes += 3;
}
indexes[0] = p + 1;
indexes[1] = p + size[0];
indexes[2] = p + size[0] + 1;
// if ( !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[1]]) &&
// !VectorEquals(mesh->xyz_array[indexes[0]], mesh->xyz_array[indexes[2]]) &&
// !VectorEquals(mesh->xyz_array[indexes[1]], mesh->xyz_array[indexes[2]]) )
{
indexes += 3;
numindexes += 3;
}
}
}
// allocate and fill index table
mesh->numindexes = numindexes;
memcpy (mesh->indexes, tempIndexesArray, numindexes * sizeof(index_t) );
}
#ifdef RFBSPS #ifdef RFBSPS
static void CModRBSP_BuildSurfMesh(model_t *mod, msurface_t *out, builddata_t *bd) static void CModRBSP_BuildSurfMesh(model_t *mod, msurface_t *out, builddata_t *bd)
{ {
@ -2878,15 +3042,19 @@ static void CModRBSP_BuildSurfMesh(model_t *mod, msurface_t *out, builddata_t *b
static void CModQ3_BuildSurfMesh(model_t *mod, msurface_t *out, builddata_t *bd) static void CModQ3_BuildSurfMesh(model_t *mod, msurface_t *out, builddata_t *bd)
{ {
cminfo_t *prv = (cminfo_t*)mod->meshinfo; cminfo_t *prv = (cminfo_t*)mod->meshinfo;
q3dface_t *in = (q3dface_t*)(bd+1);
int idx = (out - mod->surfaces) - mod->firstmodelsurface; int idx = (out - mod->surfaces) - mod->firstmodelsurface;
in += idx; q3dface_t *in = (q3dface_t*)(bd+1) + idx;
int facetype = LittleLong(in->facetype);
if (LittleLong(in->facetype) == MST_PATCH) if (facetype == MST_PATCH)
{ {
GL_CreateMeshForPatch(mod, out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex)); GL_CreateMeshForPatch(mod, out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex));
} }
else if (LittleLong(in->facetype) == MST_PLANAR || LittleLong(in->facetype) == MST_TRIANGLE_SOUP) else if (facetype == MST_PATCH_FIXED)
{
GL_CreateMeshForPatchFixed(mod, out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex));
}
else if (facetype == MST_PLANAR || facetype == MST_TRIANGLE_SOUP)
{ {
unsigned int fv = LittleLong(in->firstvertex), fi = LittleLong(in->firstindex), i; unsigned int fv = LittleLong(in->firstvertex), fi = LittleLong(in->firstindex), i;
for (i = 0; i < out->mesh->numvertexes; i++) for (i = 0; i < out->mesh->numvertexes; i++)
@ -3037,6 +3205,11 @@ static qboolean CModQ3_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
out->mesh = &mesh[surfnum]; out->mesh = &mesh[surfnum];
GL_SizePatch(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex), prv); GL_SizePatch(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex), prv);
} }
else if (facetype == MST_PATCH_FIXED)
{
out->mesh = &mesh[surfnum];
GL_SizePatchFixed(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex), prv);
}
else if (facetype == MST_PLANAR || facetype == MST_TRIANGLE_SOUP) else if (facetype == MST_PLANAR || facetype == MST_TRIANGLE_SOUP)
{ {
out->mesh = &mesh[surfnum]; out->mesh = &mesh[surfnum];
@ -3149,6 +3322,11 @@ static qboolean CModRBSP_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
out->mesh = &mesh[surfnum]; out->mesh = &mesh[surfnum];
GL_SizePatch(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex), prv); GL_SizePatch(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex), prv);
} }
else if (facetype == MST_PATCH_FIXED)
{
out->mesh = &mesh[surfnum];
GL_SizePatchFixed(out->mesh, LittleLong(in->patchwidth), LittleLong(in->patchheight), LittleLong(in->num_vertices), LittleLong(in->firstvertex), prv);
}
else if (facetype == MST_PLANAR || facetype == MST_TRIANGLE_SOUP) else if (facetype == MST_PLANAR || facetype == MST_TRIANGLE_SOUP)
{ {
out->mesh = &mesh[surfnum]; out->mesh = &mesh[surfnum];
@ -3188,7 +3366,7 @@ static qboolean CModQ3_LoadNodes (model_t *loadmodel, qbyte *mod_base, lump_t *l
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
if (count > SANITY_MAX_MAP_NODES) if (count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "Too many nodes on map\n"); Con_Printf (CON_ERROR "Too many nodes on map\n");
return false; return false;
@ -3297,7 +3475,7 @@ static qboolean CModQ3_LoadLeafs (model_t *mod, qbyte *mod_base, lump_t *l)
} }
// need to save space for box planes // need to save space for box planes
if (count > SANITY_MAX_MAP_LEAFS) if (count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "Too many leaves on map"); Con_Printf (CON_ERROR "Too many leaves on map");
return false; return false;
@ -3362,7 +3540,7 @@ static qboolean CModQ3_LoadPlanes (model_t *loadmodel, qbyte *mod_base, lump_t *
} }
count = l->filelen / sizeof(*in); count = l->filelen / sizeof(*in);
if (count > SANITY_MAX_MAP_PLANES) if (count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "Too many planes on map (%i)\n", count); Con_Printf (CON_ERROR "Too many planes on map (%i)\n", count);
return false; return false;

View File

@ -2430,12 +2430,12 @@ qboolean Mod_LoadVertexes (model_t *loadmodel, qbyte *mod_base, lump_t *l)
int i, count; int i, count;
in = (void *)(mod_base + l->fileofs); in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) count = l->filelen / sizeof(*in);
if (l->filelen % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*in);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->vertexes = out; loadmodel->vertexes = out;
@ -2460,12 +2460,12 @@ qboolean Mod_LoadVertexNormals (model_t *loadmodel, bspx_header_t *bspx, qbyte *
if (l) if (l)
{ {
in = (void *)(mod_base + l->fileofs); in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(vec3_t)) count = l->filelen / sizeof(vec3_t);
if (l->filelen % sizeof(*in) || count > SANITY_LIMIT(vec3_t))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(vec3_t);
} }
else else
{ {
@ -3308,12 +3308,12 @@ qboolean Mod_LoadEdges (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
if (lm) if (lm)
{ {
dledge_t *in = (void *)(mod_base + l->fileofs); dledge_t *in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) count = l->filelen / sizeof(*in);
if (l->filelen % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf ("MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name); Con_Printf ("MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*in);
out = ZG_Malloc(&loadmodel->memgroup, (count + 1) * sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, (count + 1) * sizeof(*out));
loadmodel->edges = out; loadmodel->edges = out;
@ -3328,12 +3328,12 @@ qboolean Mod_LoadEdges (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
else else
{ {
dsedge_t *in = (void *)(mod_base + l->fileofs); dsedge_t *in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) count = l->filelen / sizeof(*in);
if (l->filelen % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf ("MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name); Con_Printf ("MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*in);
out = ZG_Malloc(&loadmodel->memgroup, (count + 1) * sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, (count + 1) * sizeof(*out));
loadmodel->edges = out; loadmodel->edges = out;
@ -3363,12 +3363,12 @@ qboolean Mod_LoadMarksurfaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, q
{ {
int *inl; int *inl;
inl = (void *)(mod_base + l->fileofs); inl = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*inl)) count = l->filelen / sizeof(*inl);
if (l->filelen % sizeof(*inl) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*inl);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->marksurfaces = out; loadmodel->marksurfaces = out;
@ -3389,12 +3389,12 @@ qboolean Mod_LoadMarksurfaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, q
{ {
short *ins; short *ins;
ins = (void *)(mod_base + l->fileofs); ins = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*ins)) count = l->filelen / sizeof(*ins);
if (l->filelen % sizeof(*ins) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*ins);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->marksurfaces = out; loadmodel->marksurfaces = out;
@ -3426,12 +3426,12 @@ qboolean Mod_LoadSurfedges (model_t *loadmodel, qbyte *mod_base, lump_t *l)
int *in, *out; int *in, *out;
in = (void *)(mod_base + l->fileofs); in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) count = l->filelen / sizeof(*in);
if (l->filelen % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*in);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->surfedges = out; loadmodel->surfedges = out;
@ -3710,12 +3710,12 @@ static qboolean Mod_LoadSubmodels (model_t *loadmodel, qbyte *mod_base, lump_t *
if (!inq->numfaces) if (!inq->numfaces)
{ {
*hexen2map = true; *hexen2map = true;
if (l->filelen % sizeof(*inh)) count = l->filelen / sizeof(*inh);
if (l->filelen % sizeof(*inh) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*inh);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->submodels = out; loadmodel->submodels = out;
@ -3748,12 +3748,12 @@ static qboolean Mod_LoadSubmodels (model_t *loadmodel, qbyte *mod_base, lump_t *
else else
{ {
*hexen2map = false; *hexen2map = false;
if (l->filelen % sizeof(*inq)) count = l->filelen / sizeof(*inq);
if (l->filelen % sizeof(*inq) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*inq);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->submodels = out; loadmodel->submodels = out;
@ -3799,12 +3799,12 @@ static qboolean Mod_LoadTexinfo (model_t *loadmodel, qbyte *mod_base, lump_t *l)
int miptex; int miptex;
in = (void *)(mod_base + l->fileofs); in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) count = l->filelen / sizeof(*in);
if (l->filelen % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*in);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->texinfo = out; loadmodel->texinfo = out;
@ -3942,23 +3942,23 @@ static qboolean Mod_LoadFaces (model_t *loadmodel, bspx_header_t *bspx, qbyte *m
{ {
ins = NULL; ins = NULL;
inl = (void *)(mod_base + l->fileofs); inl = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*inl)) count = l->filelen / sizeof(*inl);
if (l->filelen % sizeof(*inl) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*inl);
} }
else else
{ {
ins = (void *)(mod_base + l->fileofs); ins = (void *)(mod_base + l->fileofs);
inl = NULL; inl = NULL;
if (l->filelen % sizeof(*ins)) count = l->filelen / sizeof(*ins);
if (l->filelen % sizeof(*ins) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*ins);
} }
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
@ -4106,12 +4106,12 @@ static qboolean Mod_LoadNodes (model_t *loadmodel, qbyte *mod_base, lump_t *l, i
{ {
dl2node_t *in; dl2node_t *in;
in = (void *)(mod_base + l->fileofs); in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) count = l->filelen / sizeof(*in);
if (l->filelen % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*in);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->nodes = out; loadmodel->nodes = out;
@ -4145,12 +4145,12 @@ static qboolean Mod_LoadNodes (model_t *loadmodel, qbyte *mod_base, lump_t *l, i
{ {
dl1node_t *in; dl1node_t *in;
in = (void *)(mod_base + l->fileofs); in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) count = l->filelen / sizeof(*in);
if (l->filelen % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*in);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->nodes = out; loadmodel->nodes = out;
@ -4184,12 +4184,12 @@ static qboolean Mod_LoadNodes (model_t *loadmodel, qbyte *mod_base, lump_t *l, i
{ {
dsnode_t *in; dsnode_t *in;
in = (void *)(mod_base + l->fileofs); in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) count = l->filelen / sizeof(*in);
if (l->filelen % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*in);
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->nodes = out; loadmodel->nodes = out;
@ -4254,17 +4254,12 @@ static qboolean Mod_LoadLeafs (model_t *loadmodel, qbyte *mod_base, lump_t *l, i
{ {
dl2leaf_t *in; dl2leaf_t *in;
in = (void *)ptr; in = (void *)ptr;
if (len % sizeof(*in)) count = len / sizeof(*in);
if (len % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = len / sizeof(*in);
if (count > SANITY_MAX_MAP_LEAFS)
{
Con_Printf (CON_ERROR "Mod_LoadLeafs: %s has more than %i leafs\n",loadmodel->name, SANITY_MAX_MAP_LEAFS);
return false;
}
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->leafs = out; loadmodel->leafs = out;
@ -4318,17 +4313,12 @@ static qboolean Mod_LoadLeafs (model_t *loadmodel, qbyte *mod_base, lump_t *l, i
{ {
dl1leaf_t *in; dl1leaf_t *in;
in = (void *)(ptr); in = (void *)(ptr);
if (len % sizeof(*in)) count = len / sizeof(*in);
if (len % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = len / sizeof(*in);
if (count > SANITY_MAX_MAP_LEAFS)
{
Con_Printf (CON_ERROR "Mod_LoadLeafs: %s has more than %i leafs\n",loadmodel->name, SANITY_MAX_MAP_LEAFS);
return false;
}
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->leafs = out; loadmodel->leafs = out;
@ -4382,17 +4372,12 @@ static qboolean Mod_LoadLeafs (model_t *loadmodel, qbyte *mod_base, lump_t *l, i
{ {
dsleaf_t *in; dsleaf_t *in;
in = (void *)(ptr); in = (void *)(ptr);
if (len % sizeof(*in)) count = len / sizeof(*in);
if (len % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = len / sizeof(*in);
if (count > SANITY_MAX_MAP_LEAFS)
{
Con_Printf (CON_ERROR "Mod_LoadLeafs: %s has more than %i leafs\n",loadmodel->name, SANITY_MAX_MAP_LEAFS);
return false;
}
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->leafs = out; loadmodel->leafs = out;
@ -4538,23 +4523,23 @@ static qboolean Mod_LoadClipnodes (model_t *loadmodel, qbyte *mod_base, lump_t *
{ {
ins = NULL; ins = NULL;
inl = (void *)(mod_base + l->fileofs); inl = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*inl)) count = l->filelen / sizeof(*inl);
if (l->filelen % sizeof(*inl) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*inl);
} }
else else
{ {
ins = (void *)(mod_base + l->fileofs); ins = (void *)(mod_base + l->fileofs);
inl = NULL; inl = NULL;
if (l->filelen % sizeof(*ins)) count = l->filelen / sizeof(*ins);
if (l->filelen % sizeof(*ins) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*ins);
} }
out = ZG_Malloc(&loadmodel->memgroup, (count+numsuplementryclipnodes)*sizeof(*out));//space for both out = ZG_Malloc(&loadmodel->memgroup, (count+numsuplementryclipnodes)*sizeof(*out));//space for both
@ -4830,12 +4815,12 @@ static qboolean Mod_LoadPlanes (model_t *loadmodel, qbyte *mod_base, lump_t *l)
int bits; int bits;
in = (void *)(mod_base + l->fileofs); in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) count = l->filelen / sizeof(*in);
if (l->filelen % sizeof(*in) || count > SANITY_LIMIT(*out))
{ {
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false; return false;
} }
count = l->filelen / sizeof(*in);
out = ZG_Malloc(&loadmodel->memgroup, (count+numsuplementryplanes)*2*sizeof(*out)); out = ZG_Malloc(&loadmodel->memgroup, (count+numsuplementryplanes)*2*sizeof(*out));
loadmodel->planes = out; loadmodel->planes = out;