Modeling - Prevent crashes in ChFi3d_Builder::StartSol (#1407)

Guard invalid edges, faces, adaptors, and missing pcurves before they
  are passed to BRepAdaptor_Curve2d or dereferenced during chamfer construction.
When the topology does not provide a valid curve-on-surface, preserve
  the existing state where possible and return false.
This makes an oversized or otherwise invalid chamfer finish with IsDone() == false
  instead of crashing in BRep_Tool::CurveOnSurface.
This commit is contained in:
Pasukhin Dmitry
2026-07-29 19:14:52 +01:00
committed by GitHub
parent d8b85a6626
commit cffb2852ba
@@ -79,6 +79,11 @@ namespace
static inline occ::handle<Geom2d_Curve> getCurveOnSurface(const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace)
{
if (theEdge.IsNull() || theFace.IsNull())
{
return occ::handle<Geom2d_Curve>();
}
double aFirstParam = 0.;
double aLastParam = 0.;
return BRep_Tool::CurveOnSurface(theEdge, theFace, aFirstParam, aLastParam);
@@ -1189,6 +1194,10 @@ bool ChFi3d_Builder::StartSol(
const TopOpeBRepDS_DataStructure& DStr = myDS->ChangeDS();
TopoDS_Face Fref = !HSref.IsNull() ? HSref->Face() : TopoDS_Face();
TopoDS_Face F = TopoDS::Face(DStr.Shape(SD->Index(ons)));
if (F.IsNull())
{
return false;
}
const ChFiDS_CommonPoint& aCommonPoint = SD->Vertex(isfirst, ons);
HSBis.Nullify();
@@ -1209,8 +1218,12 @@ bool ChFi3d_Builder::StartSol(
if (isExtend && !aCommonPoint.Point().IsEqual(CPbis.Point(), 0))
{
// the state is preserved and False is returned (extension by the expected plane).
HS->Initialize(F);
aPCurve = SD->Interference(ons).PCurveOnFace();
if (aPCurve.IsNull())
{
return false;
}
HS->Initialize(F);
// The 2nd point is given by its trace on the support surface
RecS = false;
pons = aPCurve->Value(tns);
@@ -1225,6 +1238,10 @@ bool ChFi3d_Builder::StartSol(
// eventually the support face and(or) the reference face.
const TopoDS_Vertex VCP = aCommonPoint.Vertex();
const TopoDS_Edge EHC = HC->Edge();
if (VCP.IsNull() || EHC.IsNull() || Fref.IsNull() || HSref.IsNull() || HCref.IsNull())
{
return false;
}
// One starts by searching in Fref another edge referencing VCP.
TopoDS_Edge newedge;
TopoDS_Edge edgereg;
@@ -1330,9 +1347,12 @@ bool ChFi3d_Builder::StartSol(
}
else
{
HS->Initialize(Fv);
W = BRep_Tool::Parameter(VCP, newedge);
HCref->Initialize(newedge, Fref);
const occ::handle<Geom2d_Curve> aRefPCurve = getCurveOnSurface(newedge, Fref);
if (aRefPCurve.IsNull())
{
return false;
}
TopoDS_Face newface = Fv;
newface.Orientation(TopAbs_FORWARD);
for (TopExp_Explorer ex(newface, TopAbs_EDGE); ex.More(); ex.Next())
@@ -1343,6 +1363,14 @@ bool ChFi3d_Builder::StartSol(
break;
}
}
const occ::handle<Geom2d_Curve> aNewPCurve = getCurveOnSurface(newedge, Fv);
if (aNewPCurve.IsNull())
{
return false;
}
HS->Initialize(Fv);
W = BRep_Tool::Parameter(VCP, newedge);
HCref->Initialize(newedge, Fref);
HC->Initialize(newedge, Fv);
pons = HC->Value(W);
}
@@ -1363,28 +1391,52 @@ bool ChFi3d_Builder::StartSol(
if (aCommonPoint.IsOnArc())
{
const TopoDS_Edge& anArcEdge = aCommonPoint.Arc();
if (anArcEdge.IsNull())
{
return false;
}
// Lambda to avoid code duplication.
// Sets HS, W, aPCurve and pons to default return values.
auto prepareDefaultReturn = [&]() {
HS->Initialize(F);
W = aCommonPoint.ParameterOnArc();
// Attempts to set HS, W, aPCurve and pons to default return values.
auto prepareDefaultReturn = [&]() -> bool {
aPCurve = getCurveOnSurface(anArcEdge, F);
pons = aPCurve->Value(W);
if (aPCurve.IsNull())
{
return false;
}
HS->Initialize(F);
W = aCommonPoint.ParameterOnArc();
pons = aPCurve->Value(W);
return true;
};
if (decroch)
{
HS->Initialize(Fref);
W = aCommonPoint.ParameterOnArc();
if (Fref.IsNull())
{
prepareDefaultReturn();
return false;
}
aPCurve = getCurveOnSurface(anArcEdge, Fref);
pons = aPCurve->Value(W);
RecS = true;
if (aPCurve.IsNull())
{
prepareDefaultReturn();
return false;
}
HS->Initialize(Fref);
W = aCommonPoint.ParameterOnArc();
pons = aPCurve->Value(W);
RecS = true;
return true;
}
if (SearchFace(Spine, aCommonPoint, F, Fv))
{
if (Fv.IsNull())
{
prepareDefaultReturn();
return false;
}
HS->Initialize(Fv);
RecS = true;
if (aCommonPoint.IsVertex())
@@ -1420,10 +1472,20 @@ bool ChFi3d_Builder::StartSol(
if (isTangentToArc(aCommonPoint, 0.1))
{
aPCurve = getCurveOnSurface(aCommonPoint.Arc(), F);
HSBis = new BRepAdaptor_Surface(F);
PBis = aPCurve->Value(aCommonPoint.ParameterOnArc());
if (aPCurve.IsNull())
{
prepareDefaultReturn();
return false;
}
HSBis = new BRepAdaptor_Surface(F);
PBis = aPCurve->Value(aCommonPoint.ParameterOnArc());
}
if (newedge.IsNull())
{
prepareDefaultReturn();
return false;
}
aPCurve = getCurveOnSurface(newedge, Fv);
}
else
@@ -1433,6 +1495,11 @@ bool ChFi3d_Builder::StartSol(
Fv.Orientation(TopAbs_FORWARD);
aPCurve = getCurveOnSurface(newedge, Fv);
}
if (aPCurve.IsNull())
{
prepareDefaultReturn();
return false;
}
pons = aPCurve->Value(aCommonPoint.ParameterOnArc());
return true;
}
@@ -1452,6 +1519,11 @@ bool ChFi3d_Builder::StartSol(
}
if (c1obstacle)
{
if (HSref.IsNull() || HCref.IsNull())
{
prepareDefaultReturn();
return false;
}
HS->Initialize(Fv);
HSref->Initialize(F);
W = aCommonPoint.ParameterOnArc();