summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2014-08-20 15:24:21 +0200
committerMichael Stahl <mstahl@redhat.com>2014-08-20 16:40:12 +0200
commitc71c1b2bb3b0a1767cd062e46e7dd81cc1027fb1 (patch)
treea0a7cf5b054277516bb6bb1670132642f2c7cb49
parent8deeb0d53850e7fef0b3011a0335837e6316ce0e (diff)
fdo#72695: avoid double-free race condition for SwXFieldMaster
Change-Id: Id3dfe1c68f00964200ad53922a0f41ebdbc4c3f8
-rw-r--r--sw/source/core/inc/unofield.hxx7
-rw-r--r--sw/source/core/unocore/unocoll.cxx4
-rw-r--r--sw/source/core/unocore/unofield.cxx48
3 files changed, 39 insertions, 20 deletions
diff --git a/sw/source/core/inc/unofield.hxx b/sw/source/core/inc/unofield.hxx
index 0e30e97526c7..90b659494540 100644
--- a/sw/source/core/inc/unofield.hxx
+++ b/sw/source/core/inc/unofield.hxx
@@ -58,14 +58,15 @@ private:
SwXFieldMaster(SwFieldType& rType, SwDoc & rDoc);
-public:
-
/// descriptor
SwXFieldMaster(SwDoc* pDoc, sal_uInt16 nResId);
+public:
+
static ::com::sun::star::uno::Reference<
::com::sun::star::beans::XPropertySet>
- CreateXFieldMaster(SwDoc & rDoc, SwFieldType & rType);
+ CreateXFieldMaster(SwDoc & rDoc, SwFieldType * pType,
+ sal_uInt16 nResId = 0xFFFF);
static OUString GetProgrammaticName(const SwFieldType& rType, SwDoc& rDoc);
static OUString LocalizeFormula(const SwSetExpField& rFld, const OUString& rFormula, bool bQuery);
diff --git a/sw/source/core/unocore/unocoll.cxx b/sw/source/core/unocore/unocoll.cxx
index e9dcf830bbe6..a7ff947b1c92 100644
--- a/sw/source/core/unocore/unocoll.cxx
+++ b/sw/source/core/unocore/unocoll.cxx
@@ -774,7 +774,7 @@ uno::Reference< uno::XInterface > SwXServiceProvider::MakeInstance(sal_uInt16
case SW_SERVICE_FIELDMASTER_SET_EXP : nResId = RES_SETEXPFLD; break;
case SW_SERVICE_FIELDMASTER_DATABASE: nResId = RES_DBFLD; break;
}
- xRet = (cppu::OWeakObject*)new SwXFieldMaster(pDoc, nResId);
+ xRet = SwXFieldMaster::CreateXFieldMaster(*pDoc, 0, nResId);
}
break;
case SW_SERVICE_FIELDMASTER_BIBLIOGRAPHY:
@@ -785,7 +785,7 @@ uno::Reference< uno::XInterface > SwXServiceProvider::MakeInstance(sal_uInt16
SwAuthorityFieldType aType(pDoc);
pType = pDoc->getIDocumentFieldsAccess().InsertFldType(aType);
}
- xRet = SwXFieldMaster::CreateXFieldMaster(*pDoc, *pType);
+ xRet = SwXFieldMaster::CreateXFieldMaster(*pDoc, pType);
}
break;
case SW_SERVICE_PARAGRAPH :
diff --git a/sw/source/core/unocore/unofield.cxx b/sw/source/core/unocore/unofield.cxx
index 353d0d4d4505..c271a8200c33 100644
--- a/sw/source/core/unocore/unofield.cxx
+++ b/sw/source/core/unocore/unofield.cxx
@@ -412,9 +412,9 @@ class SwXFieldMaster::Impl
{
private:
::osl::Mutex m_Mutex; // just for OInterfaceContainerHelper
- SwXFieldMaster & m_rThis;
public:
+ uno::WeakReference<uno::XInterface> m_wThis;
::cppu::OInterfaceContainerHelper m_EventListeners;
SwDoc* m_pDoc;
@@ -434,10 +434,9 @@ public:
bool m_bParam1; // IsExpression
sal_Int32 m_nParam2;
- Impl(SwXFieldMaster & rThis, SwModify *const pModify,
+ Impl(SwModify *const pModify,
SwDoc & rDoc, sal_uInt16 const nResId, bool const bIsDescriptor)
: SwClient(pModify)
- , m_rThis(rThis)
, m_EventListeners(m_Mutex)
, m_pDoc(& rDoc)
, m_bIsDescriptor(bIsDescriptor)
@@ -526,13 +525,13 @@ SwXFieldMaster::getSupportedServiceNames() throw (uno::RuntimeException, std::ex
}
SwXFieldMaster::SwXFieldMaster(SwDoc *const pDoc, sal_uInt16 const nResId)
- : m_pImpl(new Impl(*this, pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_STANDARD),
+ : m_pImpl(new Impl(pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_STANDARD),
*pDoc, nResId, true))
{
}
SwXFieldMaster::SwXFieldMaster(SwFieldType& rType, SwDoc & rDoc)
- : m_pImpl(new Impl(*this, &rType, rDoc, rType.Which(), false))
+ : m_pImpl(new Impl(&rType, rDoc, rType.Which(), false))
{
}
@@ -541,15 +540,27 @@ SwXFieldMaster::~SwXFieldMaster()
}
uno::Reference<beans::XPropertySet>
-SwXFieldMaster::CreateXFieldMaster(SwDoc & rDoc, SwFieldType & rType)
+SwXFieldMaster::CreateXFieldMaster(SwDoc & rDoc, SwFieldType *const pType,
+ sal_uInt16 nResId)
{
// re-use existing SwXFieldMaster
- uno::Reference<beans::XPropertySet> xFM(rType.GetXObject());
+ uno::Reference<beans::XPropertySet> xFM;
+ if (pType)
+ {
+ xFM = pType->GetXObject();
+ }
if (!xFM.is())
{
- SwXFieldMaster *const pFM(new SwXFieldMaster(rType, rDoc));
+ SwXFieldMaster *const pFM( (pType)
+ ? new SwXFieldMaster(*pType, rDoc)
+ : new SwXFieldMaster(& rDoc, nResId));
xFM.set(pFM);
- rType.SetXObject(xFM);
+ if (pType)
+ {
+ pType->SetXObject(xFM);
+ }
+ // need a permanent Reference to initialize m_wThis
+ pFM->m_pImpl->m_wThis = xFM;
}
return xFM;
}
@@ -1020,12 +1031,19 @@ void SwXFieldMaster::Impl::Modify(
SfxPoolItem const*const pOld, SfxPoolItem const*const pNew)
{
ClientModify(this, pOld, pNew);
- if(!GetRegisteredIn())
+ if (GetRegisteredIn())
{
- m_pDoc = 0;
- lang::EventObject const ev(static_cast< ::cppu::OWeakObject&>(m_rThis));
- m_EventListeners.disposeAndClear(ev);
+ return; // core object still alive
+ }
+
+ 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);
}
OUString SwXFieldMaster::GetProgrammaticName(const SwFieldType& rType, SwDoc& rDoc)
@@ -1293,7 +1311,7 @@ SwXTextField::getTextFieldMaster() throw (uno::RuntimeException, std::exception)
}
uno::Reference<beans::XPropertySet> const xRet(
- SwXFieldMaster::CreateXFieldMaster(*m_pImpl->m_pDoc, *pType));
+ SwXFieldMaster::CreateXFieldMaster(*m_pImpl->m_pDoc, pType));
return xRet;
}
@@ -2741,7 +2759,7 @@ uno::Any SwXTextFieldMasters::getByName(const OUString& rName)
css::uno::Reference<css::uno::XInterface>());
uno::Reference<beans::XPropertySet> const xRet(
- SwXFieldMaster::CreateXFieldMaster(*GetDoc(), *pType));
+ SwXFieldMaster::CreateXFieldMaster(*GetDoc(), pType));
return uno::makeAny(xRet);
}