sw/source/core/docnode/ndtbl1.cxx | 78 +++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 34 deletions(-)
New commits: commit 0dc71c7caf5cd1f7508451455a4907cde0809d72 Author: Mike Kaganski <mike.kagan...@collabora.com> Date: Tue Jun 12 07:30:10 2018 +0200 Register SwTableFormatCmp as its old format's writer listener Using SwTableFormatCmp in loops with SwTableLine::ChgFrameFormat, where the latter may delete the old format of a frame, may invalidate the pOld of a SwTableFormatCmp, and lead to use-after-free. To avoid this, let's register SwTableFormatCmp as the old format writer listener. Also use unique_ptr in vectors to simplify memory management. Change-Id: I5ac93f4c3ae549b79a41220bda880386dd529c36 Reviewed-on: https://gerrit.libreoffice.org/55653 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@cib.de> diff --git a/sw/source/core/docnode/ndtbl1.cxx b/sw/source/core/docnode/ndtbl1.cxx index d5070c99cf6b..9b9c86d6d57c 100644 --- a/sw/source/core/docnode/ndtbl1.cxx +++ b/sw/source/core/docnode/ndtbl1.cxx @@ -51,6 +51,7 @@ #include <calbck.hxx> #include <UndoTable.hxx> #include <o3tl/enumrange.hxx> +#include <o3tl/make_unique.hxx> using ::editeng::SvxBorderLine; using namespace ::com::sun::star; @@ -60,27 +61,44 @@ using namespace ::com::sun::star; inline bool IsSame( long nA, long nB ) { return std::abs(nA-nB) <= COLFUZZY; } -class SwTableFormatCmp +// SwTableLine::ChgFrameFormat may delete old format which doesn't have writer listeners anymore. +// This may invalidate my pointers, and lead to use-after-free. For this reason, I register myself +// as a writer listener for the old format here, and take care to delete formats without listeners +// in my own dtor. +class SwTableFormatCmp : public SwClient { public: - SwFrameFormat *pOld, - *pNew; - sal_Int16 nType; - SwTableFormatCmp( SwFrameFormat *pOld, SwFrameFormat *pNew, sal_Int16 nType ); + ~SwTableFormatCmp() override; + + static SwFrameFormat* FindNewFormat(std::vector<std::unique_ptr<SwTableFormatCmp>>& rArr, + SwFrameFormat const* pOld, sal_Int16 nType); - static SwFrameFormat *FindNewFormat( std::vector<SwTableFormatCmp*> &rArr, SwFrameFormat const *pOld, sal_Int16 nType ); - static void Delete( std::vector<SwTableFormatCmp*> &rArr ); +private: + SwFrameFormat *pOld, *pNew; + sal_Int16 nType; }; SwTableFormatCmp::SwTableFormatCmp( SwFrameFormat *pO, SwFrameFormat *pN, sal_Int16 nT ) : pOld ( pO ), pNew ( pN ), nType( nT ) { + if (pOld) + pOld->Add(this); +} + +SwTableFormatCmp::~SwTableFormatCmp() +{ + if (pOld) + pOld->Remove(this); + if (!pOld->HasWriterListeners()) + delete pOld; } -SwFrameFormat *SwTableFormatCmp::FindNewFormat( std::vector<SwTableFormatCmp*> &rArr, SwFrameFormat const *pOld, sal_Int16 nType ) +// static +SwFrameFormat* SwTableFormatCmp::FindNewFormat(std::vector<std::unique_ptr<SwTableFormatCmp>>& rArr, + SwFrameFormat const* pOld, sal_Int16 nType) { - for ( auto pCmp : rArr ) + for (auto& pCmp : rArr) { if ( pCmp->pOld == pOld && pCmp->nType == nType ) return pCmp->pNew; @@ -88,12 +106,6 @@ SwFrameFormat *SwTableFormatCmp::FindNewFormat( std::vector<SwTableFormatCmp*> & return nullptr; } -void SwTableFormatCmp::Delete( std::vector<SwTableFormatCmp*> &rArr ) -{ - for ( auto pCmp : rArr ) - delete pCmp; -} - static void lcl_GetStartEndCell( const SwCursor& rCursor, SwLayoutFrame *&prStart, SwLayoutFrame *&prEnd ) { @@ -254,7 +266,8 @@ static void lcl_CollectLines( std::vector<SwTableLine*> &rArr, const SwCursor& r } } -static void lcl_ProcessRowAttr( std::vector<SwTableFormatCmp*>& rFormatCmp, SwTableLine* pLine, const SfxPoolItem& rNew ) +static void lcl_ProcessRowAttr(std::vector<std::unique_ptr<SwTableFormatCmp>>& rFormatCmp, + SwTableLine* pLine, const SfxPoolItem& rNew) { SwFrameFormat *pNewFormat; if ( nullptr != (pNewFormat = SwTableFormatCmp::FindNewFormat( rFormatCmp, pLine->GetFrameFormat(), 0 ))) @@ -264,13 +277,15 @@ static void lcl_ProcessRowAttr( std::vector<SwTableFormatCmp*>& rFormatCmp, SwTa SwFrameFormat *pOld = pLine->GetFrameFormat(); SwFrameFormat *pNew = pLine->ClaimFrameFormat(); pNew->SetFormatAttr( rNew ); - rFormatCmp.push_back( new SwTableFormatCmp( pOld, pNew, 0 ) ); + rFormatCmp.push_back(o3tl::make_unique<SwTableFormatCmp>(pOld, pNew, 0)); } } -static void lcl_ProcessBoxSize( std::vector<SwTableFormatCmp*> &rFormatCmp, SwTableBox *pBox, const SwFormatFrameSize &rNew ); +static void lcl_ProcessBoxSize(std::vector<std::unique_ptr<SwTableFormatCmp>>& rFormatCmp, + SwTableBox* pBox, const SwFormatFrameSize& rNew); -static void lcl_ProcessRowSize( std::vector<SwTableFormatCmp*> &rFormatCmp, SwTableLine *pLine, const SwFormatFrameSize &rNew ) +static void lcl_ProcessRowSize(std::vector<std::unique_ptr<SwTableFormatCmp>>& rFormatCmp, + SwTableLine* pLine, const SwFormatFrameSize& rNew) { lcl_ProcessRowAttr( rFormatCmp, pLine, rNew ); SwTableBoxes &rBoxes = pLine->GetTabBoxes(); @@ -278,7 +293,8 @@ static void lcl_ProcessRowSize( std::vector<SwTableFormatCmp*> &rFormatCmp, SwTa ::lcl_ProcessBoxSize( rFormatCmp, pBox, rNew ); } -static void lcl_ProcessBoxSize( std::vector<SwTableFormatCmp*> &rFormatCmp, SwTableBox *pBox, const SwFormatFrameSize &rNew ) +static void lcl_ProcessBoxSize(std::vector<std::unique_ptr<SwTableFormatCmp>>& rFormatCmp, + SwTableBox* pBox, const SwFormatFrameSize& rNew) { SwTableLines &rLines = pBox->GetTabLines(); if ( !rLines.empty() ) @@ -305,13 +321,12 @@ void SwDoc::SetRowSplit( const SwCursor& rCursor, const SwFormatRowSplit &rNew ) GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTable(*pTableNd)); } - std::vector<SwTableFormatCmp*> aFormatCmp; + std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp; aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) ); for( auto pLn : aRowArr ) ::lcl_ProcessRowAttr( aFormatCmp, pLn, rNew ); - SwTableFormatCmp::Delete( aFormatCmp ); getIDocumentState().SetModified(); } } @@ -378,11 +393,10 @@ void SwDoc::SetRowHeight( const SwCursor& rCursor, const SwFormatFrameSize &rNew GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTable(*pTableNd)); } - std::vector<SwTableFormatCmp*> aFormatCmp; + std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp; aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) ); for ( auto pLn : aRowArr ) ::lcl_ProcessRowSize( aFormatCmp, pLn, rNew ); - SwTableFormatCmp::Delete( aFormatCmp ); getIDocumentState().SetModified(); } @@ -453,11 +467,10 @@ bool SwDoc::BalanceRowHeight( const SwCursor& rCursor, bool bTstOnly ) new SwUndoAttrTable(*pTableNd)); } - std::vector<SwTableFormatCmp*> aFormatCmp; + std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp; aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) ); for( auto pLn : aRowArr ) ::lcl_ProcessRowSize( aFormatCmp, pLn, aNew ); - SwTableFormatCmp::Delete( aFormatCmp ); getIDocumentState().SetModified(); } @@ -482,13 +495,12 @@ void SwDoc::SetRowBackground( const SwCursor& rCursor, const SvxBrushItem &rNew GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTable(*pTableNd)); } - std::vector<SwTableFormatCmp*> aFormatCmp; + std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp; aFormatCmp.reserve( std::max( 255, static_cast<int>(aRowArr.size()) ) ); for( auto pLn : aRowArr ) ::lcl_ProcessRowAttr( aFormatCmp, pLn, rNew ); - SwTableFormatCmp::Delete( aFormatCmp ); getIDocumentState().SetModified(); } } @@ -570,7 +582,7 @@ void SwDoc::SetTabBorders( const SwCursor& rCursor, const SfxItemSet& rSet ) GetIDocumentUndoRedo().AppendUndo( new SwUndoAttrTable(*pTableNd) ); } - std::vector<SwTableFormatCmp*> aFormatCmp; + std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp; aFormatCmp.reserve( 255 ); const SvxBoxItem* pSetBox; const SvxBoxInfoItem *pSetBoxInfo; @@ -791,7 +803,7 @@ void SwDoc::SetTabBorders( const SwCursor& rCursor, const SfxItemSet& rSet ) SwFrameFormat *pOld = pBox->GetFrameFormat(); SwFrameFormat *pNew = pBox->ClaimFrameFormat(); pNew->SetFormatAttr( aBox ); - aFormatCmp.push_back( new SwTableFormatCmp( pOld, pNew, nType ) ); + aFormatCmp.push_back(o3tl::make_unique<SwTableFormatCmp>(pOld, pNew, nType)); } } @@ -807,7 +819,6 @@ void SwDoc::SetTabBorders( const SwCursor& rCursor, const SfxItemSet& rSet ) pTableLayout->BordersChanged( pTableLayout->GetBrowseWidthByTabFrame( *pTabFrame ) ); } - SwTableFormatCmp::Delete( aFormatCmp ); ::ClearFEShellTabCols(*this, nullptr); getIDocumentState().SetModified(); } @@ -1139,7 +1150,7 @@ void SwDoc::SetBoxAttr( const SwCursor& rCursor, const SfxPoolItem &rNew ) GetIDocumentUndoRedo().AppendUndo( new SwUndoAttrTable(*pTableNd) ); } - std::vector<SwTableFormatCmp*> aFormatCmp; + std::vector<std::unique_ptr<SwTableFormatCmp>> aFormatCmp; aFormatCmp.reserve(std::max<size_t>(255, aBoxes.size())); for (size_t i = 0; i < aBoxes.size(); ++i) { @@ -1153,7 +1164,7 @@ void SwDoc::SetBoxAttr( const SwCursor& rCursor, const SfxPoolItem &rNew ) SwFrameFormat *pOld = pBox->GetFrameFormat(); SwFrameFormat *pNew = pBox->ClaimFrameFormat(); pNew->SetFormatAttr( rNew ); - aFormatCmp.push_back( new SwTableFormatCmp( pOld, pNew, 0 ) ); + aFormatCmp.push_back(o3tl::make_unique<SwTableFormatCmp>(pOld, pNew, 0)); } pBox->SetDirectFormatting(true); @@ -1168,7 +1179,6 @@ void SwDoc::SetBoxAttr( const SwCursor& rCursor, const SfxPoolItem &rNew ) pTableLayout->Resize( pTableLayout->GetBrowseWidthByTabFrame( *pTabFrame ), true ); } - SwTableFormatCmp::Delete( aFormatCmp ); getIDocumentState().SetModified(); } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits