]> OCCT Git - occt.git/commitdiff
0032931: Modeling Algorithms - Crash in ChFi3d_IsInFront when no face was found
authorCharlemagne Lasse <charlemagnelasse@gmail.com>
Wed, 13 Apr 2022 09:54:30 +0000 (11:54 +0200)
committerafokin <afokin@opencascade.com>
Fri, 3 Jun 2022 14:46:28 +0000 (17:46 +0300)
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 <charlemagnelasse@gmail.com>
src/ChFi3d/ChFi3d_Builder_0.cxx
tests/bugs/modalg_8/bug32931 [new file with mode: 0644]

index 5e64b338a11adfee3c4f99bf6f817cfb2df37c38..ef17f40eb185a0648c5efd4c80cc6c6845284302 100644 (file)
@@ -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 (file)
index 0000000..344b5b0
--- /dev/null
@@ -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
+