From 3dc5809557a675453fd352f69a4cfd948d64cd59 Mon Sep 17 00:00:00 2001 From: emv Date: Fri, 20 Jul 2018 15:16:50 +0300 Subject: [PATCH] 0029973: Modeling Algorithms - access violation within BRepAlgoAPI_Cut on empty input shape 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 | 39 +++++++++++++-- src/BOPAlgo/BOPAlgo_BuilderShape.hxx | 18 ++++++- src/BRepTools/BRepTools_History.cxx | 9 +++- src/BRepTools/BRepTools_History.hxx | 5 +- tests/bugs/modalg_7/bug29973_1 | 17 +++++++ tests/bugs/modalg_7/bug29973_2 | 73 ++++++++++++++++++++++++++++ 6 files changed, 152 insertions(+), 9 deletions(-) create mode 100644 tests/bugs/modalg_7/bug29973_1 create mode 100644 tests/bugs/modalg_7/bug29973_2 diff --git a/src/BOPAlgo/BOPAlgo_BOP.cxx b/src/BOPAlgo/BOPAlgo_BOP.cxx index 3d1271c595..8a134caa1c 100644 --- a/src/BOPAlgo/BOPAlgo_BOP.cxx +++ b/src/BOPAlgo/BOPAlgo_BOP.cxx @@ -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; } } diff --git a/src/BOPAlgo/BOPAlgo_BuilderShape.hxx b/src/BOPAlgo/BOPAlgo_BuilderShape.hxx index ffdf8b1094..15e469bef1 100644 --- a/src/BOPAlgo/BOPAlgo_BuilderShape.hxx +++ b/src/BOPAlgo/BOPAlgo_BuilderShape.hxx @@ -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. diff --git a/src/BRepTools/BRepTools_History.cxx b/src/BRepTools/BRepTools_History.cxx index 0fee0a195c..16787c3c03 100644 --- a/src/BRepTools/BRepTools_History.cxx +++ b/src/BRepTools/BRepTools_History.cxx @@ -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[] = diff --git a/src/BRepTools/BRepTools_History.hxx b/src/BRepTools/BRepTools_History.hxx index b5edd8d548..103b59b8c3 100644 --- a/src/BRepTools/BRepTools_History.hxx +++ b/src/BRepTools/BRepTools_History.hxx @@ -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 index 0000000000..e70eeb4b65 --- /dev/null +++ b/tests/bugs/modalg_7/bug29973_1 @@ -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 index 0000000000..6b4b38cfe5 --- /dev/null +++ b/tests/bugs/modalg_7/bug29973_2 @@ -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 -- 2.20.1