GPU: Avoid spline crashes on bad data.

If we get 0 prims, we can generate confusing index bounds and go out of
bounds.  Similarly, if we get a crazy number of control points and fail to
allocate, we can crash.
This commit is contained in:
Unknown W. Brackets 2022-01-01 14:14:33 -08:00
parent 12405709f0
commit e82fd3bd33
3 changed files with 16 additions and 6 deletions

View File

@ -321,7 +321,8 @@ ControlPoints::ControlPoints(const SimpleVertex *const *points, int size, Simple
pos = (Vec3f *)managedBuf.Allocate(sizeof(Vec3f) * size);
tex = (Vec2f *)managedBuf.Allocate(sizeof(Vec2f) * size);
col = (Vec4f *)managedBuf.Allocate(sizeof(Vec4f) * size);
Convert(points, size);
if (pos && tex && col)
Convert(points, size);
}
void ControlPoints::Convert(const SimpleVertex *const *points, int size) {
@ -554,7 +555,10 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic
HardwareTessellation(output, surface, origVertType, points, tessDataTransfer);
} else {
ControlPoints cpoints(points, num_points, managedBuf);
SoftwareTessellation(output, surface, origVertType, cpoints);
if (cpoints.IsValid())
SoftwareTessellation(output, surface, origVertType, cpoints);
else
ERROR_LOG(G3D, "Failed to allocate space for control point values, skipping curve draw");
}
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
@ -571,7 +575,8 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic
uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode());
int generatedBytesRead;
DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, gstate.getCullMode(), &generatedBytesRead);
if (output.count)
DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, gstate.getCullMode(), &generatedBytesRead);
DispatchFlush();

View File

@ -186,14 +186,17 @@ struct Weight2D {
};
struct ControlPoints {
Vec3f *pos;
Vec2f *tex;
Vec4f *col;
Vec3f *pos = nullptr;
Vec2f *tex = nullptr;
Vec4f *col = nullptr;
u32_le defcolor;
ControlPoints() {}
ControlPoints(const SimpleVertex *const *points, int size, SimpleBufferManager &managedBuf);
void Convert(const SimpleVertex *const *points, int size);
bool IsValid() const {
return pos && tex && col;
}
};
struct OutputBuffers {

View File

@ -329,6 +329,8 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) {
u32 count = data & 0xFFFF;
// Upper bits are ignored.
GEPrimitiveType prim = static_cast<GEPrimitiveType>((data >> 16) & 7);
if (count == 0)
break;
if (!Memory::IsValidAddress(gstate_c.vertexAddr)) {
ERROR_LOG_REPORT(G3D, "Software: Bad vertex address %08x!", gstate_c.vertexAddr);