summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2014-10-31 12:35:53 +0100
committerMichael Stahl <mstahl@redhat.com>2014-10-31 17:55:18 +0100
commit03cca068ed901d1862c440a6f414d17609785974 (patch)
tree49f1e8fe6beadc89e662ddbc54668595f8926fb7 /sc
parent21a5dc2ac524815a7b80fa54cd28a7b49aae6d5f (diff)
i#90076: avoid double-free race condition for ScCellRangesBase
This is similar to fdo#72695, just with SfxBroadcaster in Calc. Solve it in a similar way, by putting a WeakReference to "this" into the UNO object so its Notify() can return if another thread is already in the dtor waiting for the SolarMutex. ==11581==ERROR: AddressSanitizer: heap-use-after-free on address 0x6170006fdb08 at pc 0x2b2c4f5b8e3e bp 0x2b2c0b2ad9f0 sp 0x2b2c0b2ad9e8 READ of size 8 at 0x6170006fdb08 thread T262 (cppu_threadpool) #0 0x2b2c4f5b8e3d in ScCellRangesBase::~ScCellRangesBase() /sc/source/ui/unoobj/cellsuno.cxx:1448 #1 0x2b2c4f643914 in ScCellRangeObj::~ScCellRangeObj() /sc/source/ui/unoobj/cellsuno.cxx:4751 #2 0x2b2c4f697624 in ScCellObj::~ScCellObj() /sc/source/ui/unoobj/cellsuno.cxx:6053 #3 0x2b2c4f69648d in ScCellObj::~ScCellObj() /sc/source/ui/unoobj/cellsuno.cxx:6052 #4 0x2b2c4f69661f in non-virtual thunk to ScCellObj::~ScCellObj() /sc/source/ui/unoobj/cellsuno.cxx:6053 #5 0x2b2b2c58b6af in cppu::OWeakObject::release() /cppuhelper/source/weak.cxx:204 #6 0x2b2c4f5c50ff in ScCellRangesBase::release() /sc/source/ui/unoobj/cellsuno.cxx:1752 #7 0x2b2c4f64de58 in ScCellRangeObj::release() /sc/source/ui/unoobj/cellsuno.cxx:4800 #8 0x2b2c4f6a2c08 in ScCellObj::release() /sc/source/ui/unoobj/cellsuno.cxx:6093 #9 0x2b2c4f6a5f0f in non-virtual thunk to ScCellObj::release() /sc/source/ui/unoobj/cellsuno.cxx:6094 #10 0x2b2c053b96fb in bridges::cpp_uno::shared::freeUnoInterfaceProxy(_uno_ExtEnvironment*, void*) /bridges/source/cpp_uno/shared/unointerfaceproxy.cxx:43 #11 0x2b2b2bae80fb in (anonymous namespace)::s_stub_defenv_revokeInterface(__va_list_tag (*) [1]) /cppu/source/uno/lbenv.cxx:383 0x6170006fdb08 is located 264 bytes inside of 728-byte region [0x6170006fda00,0x6170006fdcd8) freed by thread T264 (cppu_threadpool) here: #3 0x2b2c49c980f5 in cppu::OWeakObject::operator delete(void*) /include/cppuhelper/weak.hxx:87 #4 0x2b2c4f5b840a in ScCellRangesBase::~ScCellRangesBase() /sc/source/ui/unoobj/cellsuno.cxx:1442 #5 0x2b2c4f5b858f in non-virtual thunk to ScCellRangesBase::~ScCellRangesBase() /sc/source/ui/unoobj/cellsuno.cxx:1458 #6 0x2b2b2c58b6af in cppu::OWeakObject::release() /cppuhelper/source/weak.cxx:204 #7 0x2b2c4f5c50ff in ScCellRangesBase::release() /sc/source/ui/unoobj/cellsuno.cxx:1752 #8 0x2b2c4f5c65ff in non-virtual thunk to ScCellRangesBase::release() /sc/source/ui/unoobj/cellsuno.cxx:1753 #9 0x2b2c4af84583 in com::sun::star::uno::Reference<com::sun::star::uno::XInterface>::~Reference() /include/com/sun/star/uno/Reference.hxx:104 #10 0x2b2c4f5bc66f in ScCellRangesBase::Notify(SfxBroadcaster&, SfxHint const&) /sc/source/ui/unoobj/cellsuno.cxx:1570 #11 0x2b2c4f5bdf0d in non-virtual thunk to ScCellRangesBase::Notify(SfxBroadcaster&, SfxHint const&) /sc/source/ui/unoobj/cellsuno.cxx:1645 #12 0x2b2b31dda705 in SfxBroadcaster::Broadcast(SfxHint const&) /svl/source/notify/SfxBroadcaster.cxx:41 #13 0x2b2c4b03f2e4 in ScDocument::InsertTab(short, rtl::OUString const&, bool, bool) /sc/source/core/data/document.cxx:510 #14 0x2b2c4e7ed861 in ScDocFunc::InsertTable(short, rtl::OUString const&, bool, bool) /sc/source/ui/docshell/docfunc.cxx:3007 #15 0x2b2c50b1f415 in ScViewFunc::InsertTable(rtl::OUString const&, short, bool) /sc/source/ui/view/viewfun2.cxx:1855 #16 0x2b2c502e075f in ScDBFunc::ShowDataPilotSourceData(ScDPObject&, com::sun::star::uno::Sequence<com::sun::star::sheet::DataPilotFieldFilter> const&) /sc/source/ui/view/dbfunc3.cxx:2056 #17 0x2b2c4fa8924d in ScDataPilotTableObj::insertDrillDownSheet(com::sun::star::table::CellAddress const&) /sc/source/ui/unoobj/dapiuno.cxx:1286 Change-Id: I4cd0fca46b9b81311bddfab2229ab9abf4c06c4e
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/cellsuno.hxx1
-rw-r--r--sc/source/ui/unoobj/cellsuno.cxx28
2 files changed, 25 insertions, 4 deletions
diff --git a/sc/inc/cellsuno.hxx b/sc/inc/cellsuno.hxx
index 7408ee2a5f44..0ec4e6cfa5a5 100644
--- a/sc/inc/cellsuno.hxx
+++ b/sc/inc/cellsuno.hxx
@@ -175,6 +175,7 @@ class SC_DLLPUBLIC ScCellRangesBase : public com::sun::star::beans::XPropertySet
friend class ooo::vba::excel::ScVbaCellRangeAccess;
private:
+ css::uno::WeakReference<css::uno::XInterface> m_wThis;
const SfxItemPropertySet* pPropSet;
ScDocShell* pDocShell;
ScLinkListener* pValueListener;
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index 9280d96418ed..7a50745eea01 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -1401,6 +1401,15 @@ ScCellRangesBase::ScCellRangesBase(ScDocShell* pDocSh, const ScRange& rR) :
bGotDataChangedHint( false ),
aValueListeners( 0 )
{
+ // this is a hack to get m_wThis initialized; ideally there would be
+ // factory functions doing this but there are so many subclasses of this...
+ ++m_refCount;
+ {
+ m_wThis = uno::Reference<uno::XInterface>(
+ static_cast<cppu::OWeakObject*>(this));
+ }
+ --m_refCount;
+
ScRange aCellRange(rR);
aCellRange.Justify();
aRanges.Append( aCellRange );
@@ -1430,6 +1439,15 @@ ScCellRangesBase::ScCellRangesBase(ScDocShell* pDocSh, const ScRangeList& rR) :
bGotDataChangedHint( false ),
aValueListeners( 0 )
{
+ // this is a hack to get m_wThis initialized; ideally there would be
+ // factory functions doing this but there are so many subclasses of this...
+ ++m_refCount;
+ {
+ m_wThis = uno::Reference<uno::XInterface>(
+ static_cast<cppu::OWeakObject*>(this));
+ }
+ --m_refCount;
+
if (pDocShell) // Null if created with createInstance
{
ScDocument& rDoc = pDocShell->GetDocument();
@@ -1529,6 +1547,11 @@ const ScMarkData* ScCellRangesBase::GetMarkData()
void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
+ 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;
+ }
if ( dynamic_cast<const ScUpdateRefHint*>(&rHint) )
{
const ScUpdateRefHint& rRef = static_cast<const ScUpdateRefHint&>(rHint);
@@ -1541,12 +1564,9 @@ void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint )
if ( aRanges.UpdateReference( rRef.GetMode(), &rDoc, rRef.GetRange(),
rRef.GetDx(), rRef.GetDy(), rRef.GetDz() ) )
{
- // i#90076; the object "this" was destroyed after calling ScTableSheetObj::getImplementation
- // this hack make sure that the object lives a bit longer
- uno::Reference<uno::XInterface> xInterface((cppu::OWeakObject*)this, uno::UNO_QUERY);
if ( rRef.GetMode() == URM_INSDEL
&& aRanges.size() == 1
- && ScTableSheetObj::getImplementation( xInterface )
+ && ScTableSheetObj::getImplementation(xThis)
)
{
// #101755#; the range size of a sheet does not change