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

fdo#72695: avoid double-free race condition for SwXBookmark/SwXFieldmark

Change-Id: I92838d75f5573e4b626b94ef446f464be1b39b67
üst 778fc411
......@@ -300,7 +300,7 @@ namespace sw { namespace mark
SwDoc *const pDoc( GetMarkPos().GetDoc() );
OSL_ENSURE(pDoc, "Bookmark::MakeUnoObject: no doc?");
const uno::Reference< rdf::XMetadatable> xMeta(
SwXBookmark::CreateXBookmark(*pDoc, *this), uno::UNO_QUERY);
SwXBookmark::CreateXBookmark(*pDoc, this), uno::UNO_QUERY);
return xMeta;
}
......
......@@ -77,14 +77,14 @@ protected:
/// @param pDoc and pMark != 0, but not & because of ImplInheritanceHelper
SwXBookmark(::sw::mark::IMark *const pMark, SwDoc *const pDoc);
public:
/// descriptor
SwXBookmark();
public:
static ::com::sun::star::uno::Reference<
::com::sun::star::text::XTextContent>
CreateXBookmark(SwDoc & rDoc, ::sw::mark::IMark & rBookmark);
CreateXBookmark(SwDoc & rDoc, ::sw::mark::IMark * pBookmark);
/// @return IMark for this, but only if it lives in pDoc
static ::sw::mark::IMark const* GetBookmarkInDoc(SwDoc const*const pDoc,
......@@ -229,15 +229,19 @@ class SwXFieldmark
private:
::sw::mark::ICheckboxFieldmark* getCheckboxFieldmark();
bool isReplacementObject;
public:
static ::com::sun::star::uno::Reference<
::com::sun::star::text::XTextContent>
CreateXFieldmark( SwDoc & rDoc, ::sw::mark::IMark & rMark );
protected:
SwXFieldmark(bool isReplacementObject,
::sw::mark::IMark* pBkm = 0, SwDoc* pDoc = 0);
public:
static ::com::sun::star::uno::Reference<
::com::sun::star::text::XTextContent>
CreateXFieldmark(SwDoc & rDoc, ::sw::mark::IMark * pMark,
bool isReplacementObject = false);
virtual void attachToRange(
const ::com::sun::star::uno::Reference<
::com::sun::star::text::XTextRange > & xTextRange)
......
......@@ -60,6 +60,7 @@ private:
::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper
public:
uno::WeakReference<uno::XInterface> m_wThis;
::cppu::OInterfaceContainerHelper m_EventListeners;
SwDoc * m_pDoc;
::sw::mark::IMark * m_pRegisteredBookmark;
......@@ -86,18 +87,26 @@ protected:
void SwXBookmark::Impl::Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew)
{
ClientModify(this, pOld, pNew);
if (!GetRegisteredIn())
if (GetRegisteredIn())
{
m_pRegisteredBookmark = NULL;
m_pDoc = NULL;
lang::EventObject const ev(static_cast< ::cppu::OWeakObject&>(m_rThis));
m_EventListeners.disposeAndClear(ev);
return; // core object still alive
}
m_pRegisteredBookmark = 0;
m_pDoc = 0;
uno::Reference<uno::XInterface> const xThis(m_wThis);
if (!xThis.is())
{ // fdo#72695: if UNO object is already dead, don't revive it with event
return;
}
lang::EventObject const ev(xThis);
m_EventListeners.disposeAndClear(ev);
}
void SwXBookmark::Impl::registerInMark(SwXBookmark & rThis,
::sw::mark::IMark *const pBkmk)
{
const uno::Reference<text::XTextContent> xBookmark(& rThis);
if (pBkmk)
{
pBkmk->Add(this);
......@@ -105,7 +114,6 @@ void SwXBookmark::Impl::registerInMark(SwXBookmark & rThis,
OSL_ENSURE(pMarkBase, "registerInMark: no MarkBase?");
if (pMarkBase)
{
const uno::Reference<text::XTextContent> xBookmark(& rThis);
pMarkBase->SetXBookmark(xBookmark);
}
}
......@@ -115,6 +123,8 @@ void SwXBookmark::Impl::registerInMark(SwXBookmark & rThis,
m_pRegisteredBookmark->Remove(this);
}
m_pRegisteredBookmark = pBkmk;
// need a permanent Reference to initialize m_wThis
m_wThis = xBookmark;
}
void SwXBookmark::registerInMark(SwXBookmark & rThis,
......@@ -146,20 +156,24 @@ SwXBookmark::~SwXBookmark()
uno::Reference<text::XTextContent> SwXBookmark::CreateXBookmark(
SwDoc & rDoc,
::sw::mark::IMark & rBookmark)
::sw::mark::IMark *const pBookmark)
{
// #i105557#: do not iterate over the registered clients: race condition
::sw::mark::MarkBase *const pMarkBase(dynamic_cast< ::sw::mark::MarkBase * >(&rBookmark));
OSL_ENSURE(pMarkBase, "CreateXBookmark: no MarkBase?");
if (!pMarkBase) { return 0; }
uno::Reference<text::XTextContent> xBookmark(pMarkBase->GetXBookmark());
::sw::mark::MarkBase *const pMarkBase(dynamic_cast< ::sw::mark::MarkBase * >(pBookmark));
OSL_ENSURE(!pBookmark || pMarkBase, "CreateXBookmark: no MarkBase?");
uno::Reference<text::XTextContent> xBookmark;
if (pMarkBase)
{
xBookmark = pMarkBase->GetXBookmark();
}
if (!xBookmark.is())
{
OSL_ENSURE(
dynamic_cast< ::sw::mark::IBookmark* >(&rBookmark) || IDocumentMarkAccess::GetType(rBookmark) == IDocumentMarkAccess::ANNOTATIONMARK,
OSL_ENSURE(!pBookmark ||
dynamic_cast< ::sw::mark::IBookmark* >(pBookmark) || IDocumentMarkAccess::GetType(*pBookmark) == IDocumentMarkAccess::ANNOTATIONMARK,
"<SwXBookmark::GetObject(..)>"
"SwXBookmark requested for non-bookmark mark and non-annotation mark.");
SwXBookmark *const pXBookmark = new SwXBookmark(&rBookmark, &rDoc);
SwXBookmark *const pXBookmark =
(pBookmark) ? new SwXBookmark(pBookmark, &rDoc) : new SwXBookmark;
xBookmark.set(pXBookmark);
pXBookmark->m_pImpl->registerInMark(*pXBookmark, pMarkBase);
}
......@@ -617,22 +631,28 @@ uno::Reference<container::XNameContainer> SwXFieldmark::getParameters()
}
uno::Reference<text::XTextContent>
SwXFieldmark::CreateXFieldmark(SwDoc & rDoc, ::sw::mark::IMark & rMark)
SwXFieldmark::CreateXFieldmark(SwDoc & rDoc, ::sw::mark::IMark *const pMark,
bool const isReplacementObject)
{
// #i105557#: do not iterate over the registered clients: race condition
::sw::mark::MarkBase *const pMarkBase(
dynamic_cast< ::sw::mark::MarkBase * >(&rMark));
OSL_ENSURE(pMarkBase, "CreateXBookmark: no MarkBase?");
if (!pMarkBase) { return 0; }
uno::Reference<text::XTextContent> xMark(pMarkBase->GetXBookmark());
dynamic_cast< ::sw::mark::MarkBase * >(pMark));
assert(!pMark || pMarkBase);
uno::Reference<text::XTextContent> xMark;
if (pMarkBase)
{
xMark = pMarkBase->GetXBookmark();
}
if (!xMark.is())
{
// FIXME: These belong in XTextFieldsSupplier
SwXFieldmark* pXBkmk = NULL;
if (dynamic_cast< ::sw::mark::TextFieldmark* >(&rMark))
pXBkmk = new SwXFieldmark(false, &rMark, &rDoc);
else if (dynamic_cast< ::sw::mark::CheckboxFieldmark* >(&rMark))
pXBkmk = new SwXFieldmark(true, &rMark, &rDoc);
if (dynamic_cast< ::sw::mark::TextFieldmark* >(pMark))
pXBkmk = new SwXFieldmark(false, pMark, &rDoc);
else if (dynamic_cast< ::sw::mark::CheckboxFieldmark* >(pMark))
pXBkmk = new SwXFieldmark(true, pMark, &rDoc);
else
pXBkmk = new SwXFieldmark(isReplacementObject, 0, &rDoc);
xMark.set(pXBkmk);
pXBkmk->registerInMark(*pXBkmk, pMarkBase);
......
......@@ -547,20 +547,17 @@ uno::Reference< uno::XInterface > SwXServiceProvider::MakeInstance(sal_uInt16
break;
case SW_SERVICE_TYPE_BOOKMARK :
{
SwXBookmark* pBookmark = new SwXBookmark;
xRet = (cppu::OWeakObject*)pBookmark;
xRet = SwXBookmark::CreateXBookmark(*pDoc, 0);
}
break;
case SW_SERVICE_TYPE_FIELDMARK :
{
SwXFieldmark* pFieldmark = new SwXFieldmark(false);
xRet = (cppu::OWeakObject*)pFieldmark;
xRet = SwXFieldmark::CreateXFieldmark(*pDoc, 0, false);
}
break;
case SW_SERVICE_TYPE_FORMFIELDMARK :
{
SwXFieldmark* pFieldmark = new SwXFieldmark(true);
xRet = (cppu::OWeakObject*)pFieldmark;
xRet = SwXFieldmark::CreateXFieldmark(*pDoc, 0, true);
}
break;
case SW_SERVICE_VBAOBJECTPROVIDER :
......@@ -1629,7 +1626,7 @@ uno::Any SwXBookmarks::getByIndex(sal_Int32 nIndex)
{
uno::Any aRet;
const uno::Reference< text::XTextContent > xRef =
SwXBookmark::CreateXBookmark(*GetDoc(), **ppMark);
SwXBookmark::CreateXBookmark(*GetDoc(), ppMark->get());
aRet <<= xRef;
return aRet;
}
......@@ -1653,7 +1650,7 @@ uno::Any SwXBookmarks::getByName(const OUString& rName)
uno::Any aRet;
const uno::Reference< text::XTextContent > xRef =
SwXBookmark::CreateXBookmark(*GetDoc(), *(ppBkmk->get()));
SwXBookmark::CreateXBookmark(*GetDoc(), ppBkmk->get());
aRet <<= xRef;
return aRet;
}
......
......@@ -161,7 +161,7 @@ namespace
? BKM_TYPE_START : BKM_TYPE_START_END;
rBkmArr.insert(SwXBookmarkPortion_ImplSharedPtr(
new SwXBookmarkPortion_Impl(
SwXBookmark::CreateXBookmark(rDoc, *pBkmk),
SwXBookmark::CreateXBookmark(rDoc, pBkmk),
nType, rStartPos)));
}
......@@ -189,7 +189,7 @@ namespace
{
rBkmArr.insert(SwXBookmarkPortion_ImplSharedPtr(
new SwXBookmarkPortion_Impl(
SwXBookmark::CreateXBookmark(rDoc, *pBkmk),
SwXBookmark::CreateXBookmark(rDoc, pBkmk),
BKM_TYPE_END, *pEndPos)));
}
}
......@@ -439,7 +439,8 @@ lcl_ExportFieldMark(
xRef = pPortion;
if (pPortion && pFieldmark && pDoc)
{
pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
pPortion->SetBookmark(
SwXFieldmark::CreateXFieldmark(*pDoc, pFieldmark));
}
}
else if (CH_TXT_ATR_FIELDEND == Char)
......@@ -454,7 +455,10 @@ lcl_ExportFieldMark(
pUnoCrsr, i_xParentText, PORTION_FIELD_END);
xRef = pPortion;
if (pPortion && pFieldmark && pDoc)
pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
{
pPortion->SetBookmark(
SwXFieldmark::CreateXFieldmark(*pDoc, pFieldmark));
}
}
else if (CH_TXT_ATR_FORMELEMENT == Char)
{
......@@ -467,7 +471,10 @@ lcl_ExportFieldMark(
pUnoCrsr, i_xParentText, PORTION_FIELD_START_END);
xRef = pPortion;
if (pPortion && pFieldmark && pDoc)
pPortion->SetBookmark( SwXFieldmark::CreateXFieldmark( *pDoc, *pFieldmark ) );
{
pPortion->SetBookmark(
SwXFieldmark::CreateXFieldmark(*pDoc, pFieldmark));
}
}
else
{
......@@ -820,7 +827,8 @@ lcl_ExportHints(
if ( pAnnotationMark != NULL )
{
SwXTextPortion* pPortion = new SwXTextPortion( pUnoCrsr, xParent, PORTION_ANNOTATION_END );
pPortion->SetBookmark( SwXBookmark::CreateXBookmark( *pDoc, *pAnnotationMark ) );
pPortion->SetBookmark(SwXBookmark::CreateXBookmark(
*pDoc, pAnnotationMark));
xRef = pPortion;
}
else
......
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