Kaydet (Commit) a54ba50d authored tarafından Michael Stahl's avatar Michael Stahl

tdf#108863 svx: fix use-after-free in SdrEditView::DeleteMarkedObj()

The sdr::ViewSelection has multiple vectors with pointers to the same
SdrObjects, and those are only cleared in
sdr::ViewSelection::SetEdgesOfMarkedNodesDirty(), so deleting SdrObjects
that are marked must be delayed until after that is called.

Change-Id: I7ab18cb2116164a71dce29bf10eca974061ab424
üst 49528471
...@@ -154,7 +154,8 @@ protected: ...@@ -154,7 +154,8 @@ protected:
// Removes all objects of the MarkList from their ObjLists including Undo. // Removes all objects of the MarkList from their ObjLists including Undo.
// The entries in rMark remain. // The entries in rMark remain.
void DeleteMarkedList(const SdrMarkList& rMark); // DeleteMarked -> DeleteMarkedList // @return a list of objects that must be deleted after the outermost EndUndo
std::vector<SdrObject *> DeleteMarkedList(SdrMarkList const& rMark); // DeleteMarked -> DeleteMarkedList
// Check possibilities of all marked objects // Check possibilities of all marked objects
virtual void CheckPossibilities(); virtual void CheckPossibilities();
......
...@@ -678,8 +678,9 @@ void SdrEditView::ForceMarkedObjToAnotherPage() ...@@ -678,8 +678,9 @@ void SdrEditView::ForceMarkedObjToAnotherPage()
} }
} }
void SdrEditView::DeleteMarkedList(const SdrMarkList& rMark) std::vector<SdrObject*> SdrEditView::DeleteMarkedList(SdrMarkList const& rMark)
{ {
std::vector<SdrObject*> ret;
if (rMark.GetMarkCount()!=0) if (rMark.GetMarkCount()!=0)
{ {
rMark.ForceSort(); rMark.ForceSort();
...@@ -733,10 +734,8 @@ void SdrEditView::DeleteMarkedList(const SdrMarkList& rMark) ...@@ -733,10 +734,8 @@ void SdrEditView::DeleteMarkedList(const SdrMarkList& rMark)
if( !bUndo ) if( !bUndo )
{ {
if( bIs3D ) // tdf#108863 don't delete objects before EndUndo()
aRemoved3DObjects.push_back( pObj ); // may be needed later ret.push_back(pObj);
else
SdrObject::Free(pObj);
} }
} }
...@@ -746,21 +745,22 @@ void SdrEditView::DeleteMarkedList(const SdrMarkList& rMark) ...@@ -746,21 +745,22 @@ void SdrEditView::DeleteMarkedList(const SdrMarkList& rMark)
delete aUpdaters.back(); delete aUpdaters.back();
aUpdaters.pop_back(); aUpdaters.pop_back();
} }
if( !bUndo )
{
// now delete removed scene objects
while(!aRemoved3DObjects.empty())
{
SdrObject::Free( aRemoved3DObjects.back() );
aRemoved3DObjects.pop_back();
}
}
} }
if( bUndo ) if( bUndo )
EndUndo(); EndUndo();
} }
return ret;
}
static void lcl_LazyDelete(std::vector<SdrObject*> & rLazyDelete)
{
// now delete removed scene objects
while (!rLazyDelete.empty())
{
SdrObject::Free( rLazyDelete.back() );
rLazyDelete.pop_back();
}
} }
void SdrEditView::DeleteMarkedObj() void SdrEditView::DeleteMarkedObj()
...@@ -775,6 +775,7 @@ void SdrEditView::DeleteMarkedObj() ...@@ -775,6 +775,7 @@ void SdrEditView::DeleteMarkedObj()
BrkAction(); BrkAction();
BegUndo(ImpGetResStr(STR_EditDelete),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::Delete); BegUndo(ImpGetResStr(STR_EditDelete),GetDescriptionOfMarkedObjects(),SdrRepeatFunc::Delete);
std::vector<SdrObject*> lazyDeleteObjects;
// remove as long as something is selected. This allows to schedule objects for // remove as long as something is selected. This allows to schedule objects for
// removal for a next run as needed // removal for a next run as needed
while(GetMarkedObjectCount()) while(GetMarkedObjectCount())
...@@ -835,7 +836,11 @@ void SdrEditView::DeleteMarkedObj() ...@@ -835,7 +836,11 @@ void SdrEditView::DeleteMarkedObj()
// original stuff: remove selected objects. Handle clear will // original stuff: remove selected objects. Handle clear will
// do something only once // do something only once
DeleteMarkedList(GetMarkedObjectList()); auto temp(DeleteMarkedList(GetMarkedObjectList()));
for (auto p : temp)
{
lazyDeleteObjects.push_back(p);
}
GetMarkedObjectListWriteAccess().Clear(); GetMarkedObjectListWriteAccess().Clear();
maHdlList.Clear(); maHdlList.Clear();
...@@ -865,6 +870,8 @@ void SdrEditView::DeleteMarkedObj() ...@@ -865,6 +870,8 @@ void SdrEditView::DeleteMarkedObj()
// end undo and change messaging moved at the end // end undo and change messaging moved at the end
EndUndo(); EndUndo();
MarkListHasChanged(); MarkListHasChanged();
lcl_LazyDelete(lazyDeleteObjects);
} }
void SdrEditView::CopyMarkedObj() void SdrEditView::CopyMarkedObj()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment