Skip to content

Commit

Permalink
Further tweaks and improvements to fakeradio shadow edges. Fixed a co…
Browse files Browse the repository at this point in the history
…uple of issues when dealing with maps with geometry bugs (e.g. E4M1).

Fixed a buffer overflow vulnerability in P_IsValidControl().
  • Loading branch information
danij committed Apr 23, 2007
1 parent 9076def commit 4290e77
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 71 deletions.
2 changes: 1 addition & 1 deletion doomsday/engine/portable/include/r_shadow.h
Expand Up @@ -4,6 +4,7 @@
* Online License Link: http://www.gnu.org/licenses/gpl.html
*
*\author Copyright © 2004-2006 Jaakko Keränen <skyjake@dengine.net>
*\author Copyright © 2006-2007 Daniel Swanson <danij@dengine.net>
*
* 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
Expand All @@ -29,7 +30,6 @@
#define __DOOMSDAY_REFRESH_SHADOW_H__

void R_InitSectorShadows(void);
line_t *R_GetShadowNeighbor(shadowpoly_t *poly, boolean left);
sector_t *R_GetShadowSector(shadowpoly_t *poly, uint plane,
boolean getLinked);

Expand Down
11 changes: 8 additions & 3 deletions doomsday/engine/portable/src/p_control.c
Expand Up @@ -436,10 +436,10 @@ static void controlImpulse(int player, impulse_t impulse)
boolean P_IsValidControl(const char *cmd)
{
char name[20], *ptr;
uint idx;
uint i, idx;
int console, localPlayer = 0;

// Check the prefix to see what will be the new state of the
// Check the prefix to see what will be the new state of the
// toggle.
if(cmd[0] == '+' || cmd[0] == '-')
{
Expand All @@ -450,8 +450,13 @@ boolean P_IsValidControl(const char *cmd)
}

// Copy the name of the control and find the end.
for(ptr = name; *cmd && *cmd != '/'; cmd++)
for(ptr = name, i = 0; *cmd && *cmd != '/'; cmd++, ++i)
{
if(i >= 20)
return false;

*ptr++ = *cmd;
}
*ptr++ = 0;

// Is the local player number specified?
Expand Down
67 changes: 26 additions & 41 deletions doomsday/engine/portable/src/r_shadow.c
Expand Up @@ -140,19 +140,6 @@ void R_ShadowDelta(pvec2_t delta, line_t *line, sector_t *frontSector)
}
}

side_t *R_GetShadowLineSide(shadowpoly_t *poly)
{
return (poly->seg->linedef->sides[poly->flags & SHPF_FRONTSIDE ? FRONT : BACK]);
}

line_t *R_GetShadowNeighbor(shadowpoly_t *poly, boolean left)
{
return R_FindLineNeighbor(poly->ssec->sector, poly->seg->linedef,
poly->seg->linedef->
vo[!left^(poly->flags & SHPF_FRONTSIDE ? FRONT : BACK)],
left, NULL);
}

/**
* Returns a pointer to the sector the shadow polygon belongs in.
*/
Expand All @@ -168,12 +155,15 @@ boolean R_ShadowCornerDeltas(pvec2_t left, pvec2_t right, shadowpoly_t *poly,
{
sector_t *sector = R_GetShadowSector(poly, 0, false);
line_t *neighbor;
int side = !(poly->flags & SHPF_FRONTSIDE);

// The line itself.
R_ShadowDelta(leftCorner ? right : left, poly->seg->linedef, sector);

// The neighbor.
neighbor = R_GetShadowNeighbor(poly, leftCorner);
neighbor = R_FindLineNeighbor(poly->ssec->sector, poly->seg->linedef,
poly->seg->linedef->vo[side^!leftCorner],
!leftCorner, NULL);
if(!neighbor)
{
// Should never happen...
Expand Down Expand Up @@ -214,7 +204,7 @@ float R_ShadowEdgeWidth(const pvec2_t edge)
}

/**
* Sets the shadow edge offsets. If the associated line does not have
* Sets the shadow edge offsets. If the associated line does not have
* neighbors, it can't have a shadow.
*/
void R_ShadowEdges(shadowpoly_t *poly)
Expand All @@ -229,18 +219,21 @@ void R_ShadowEdges(shadowpoly_t *poly)
for(edge = 0; edge < 2; ++edge) // left and right
{
// The inside corner:
R_ShadowCornerDeltas(left, right, poly, edge == 0);
R_CornerNormalPoint(left, R_ShadowEdgeWidth(left), right,
R_ShadowEdgeWidth(right), poly->inoffset[edge],
edge == 0 ? poly->extoffset[edge] : NULL,
edge == 1 ? poly->extoffset[edge] : NULL);

// Now any additional extended offsets (the normal is the angle of
// each line
if(R_ShadowCornerDeltas(left, right, poly, edge == 0))
{
R_CornerNormalPoint(left, R_ShadowEdgeWidth(left), right,
R_ShadowEdgeWidth(right), poly->inoffset[edge],
edge == 0 ? poly->extoffset[edge] : NULL,
edge == 1 ? poly->extoffset[edge] : NULL);
}
else
{ // An error in the map. Set the inside corner to the extoffset.
V2_Copy(poly->inoffset[edge], poly->extoffset[edge]);
}

// The back extended offset(s):
// Determine how many we'll need.
base = R_GetVtxLineOwner(line->v[edge^side],
line);
base = R_GetVtxLineOwner(line->v[edge^side], line);
count = 0;
done = false;
p = base->link[!edge];
Expand Down Expand Up @@ -463,15 +456,8 @@ boolean R_ResolveStep(const pvec2_t outer, const pvec2_t inner,
if(span == 0)
return false;

// if(distance <= RESOLVE_STEP * 2)
//{
distance /= 2;
iterCont = false;
/* }
else
{
distance -= RESOLVE_STEP;
} */

V2_Scale(offset, distance / span);
return iterCont;
Expand All @@ -495,7 +481,7 @@ void R_ResolveOverlaps(shadowpoly_t *polys, uint count, sector_t *sector)
boolean done;
int tries;
uint i, k;
boundary_t *bound; //, *other;
boundary_t *bound;
float s, t;
vec2_t a, b;
line_t *line;
Expand Down Expand Up @@ -536,8 +522,6 @@ void R_ResolveOverlaps(shadowpoly_t *polys, uint count, sector_t *sector)
// Find the overlaps.
for(i = 0, bound = boundaries; i < count; ++i, bound++)
{
/*for(k = 0, other = boundaries; k < count; ++k, other++) */

for(k = 0; k < sector->linecount; ++k)
{
//if(i == k) continue;
Expand All @@ -555,14 +539,12 @@ void R_ResolveOverlaps(shadowpoly_t *polys, uint count, sector_t *sector)
V2_Set(b, line->v[1]->pos[VX], line->v[1]->pos[VY]);

// Try the left edge of the shadow.
V2_Intercept2(bound->left, bound->a, a /*other->left */ ,
b /*other->right */ , NULL, &s, &t);
V2_Intercept2(bound->left, bound->a, a, b, NULL, &s, &t);
if(s > 0 && s < 1 && t >= EPSILON && t <= 1 - EPSILON)
overlaps[i] |= OVERLAP_LEFT;

// Try the right edge of the shadow.
V2_Intercept2(bound->right, bound->b, a /*other->left */ ,
b /*other->right */ , NULL, &s, &t);
V2_Intercept2(bound->right, bound->b, a, b, NULL, &s, &t);
if(s > 0 && s < 1 && t >= EPSILON && t <= 1 - EPSILON)
overlaps[i] |= OVERLAP_RIGHT;
}
Expand All @@ -573,12 +555,15 @@ void R_ResolveOverlaps(shadowpoly_t *polys, uint count, sector_t *sector)
{
if(overlaps[i] & OVERLAP_LEFT)
{
if(R_ResolveStep(bound->left, bound->a, polys[i].inoffset[0]))
if(R_ResolveStep(bound->left, bound->a,
polys[i].inoffset[0]))
done = false;
}

if(overlaps[i] & OVERLAP_RIGHT)
{
if(R_ResolveStep(bound->right, bound->b, polys[i].inoffset[1]))
if(R_ResolveStep(bound->right, bound->b,
polys[i].inoffset[1]))
done = false;
}
}
Expand Down
86 changes: 60 additions & 26 deletions doomsday/engine/portable/src/rend_fakeradio.c
Expand Up @@ -307,7 +307,7 @@ static void Rend_RadioScanNeighbor(boolean scanTop, line_t *line, uint side,
if(!stopScan)
{
// This line will attribute to this seg's shadow edge.
// Store indentity for later use.
// Store identity for later use.
edge->diff = diff;
edge->line = iter;
edge->sector = scanSector;
Expand Down Expand Up @@ -365,7 +365,7 @@ static void Rend_RadioScanNeighbor(boolean scanTop, line_t *line, uint side,
}
}

// Time to stop scanning?
// Time to stop?
if(iter == line)
{
stopScan = true;
Expand All @@ -387,12 +387,16 @@ static void Rend_RadioScanNeighbor(boolean scanTop, line_t *line, uint side,
// A height difference from the start sector?
if(scanTop)
{
if(scanSector->SP_ceilvisheight != fCeil)
if(scanSector->SP_ceilvisheight != fCeil &&
scanSector->SP_floorvisheight <
startSector->SP_ceilvisheight)
stopScan = true;
}
else
{
if(scanSector->SP_floorvisheight != fFloor)
if(scanSector->SP_floorvisheight != fFloor &&
scanSector->SP_ceilvisheight >
startSector->SP_floorvisheight)
stopScan = true;
}
}
Expand All @@ -417,9 +421,19 @@ static void Rend_RadioScanNeighbor(boolean scanTop, line_t *line, uint side,
(!scanTop && scanSector->SP_floorvisheight ==
startSector->SP_floorvisheight)))
{
// Into the back neighbor sector.
own = own->link[clockwise];
startSector = scanSector;
// If the map is formed correctly, we should find a back
// neighbor attached to this line. However, if this is not
// the case and a line which SHOULD be two sided isn't, we
// need to check whether there is a valid neighbor.
line_t *backNeighbor =
R_FindLineNeighbor(startSector, iter, own, !toLeft, NULL);

if(backNeighbor && backNeighbor != iter)
{
// Into the back neighbor sector.
own = own->link[clockwise];
startSector = scanSector;
}
}

// The last line was co-alignable so apply any length delta.
Expand Down Expand Up @@ -1127,13 +1141,13 @@ static uint radioEdgeHackType(line_t *line, sector_t *front, sector_t *back,
return 3; // Consider it fully open.
}
else
return 1; // Consider it fully closed.
return 1; // Consider it fully closed.

// Check for unmasked midtextures on twosided lines that completely
// fill the gap between floor and ceiling (we don't want to give away
// the location of any secret areas (false walls)).
if(Rend_DoesMidTextureFillGap(line, backside))
return 1; // Consider it fully closed.
return 1; // Consider it fully closed.

return 0;
}
Expand Down Expand Up @@ -1177,11 +1191,12 @@ static void Rend_RadioAddShadowEdge(shadowpoly_t *shadow, boolean isCeiling,
// Walk around the vertex and choose the bextoffset for the
// back neighbor at which plane heights differ.
lineowner_t *base, *p;
vertex_t *vtx =
shadow->seg->linedef->v[i^!(shadow->flags & SHPF_FRONTSIDE)];
uint id;
boolean found;

base = R_GetVtxLineOwner(shadow->seg->linedef->v[i^!(shadow->flags & SHPF_FRONTSIDE)],
shadow->seg->linedef);
base = R_GetVtxLineOwner(vtx, shadow->seg->linedef);
p = base->link[!i];
id = 0;
found = false;
Expand All @@ -1191,18 +1206,33 @@ static void Rend_RadioAddShadowEdge(shadowpoly_t *shadow, boolean isCeiling,
{
if(!p->line->L_backsector)
{
if((isCeiling && p->line->L_frontsector->SP_ceilvisheight == z) ||
(!isCeiling && p->line->L_frontsector->SP_floorvisheight == z))
if((isCeiling &&
p->line->L_frontsector->SP_ceilvisheight == z) ||
(!isCeiling &&
p->line->L_frontsector->SP_floorvisheight == z))
found = true;
}
else
{
if((isCeiling &&
(p->line->L_frontsector->SP_ceilvisheight < z ||
p->line->L_backsector->SP_ceilvisheight < z)) ||
((p->line->L_frontsector->SP_ceilvisheight < z ||
p->line->L_backsector->SP_ceilvisheight < z) ||
((p->line->v[i^1] == vtx &&
p->line->L_backsector->SP_floorvisheight >=
shadow->ssec->sector->SP_ceilvisheight) ||
(p->line->v[i] == vtx &&
p->line->L_frontsector->SP_floorvisheight >=
shadow->ssec->sector->SP_ceilvisheight)))) ||
(!isCeiling &&
(p->line->L_frontsector->SP_floorvisheight > z ||
p->line->L_backsector->SP_floorvisheight > z)))
((p->line->L_frontsector->SP_floorvisheight > z ||
p->line->L_backsector->SP_floorvisheight > z) ||
((p->line->v[i^1] == vtx &&
p->line->L_backsector->SP_ceilvisheight <=
shadow->ssec->sector->SP_floorvisheight) ||
(p->line->v[i] == vtx &&
p->line->L_frontsector->SP_ceilvisheight <=
shadow->ssec->sector->SP_floorvisheight)))) ||
Rend_DoesMidTextureFillGap(p->line, p->line->v[i] == vtx))
{
found = true;
}
Expand Down Expand Up @@ -1243,7 +1273,7 @@ static void Rend_RadioAddShadowEdge(shadowpoly_t *shadow, boolean isCeiling,
wind = (V2_Distance(inner[1], shadow->outer[1]->pos) >
V2_Distance(inner[0], shadow->outer[0]->pos)? 1 : 0);

// Initialize the rendpoly.
// Initialize the rendpoly.
q = R_AllocRendPoly(RP_FLAT, false, 4);
q->flags = RPF_SHADOW;
memset(&q->tex, 0, sizeof(q->tex));
Expand Down Expand Up @@ -1354,9 +1384,10 @@ BEGIN_PROF( PROF_RADIO_SUBSECTOR );
continue;

line = shadow->seg->linedef;
side = (shadow->flags & SHPF_FRONTSIDE) == 0;

if(line->L_backsector)
{
side = (shadow->flags & SHPF_FRONTSIDE) == 0;
if(subsector->sector->subsgroups[subsector->group].linked[pln] &&
!devNoLinkedSurfaces)
{
Expand Down Expand Up @@ -1394,22 +1425,25 @@ BEGIN_PROF( PROF_RADIO_SUBSECTOR );
// What about the neighbours?
for(i = 0; i < 2; ++i)
{
line = R_GetShadowNeighbor(shadow, i == 0);
if(line && line->L_backsector)
line_t *neighbor =
R_FindLineNeighbor(shadow->ssec->sector, line,
line->vo[side^i], i, NULL);
if(neighbor && neighbor->L_backsector)
{
side = (line->L_frontsector != shadowSec);
front = line->sec[side];
back = line->sec[side ^ 1];
uint side2 = (neighbor->L_frontsector != shadowSec);

front = neighbor->sec[side2];
back = neighbor->sec[side2 ^ 1];
setRelativeHeights(front, back, pln, &fz, &bz, &bhz);

hack = radioEdgeHackType(line, front, back, side, pln, fz, bz);
hack = radioEdgeHackType(neighbor, front, back, side2, pln, fz, bz);
if(hack)
sideOpen[i] = hack - 1;
else
sideOpen[i] = radioEdgeOpenness(fz, bz, bhz);
}
else
sideOpen[i] = 0;
sideOpen[i] = 0;//(!neighbor? 2 : 0);
}

Rend_RadioAddShadowEdge(shadow, pln, 1 - open, sideOpen,
Expand Down

0 comments on commit 4290e77

Please sign in to comment.