From d30f25e6b1a91e5d9de1dd18d3c951274d486103 Mon Sep 17 00:00:00 2001 From: Charlemagne Lasse Date: Wed, 13 Apr 2022 11:54:30 +0200 Subject: [PATCH] 0032931: Modeling Algorithms - Crash in ChFi3d_IsInFront when no face was found The ChFi3d_IsInFront code is currently not handling all the combinations correctly. For example, if `if(fd1->IndexOfS2() == fd2->IndexOfS2())` is true, it can happen that the `TopoDS::Face(DStr.Shape(fd1->Index(jf1)))` returns a Face with entity == NULL. The subsequent usage of this NULL face in `BRep_Tool::Parameters( Vtx, face )` will then cause a segfault. While the best approach would be to identify the implementation bug in the algorithm behind PChFi3d_IsInFron, a check + exception is used instead because the actual algorithm is not known. Signed-off-by: Charlemagne Lasse --- src/ChFi3d/ChFi3d_Builder_0.cxx | 20 ++++++++++++++++---- tests/bugs/modalg_8/bug32931 | 26 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 tests/bugs/modalg_8/bug32931 diff --git a/src/ChFi3d/ChFi3d_Builder_0.cxx b/src/ChFi3d/ChFi3d_Builder_0.cxx index 5e64b338a1..ef17f40eb1 100644 --- a/src/ChFi3d/ChFi3d_Builder_0.cxx +++ b/src/ChFi3d/ChFi3d_Builder_0.cxx @@ -732,10 +732,13 @@ Standard_Boolean ChFi3d_IsInFront(TopOpeBRepDS_DataStructure& DStr, if(fd1->IndexOfS1() == fd2->IndexOfS1()) { jf1 = 1; jf2 = 1; face = TopoDS::Face(DStr.Shape(fd1->Index(jf1))); + if (face.IsNull()) throw Standard_NullObject("ChFi3d_IsInFront : Trying to check orientation of NULL face"); OrSave1 = cd1->Orientation(jf1); Or = OrFace1 = face.Orientation(); OrSave2 = cd2->Orientation(jf2); - OrFace2 = DStr.Shape(fd2->Index(jf2)).Orientation(); + const TopoDS_Shape& shape2 = DStr.Shape(fd2->Index(jf2)); + if (shape2.IsNull()) throw Standard_NullObject("ChFi3d_IsInFront : Trying to check orientation of NULL shape"); + OrFace2 = shape2.Orientation(); visavis = Standard_True; sameside = ChFi3d::SameSide(Or,OrSave1,OrSave2,OrFace1,OrFace2); // The parameters of the other side are not used for orientation. This would raise problems @@ -753,10 +756,13 @@ Standard_Boolean ChFi3d_IsInFront(TopOpeBRepDS_DataStructure& DStr, if(fd1->IndexOfS2() == fd2->IndexOfS1()) { jf1 = 2; jf2 = 1; face = TopoDS::Face(DStr.Shape(fd1->Index(jf1))); + if (face.IsNull()) throw Standard_NullObject("ChFi3d_IsInFront : Trying to check orientation of NULL face"); OrSave1 = cd1->Orientation(jf1); Or = OrFace1 = face.Orientation(); OrSave2 = cd2->Orientation(jf2); - OrFace2 = DStr.Shape(fd2->Index(jf2)).Orientation(); + const TopoDS_Shape& shape2 = DStr.Shape(fd2->Index(jf2)); + if (shape2.IsNull()) throw Standard_NullObject("ChFi3d_IsInFront : Trying to check orientation of NULL shape"); + OrFace2 = shape2.Orientation(); visavis = Standard_True; sameside = ChFi3d::SameSide(Or,OrSave1,OrSave2,OrFace1,OrFace2); // The parameters of the other side are not used for orientation. This would raise problems @@ -786,10 +792,13 @@ Standard_Boolean ChFi3d_IsInFront(TopOpeBRepDS_DataStructure& DStr, if(fd1->IndexOfS1() == fd2->IndexOfS2()) { jf1 = 1; jf2 = 2; face = TopoDS::Face(DStr.Shape(fd1->Index(jf1))); + if (face.IsNull()) throw Standard_NullObject("ChFi3d_IsInFront : Trying to check orientation of NULL face"); OrSave1 = cd1->Orientation(jf1); Or = OrFace1 = face.Orientation(); OrSave2 = cd2->Orientation(jf2); - OrFace2 = DStr.Shape(fd2->Index(jf2)).Orientation(); + const TopoDS_Shape& shape2 = DStr.Shape(fd2->Index(jf2)); + if (shape2.IsNull()) throw Standard_NullObject("ChFi3d_IsInFront : Trying to check orientation of NULL shape"); + OrFace2 = shape2.Orientation(); visavis = Standard_True; sameside = ChFi3d::SameSide(Or,OrSave1,OrSave2,OrFace1,OrFace2); // The parameters of the other side are not used for orientation. @@ -819,10 +828,13 @@ Standard_Boolean ChFi3d_IsInFront(TopOpeBRepDS_DataStructure& DStr, if(fd1->IndexOfS2() == fd2->IndexOfS2()) { jf1 = 2; jf2 = 2; face = TopoDS::Face(DStr.Shape(fd1->Index(jf1))); + if (face.IsNull()) throw Standard_NullObject("ChFi3d_IsInFront : Trying to check orientation of NULL face"); OrSave1 = cd1->Orientation(jf1); Or = OrFace1 = face.Orientation(); OrSave2 = cd2->Orientation(jf2); - OrFace2 = DStr.Shape(fd2->Index(jf2)).Orientation(); + const TopoDS_Shape& shape2 = DStr.Shape(fd2->Index(jf2)); + if (shape2.IsNull()) throw Standard_NullObject("ChFi3d_IsInFront : Trying to check orientation of NULL shape"); + OrFace2 = shape2.Orientation(); visavis = Standard_True; sameside = ChFi3d::SameSide(Or,OrSave1,OrSave2,OrFace1,OrFace2); // The parameters of the other side are not used for orientation. diff --git a/tests/bugs/modalg_8/bug32931 b/tests/bugs/modalg_8/bug32931 new file mode 100644 index 0000000000..344b5b0d1a --- /dev/null +++ b/tests/bugs/modalg_8/bug32931 @@ -0,0 +1,26 @@ +puts "TODO OCC32931 ALL: Tcl Exception" +puts "TODO OCC32931 ALL: TEST INCOMPLETE" + +puts "============" +puts "OCC32931: Modeling Algorithms - Crash in ChFi3d_IsInFront when no face was found" +puts "============" +puts "" + +# Load & prepare data. +restore [locate_data_file bug32931.brep] b +explode b E + +# Make screenshot before filleting. +smallview +donly b b_10 1 b_18 1 b_19 1 b_20 1 b_21 1 b_17 +fit +xwd $imagedir/${test_image}_1.png + +# Make fillet. +blend result b 1 b_10 1 b_18 1 b_19 1 b_20 1 b_21 1 b_17 + +# Make screenshot after filleting. +donly result +fit +xwd $imagedir/${test_image}_2.png +