From 390eaa736364a59e479a849598677b1a6a87f24e Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Fri, 9 Sep 2011 08:59:20 +0200 Subject: sb140: #i114718# avoid references to object across XAggregation::setDelegator boundary --- forms/source/component/FormattedFieldWrapper.cxx | 170 ++++++++++------------- forms/source/component/FormattedFieldWrapper.hxx | 3 +- 2 files changed, 76 insertions(+), 97 deletions(-) (limited to 'forms') diff --git a/forms/source/component/FormattedFieldWrapper.cxx b/forms/source/component/FormattedFieldWrapper.cxx index 118c06921ce1..a76ff20c6fb0 100644 --- a/forms/source/component/FormattedFieldWrapper.cxx +++ b/forms/source/component/FormattedFieldWrapper.cxx @@ -36,6 +36,7 @@ #include "services.hxx" #include #include +#include "boost/noncopyable.hpp" //......................................................................... namespace frm @@ -52,6 +53,21 @@ using namespace ::com::sun::star::io; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::util; +namespace { + +class RefCountGuard: private boost::noncopyable { +public: + explicit RefCountGuard(oslInterlockedCount & count): count_(count) + { osl_incrementInterlockedCount(&count_); } + + ~RefCountGuard() { osl_decrementInterlockedCount(&count_); } + +private: + oslInterlockedCount & count_; +}; + +} + //================================================================== // OFormattedFieldWrapper //================================================================== @@ -71,40 +87,26 @@ InterfaceRef SAL_CALL OFormattedFieldWrapper_CreateInstance(const Reference& _rxFactory, sal_Bool _bActAsFormatted) :m_xServiceFactory(_rxFactory) - ,m_pEditPart(NULL) { DBG_CTOR(OFormattedFieldWrapper, NULL); if (_bActAsFormatted) { - increment(m_refCount); + RefCountGuard g(m_refCount); { - // instantiate an FormattedModel - InterfaceRef xFormattedModel; - // (instantiate it directly ..., as the OFormattedModel isn't registered for any service names anymore) - OFormattedModel* pModel = new OFormattedModel(m_xServiceFactory); - query_interface(static_cast(pModel), xFormattedModel); - - m_xAggregate = Reference (xFormattedModel, UNO_QUERY); - DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::OFormattedFieldWrapper : the OFormattedModel didn't have an XAggregation interface !"); - - // _before_ setting the delegator, give it to the member references - query_interface(xFormattedModel, m_xFormattedPart); - m_pEditPart = new OEditModel(m_xServiceFactory); - m_pEditPart->acquire(); - } - if (m_xAggregate.is()) - { // has to be in it's own block because of the temporary variable created by *this - m_xAggregate->setDelegator(static_cast(this)); + // instantiate an FormattedModel (instantiate it directly, as the + // OFormattedModel isn't registered for any service names anymore) + m_xFormattedPart.set(new OFormattedModel(m_xServiceFactory)); + m_editPart.set(new OEditModel(m_xServiceFactory)); + m_xAggregate.set(m_xFormattedPart, UNO_QUERY_THROW); } - decrement(m_refCount); + m_xAggregate->setDelegator(static_cast< OWeakObject * >(this)); } } //------------------------------------------------------------------ OFormattedFieldWrapper::OFormattedFieldWrapper( const OFormattedFieldWrapper* _pCloneSource ) :m_xServiceFactory( _pCloneSource->m_xServiceFactory ) - ,m_pEditPart( NULL ) { Reference< XCloneable > xCloneAccess; query_aggregation( _pCloneSource->m_xAggregate, xCloneAccess ); @@ -112,25 +114,19 @@ OFormattedFieldWrapper::OFormattedFieldWrapper( const OFormattedFieldWrapper* _p // clone the aggregate if ( xCloneAccess.is() ) { - increment( m_refCount ); + RefCountGuard g(m_refCount); { - Reference< XCloneable > xClone = xCloneAccess->createClone(); - m_xAggregate = Reference< XAggregation >( xClone, UNO_QUERY ); - DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::OFormattedFieldWrapper : invalid aggregate clone!"); - - query_interface( Reference< XInterface >( xClone.get() ), m_xFormattedPart ); - - if ( _pCloneSource->m_pEditPart ) + m_xFormattedPart.set(xCloneAccess->createClone(), UNO_QUERY_THROW); + if (_pCloneSource->m_editPart.is()) { - m_pEditPart = new OEditModel( _pCloneSource->m_pEditPart, _pCloneSource->m_xServiceFactory ); - m_pEditPart->acquire(); + m_editPart.set( + new OEditModel( + _pCloneSource->m_editPart.get(), + _pCloneSource->m_xServiceFactory)); } + m_xAggregate.set(m_xFormattedPart, UNO_QUERY_THROW); } - if ( m_xAggregate.is() ) - { // has to be in it's own block because of the temporary variable created by *this - m_xAggregate->setDelegator( static_cast< XWeak* >( this ) ); - } - decrement( m_refCount ); + m_xAggregate->setDelegator(static_cast< OWeakObject * >(this)); } else { // the clone source does not yet have an aggregate -> we don't yet need one, too @@ -144,9 +140,6 @@ OFormattedFieldWrapper::~OFormattedFieldWrapper() if (m_xAggregate.is()) m_xAggregate->setDelegator(InterfaceRef ()); - if (m_pEditPart) - m_pEditPart->release(); - DBG_DTOR(OFormattedFieldWrapper, NULL); } @@ -245,22 +238,24 @@ void SAL_CALL OFormattedFieldWrapper::write(const Reference } // else we have to write an edit part first - DBG_ASSERT(m_pEditPart, "OFormattedFieldWrapper::write : formatted part without edit part ?"); - if ( !m_pEditPart ) + DBG_ASSERT( + m_editPart.is(), + "OFormattedFieldWrapper::write: formatted part without edit part?"); + if (!m_editPart.is()) throw RuntimeException( ::rtl::OUString(), *this ); // for this we transfer the current props of the formatted part to the edit part Reference xFormatProps(m_xFormattedPart, UNO_QUERY); - Reference xEditProps; - query_interface(static_cast(m_pEditPart), xEditProps); + Reference xEditProps( + static_cast< OWeakObject * >(m_editPart.get()), UNO_QUERY); Locale aAppLanguage = Application::GetSettings().GetUILocale(); dbtools::TransferFormComponentProperties(xFormatProps, xEditProps, aAppLanguage); // then write the edit part, after switching to "fake mode" - m_pEditPart->enableFormattedWriteFake(); - m_pEditPart->write(_rxOutStream); - m_pEditPart->disableFormattedWriteFake(); + m_editPart->enableFormattedWriteFake(); + m_editPart->write(_rxOutStream); + m_editPart->disableFormattedWriteFake(); // and finally write the formatted part we're really interested in m_xFormattedPart->write(_rxOutStream); @@ -285,10 +280,10 @@ void SAL_CALL OFormattedFieldWrapper::read(const Reference& DBG_ASSERT(xInMarkable.is(), "OFormattedFieldWrapper::read : can only work with markable streams !"); sal_Int32 nBeforeEditPart = xInMarkable->createMark(); - m_pEditPart->read(_rxInStream); + m_editPart->read(_rxInStream); // this only works because an edit model can read the stuff written by a formatted model (maybe with // some assertions) , but not vice versa - if (!m_pEditPart->lastReadWasFormattedFake()) + if (!m_editPart->lastReadWasFormattedFake()) { // case a), written with a version without the edit part fake, so seek to the start position, again xInMarkable->jumpToMark(nBeforeEditPart); } @@ -306,45 +301,32 @@ void SAL_CALL OFormattedFieldWrapper::read(const Reference& } // we have to decide from the data within the stream whether we should be an EditModel or a FormattedModel - OEditBaseModel* pNewAggregate = NULL; - - // let an OEditModel do the reading - OEditModel* pBasicReader = new OEditModel(m_xServiceFactory); - Reference< XInterface > xHoldBasicReaderAlive( *pBasicReader ); - pBasicReader->read(_rxInStream); - - // was it really an edit model ? - if (!pBasicReader->lastReadWasFormattedFake()) - // yes -> all fine - pNewAggregate = pBasicReader; - else - { // no -> substitute it with a formatted model - - // let the formmatted model do the reading - OFormattedModel* pFormattedReader = new OFormattedModel(m_xServiceFactory); - Reference< XInterface > xHoldAliveWhileRead( *pFormattedReader ); - pFormattedReader->read(_rxInStream); - - // for the next write (if any) : the FormattedModel and the EditModel parts - query_interface(static_cast(pFormattedReader), m_xFormattedPart); - m_pEditPart = pBasicReader; - m_pEditPart->acquire(); - - // aggregate the formatted part below - pNewAggregate = pFormattedReader; - } - - // do the aggregation - increment(m_refCount); { - query_interface(static_cast(pNewAggregate), m_xAggregate); - DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::read : the OEditModel didn't have an XAggregation interface !"); - } - if (m_xAggregate.is()) - { // has to be in it's own block because of the temporary variable created by *this - m_xAggregate->setDelegator(static_cast(this)); + // let an OEditModel do the reading + rtl::Reference< OEditModel > basicReader( + new OEditModel(m_xServiceFactory)); + basicReader->read(_rxInStream); + + // was it really an edit model ? + if (!basicReader->lastReadWasFormattedFake()) + // yes -> all fine + m_xAggregate.set( + static_cast< OWeakObject * >(basicReader.get()), + UNO_QUERY_THROW); + else + { // no -> substitute it with a formatted model + + // let the formmatted model do the reading + m_xFormattedPart.set(new OFormattedModel(m_xServiceFactory)); + m_xFormattedPart->read(_rxInStream); + + m_editPart = basicReader; + + m_xAggregate.set(m_xFormattedPart, UNO_QUERY_THROW); + } } - decrement(m_refCount); + RefCountGuard g(m_refCount); + m_xAggregate->setDelegator(static_cast< OWeakObject * >(this)); } //------------------------------------------------------------------ @@ -361,7 +343,7 @@ void OFormattedFieldWrapper::ensureAggregate() if (m_xAggregate.is()) return; - increment(m_refCount); + RefCountGuard g(m_refCount); { // instantiate an EditModel (the only place where we are allowed to decide that we're an FormattedModel // is in ::read) @@ -373,23 +355,19 @@ void OFormattedFieldWrapper::ensureAggregate() query_interface(static_cast(pModel), xEditModel); } - m_xAggregate = Reference (xEditModel, UNO_QUERY); - DBG_ASSERT(m_xAggregate.is(), "OFormattedFieldWrapper::ensureAggregate : the OEditModel didn't have an XAggregation interface !"); + m_xAggregate = Reference (xEditModel, UNO_QUERY_THROW); + Reference< XServiceInfo > xSI(m_xAggregate, UNO_QUERY); + if (!xSI.is()) { - Reference< XServiceInfo > xSI(m_xAggregate, UNO_QUERY); - if (!xSI.is()) - { - OSL_FAIL("OFormattedFieldWrapper::ensureAggregate: the aggregate has no XServiceInfo!"); - m_xAggregate.clear(); - } + OSL_FAIL("OFormattedFieldWrapper::ensureAggregate: the aggregate has no XServiceInfo!"); + m_xAggregate.clear(); } } if (m_xAggregate.is()) - { // has to be in it's own block because of the temporary variable created by *this + { m_xAggregate->setDelegator(static_cast(this)); } - decrement(m_refCount); } //......................................................................... diff --git a/forms/source/component/FormattedFieldWrapper.hxx b/forms/source/component/FormattedFieldWrapper.hxx index d7726ee428fa..489c7a26bf70 100644 --- a/forms/source/component/FormattedFieldWrapper.hxx +++ b/forms/source/component/FormattedFieldWrapper.hxx @@ -33,6 +33,7 @@ #include #include #include +#include "rtl/ref.hxx" //......................................................................... namespace frm @@ -54,7 +55,7 @@ class OFormattedFieldWrapper : public OFormattedFieldWrapper_Base protected: ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation> m_xAggregate; - OEditModel* m_pEditPart; + rtl::Reference< OEditModel > m_editPart; // if we act as formatted this is used to write the EditModel part ::com::sun::star::uno::Reference< ::com::sun::star::io::XPersistObject> m_xFormattedPart; // if we act as formatted, this is the PersistObject interface of our aggregate, used -- cgit