Skip to content

Commit ecb685f

Browse files
bugfix(w3ddevice): Prevent crashes and out-of-bounds access in W3DTerrainTracks
1 parent 8503c3b commit ecb685f

1 file changed

Lines changed: 38 additions & 7 deletions

File tree

Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainTracks.cpp

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -823,8 +823,24 @@ Try improving the fit to vertical surfaces like cliffs.
823823
//check if there is anything to draw and fill vertex buffer
824824
if (m_edgesToFlush >= 2)
825825
{
826+
// Guard against a null vertex buffer (e.g. if ReleaseResources() was called
827+
// without a matching ReAcquireResources() during a device reset).
828+
if (!m_vertexBuffer)
829+
{
830+
m_edgesToFlush = 0;
831+
return;
832+
}
833+
826834
DX8VertexBufferClass::WriteLockClass lockVtxBuffer(m_vertexBuffer);
827835
VertexFormatXYZDUV1 *verts = (VertexFormatXYZDUV1*)lockVtxBuffer.Get_Vertex_Array();
836+
837+
// Guard against a failed buffer lock returning a null pointer.
838+
if (!verts)
839+
{
840+
m_edgesToFlush = 0;
841+
return;
842+
}
843+
828844
trackStartIndex=0;
829845

830846
mod=m_usedModules;
@@ -835,9 +851,17 @@ Try improving the fit to vertical surfaces like cliffs.
835851
Vector3 *endPoint;
836852
Vector2 *endPointUV;
837853

838-
if (mod->m_activeEdgeCount >= 2 && mod->Is_Really_Visible())
854+
// Clamp activeEdgeCount to m_maxTankTrackEdges to prevent writing past the
855+
// end of the vertex buffer when m_maxTankTrackEdges was reduced (e.g. by a
856+
// graphics-detail change) while tracks still hold edges from the old, larger
857+
// limit. This also keeps index within the fixed-size m_edges[] array.
858+
Int activeEdgeCount = mod->m_activeEdgeCount;
859+
if (activeEdgeCount > m_maxTankTrackEdges)
860+
activeEdgeCount = m_maxTankTrackEdges;
861+
862+
if (activeEdgeCount >= 2 && mod->Is_Really_Visible())
839863
{
840-
for (i=0,index=mod->m_bottomIndex; i<mod->m_activeEdgeCount; i++,index++)
864+
for (i=0,index=mod->m_bottomIndex; i<activeEdgeCount; i++,index++)
841865
{
842866
if (index >= m_maxTankTrackEdges)
843867
index=0;
@@ -847,10 +871,10 @@ Try improving the fit to vertical surfaces like cliffs.
847871

848872
distanceFade=1.0f;
849873

850-
if ((mod->m_activeEdgeCount -1 -i) >= m_maxTankTrackOpaqueEdges)// && i < (MAX_PER_TRACK_EDGE_COUNT-FORCE_FADE_AT_EDGE))
874+
if ((activeEdgeCount -1 -i) >= m_maxTankTrackOpaqueEdges)// && i < (MAX_PER_TRACK_EDGE_COUNT-FORCE_FADE_AT_EDGE))
851875
{ //we're getting close to the limit on the number of track pieces allowed
852876
//so force it to fade out.
853-
distanceFade=1.0f-(float)((mod->m_activeEdgeCount -i)-m_maxTankTrackOpaqueEdges)/numFadedEdges;
877+
distanceFade=1.0f-(float)((activeEdgeCount -i)-m_maxTankTrackOpaqueEdges)/numFadedEdges;
854878
}
855879

856880
distanceFade *= mod->m_edges[index].alpha; //adjust fade with distance from start of track
@@ -898,13 +922,20 @@ Try improving the fit to vertical surfaces like cliffs.
898922
DX8Wrapper::Set_Transform(D3DTS_WORLD,mod->Transform);
899923
while (mod)
900924
{
901-
if (mod->m_activeEdgeCount >= 2 && mod->Is_Really_Visible())
925+
// Use the same clamped edge count as the vertex-fill pass above so that
926+
// trackStartIndex stays consistent and we don't read past the index buffer
927+
// (which is only allocated for m_maxTankTrackEdges-1 segments).
928+
Int activeEdgeCount = mod->m_activeEdgeCount;
929+
if (activeEdgeCount > m_maxTankTrackEdges)
930+
activeEdgeCount = m_maxTankTrackEdges;
931+
932+
if (activeEdgeCount >= 2 && mod->Is_Really_Visible())
902933
{
903934
DX8Wrapper::Set_Texture(0,mod->m_stageZeroTexture);
904935
DX8Wrapper::Set_Index_Buffer_Index_Offset(trackStartIndex);
905-
DX8Wrapper::Draw_Triangles( 0,(mod->m_activeEdgeCount-1)*2, 0, mod->m_activeEdgeCount*2);
936+
DX8Wrapper::Draw_Triangles( 0,(activeEdgeCount-1)*2, 0, activeEdgeCount*2);
906937

907-
trackStartIndex += mod->m_activeEdgeCount*2;
938+
trackStartIndex += activeEdgeCount*2;
908939
}
909940
mod=mod->m_nextSystem;
910941
}

0 commit comments

Comments
 (0)