0029973: Modeling Algorithms - access violation within BRepAlgoAPI_Cut on empty input...
authoremv <emv@opencascade.com>
Fri, 20 Jul 2018 12:16:50 +0000 (15:16 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 27 Jul 2018 13:19:20 +0000 (16:19 +0300)
Boolean Operations algorithm has been improved to handle the cases with empty shapes arguments correctly.
Test cases for the issue.

src/BOPAlgo/BOPAlgo_BOP.cxx
src/BOPAlgo/BOPAlgo_BuilderShape.hxx
src/BRepTools/BRepTools_History.cxx
src/BRepTools/BRepTools_History.hxx
tests/bugs/modalg_7/bug29973_1 [new file with mode: 0644]
tests/bugs/modalg_7/bug29973_2 [new file with mode: 0644]

index 3d1271c..8a134ca 100644 (file)
@@ -163,7 +163,7 @@ void BOPAlgo_BOP::CheckData()
   //            or equal to the MAXIMAL dimension of the TOOLS;
   // 4. COMMON: The arguments and tools could have any dimensions.
   //
-  Standard_Integer iDimMin[2], iDimMax[2];
+  Standard_Integer iDimMin[2] = { 0, 0 }, iDimMax[2] = { 0, 0 };
   Standard_Boolean bHasValid[2] = {Standard_False, Standard_False};
   //
   for (i=0; i<2; ++i) {
@@ -216,8 +216,14 @@ void BOPAlgo_BOP::CheckData()
       AddError (new BOPAlgo_AlertBOPNotAllowed);
       return;
     }
-    myDims[0] = iDimMin[0];
-    myDims[1] = iDimMin[1];
+  }
+
+  if (bHasValid[0] || bHasValid[1])
+  {
+    // In case of all empty shapes in one of the groups
+    // this group aquires the dimension of other group
+    myDims[0] = bHasValid[0] ? iDimMin[0] : iDimMin[1];
+    myDims[1] = bHasValid[1] ? iDimMin[1] : iDimMin[0];
   }
 }
 //=======================================================================
@@ -265,24 +271,46 @@ Standard_Boolean BOPAlgo_BOP::TreatEmptyShape()
   // One of the groups of arguments consists of empty shapes only,
   // so we can build the result of operation right away just by
   // choosing the list of shapes to add to result, depending on
-  // the type of the operation
+  // the type of the operation.
+  // Although, if the group with valid shapes consists from more
+  // than just one shape, depending on the operation type we may need
+  // to split the shapes in this group before adding them into result.
+
   TopTools_ListOfShape *pLResult = NULL;
   //
   switch (myOperation) {
     case BOPAlgo_FUSE:
+    {
+      if (aLValidObjs.Extent() + aLValidTools.Extent() > 1)
+        // The arguments must be split before adding into result
+        return Standard_False;
+
       // Add not empty shapes into result
       pLResult = bHasValidObj ? &aLValidObjs : &aLValidTools;
       break;
+    }
     case BOPAlgo_CUT:
+    {
+      if (aLValidObjs.Extent() > 1)
+        // The objects must be split before adding into result
+        return Standard_False;
+
       // Add objects into result
       pLResult = &aLValidObjs;
       break;
+    }
     case BOPAlgo_CUT21:
+    {
+      if (aLValidTools.Extent() > 1)
+        // The tools must be split before adding into result
+        return Standard_False;
+
       // Add tools into result
       pLResult = &aLValidTools;
       break;
+    }
     case BOPAlgo_COMMON:
-      // Common will be empty
+      // Common will always be empty
       break;
     default:
       break;
@@ -408,6 +436,7 @@ void BOPAlgo_BOP::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
   {
     Standard_Boolean bDone = TreatEmptyShape();
     if (bDone) {
+      PrepareHistory();
       return;
     }
   }
index ffdf8b1..15e469b 100644 (file)
@@ -99,9 +99,23 @@ public: //! @name History methods
   }
 
   //! History Tool
-  Handle(BRepTools_History) History() const
+  Handle(BRepTools_History) History()
   {
-    return myFillHistory ? myHistory : NULL;
+    if (myFillHistory)
+    {
+      if (myHistory.IsNull())
+       // It seems the algorithm has exited with error before filling
+       // the history. Initialize the History tool to return the empty
+       // History instead of NULL.
+       myHistory = new BRepTools_History();
+
+      return myHistory;
+    }
+
+    // If the History has not been requested to be filled, return the NULL
+    // explicitly as the History may be partially filled for the algorithm's
+    // internal needs.
+    return NULL;
   }
 
 public: //! @name Enabling/Disabling the history collection.
index 0fee0a1..16787c3 100644 (file)
@@ -209,7 +209,8 @@ Standard_Boolean BRepTools_History::IsRemoved(
 //==============================================================================
 void BRepTools_History::Merge(const Handle(BRepTools_History)& theHistory23)
 {
-  Merge(*theHistory23.get());
+  if (!theHistory23.IsNull())
+    Merge(*theHistory23.get());
 }
 //==============================================================================
 //function : Merge
@@ -217,6 +218,12 @@ void BRepTools_History::Merge(const Handle(BRepTools_History)& theHistory23)
 //==============================================================================
 void BRepTools_History::Merge(const BRepTools_History& theHistory23)
 {
+  if (!(theHistory23.HasModified() ||
+        theHistory23.HasGenerated() ||
+        theHistory23.HasRemoved()))
+    // nothing to merge
+    return;
+
   // Propagate R23 directly and M23 and G23 fully to M12 and G12.
   // Remember the propagated shapes.
   TopTools_DataMapOfShapeListOfShape* aS1ToGAndM[] =
index b5edd8d..103b59b 100644 (file)
@@ -105,7 +105,10 @@ public: //! @name Constructors for History creation
     TopTools_IndexedMapOfShape anArgsMap;
     TopTools_ListIteratorOfListOfShape aIt(theArguments);
     for (; aIt.More(); aIt.Next())
-      TopExp::MapShapes(aIt.Value(), anArgsMap);
+    {
+      if (!aIt.Value().IsNull())
+        TopExp::MapShapes(aIt.Value(), anArgsMap);
+    }
 
     // Copy the history for all supported shapes from the algorithm
     Standard_Integer i, aNb = anArgsMap.Extent();
diff --git a/tests/bugs/modalg_7/bug29973_1 b/tests/bugs/modalg_7/bug29973_1
new file mode 100644 (file)
index 0000000..e70eeb4
--- /dev/null
@@ -0,0 +1,17 @@
+puts "========"
+puts "OCC29973: Modeling Algorithms - access violation within BRepAlgoAPI_Cut on empty input shape"
+puts "========"
+puts ""
+
+
+pload QAcommands
+
+compound c
+box b 1 2 3
+if {![regexp "Test complete" [OCC25446 r b c 2]]} {
+  puts "Error: test incomplete"
+}
+
+compound b bc
+checknbshapes r -ref [nbshapes bc]
+checkprops r -equal bc
diff --git a/tests/bugs/modalg_7/bug29973_2 b/tests/bugs/modalg_7/bug29973_2
new file mode 100644 (file)
index 0000000..6b4b38c
--- /dev/null
@@ -0,0 +1,73 @@
+puts "========"
+puts "OCC29973: Modeling Algorithms - access violation within BRepAlgoAPI_Cut on empty input shape"
+puts "========"
+puts ""
+
+
+box b1 10 10 10
+box b2 5 5 5 10 10 10
+compound c
+
+bclearobjects
+bcleartools
+baddobjects b1 b2
+baddtools c
+bfillds
+bbop r_0 0
+bbop r_1 1
+bbop r_2 2
+bbop r_3 3
+bbop r_4 4
+
+checkshape r_0
+checknbshapes r_0 -shape 1
+checkprops r_0 -s empty -v empty
+
+checkshape r_1
+checknbshapes r_1 -wire 12 -face 12 -solid 1 -shell 1
+checkprops r_1 -s 1050 -v 1875
+
+checkshape r_2
+checknbshapes r_2 -wire 18 -face 18 -solid 3 -shell 3
+checkprops r_2 -s 1350 -v 1875
+
+checkshape r_3
+checknbshapes r_3 -shape 1
+checkprops r_3 -s empty -v empty
+
+checkshape r_4
+checknbshapes r_4 -vertex 6 -edge 6
+checkprops r_4 -l 30
+
+# reverse the arguments
+
+bclearobjects
+bcleartools
+baddobjects c
+baddtools b1 b2
+bfillds
+bbop r1_0 0
+bbop r1_1 1
+bbop r1_2 2
+bbop r1_3 3
+bbop r1_4 4
+
+checkshape r1_0
+checknbshapes r1_0 -ref [nbshapes r_0]
+checkprops r1_0 -equal r_0
+
+checkshape r1_1
+checknbshapes r1_1 -ref [nbshapes r_1]
+checkprops r1_1 -equal r_1
+
+checkshape r1_2
+checknbshapes r1_2 -ref [nbshapes r_3]
+checkprops r1_2 -equal r_3
+
+checkshape r1_3
+checknbshapes r1_3 -ref [nbshapes r_2]
+checkprops r1_3 -equal r_2
+
+checkshape r1_4
+checknbshapes r1_4 -ref [nbshapes r_4]
+checkprops r1_4 -equal r_4