basic/source/classes/sbxmod.cxx                     |   13 -
 compilerplugins/clang/weakobject.cxx                |  154 ++++++++++++++++++++
 dbaccess/source/ui/inc/exsrcbrw.hxx                 |    2 
 extensions/source/propctrlr/composeduiupdate.cxx    |    5 
 scripting/source/provider/BrowseNodeFactoryImpl.cxx |    7 
 sw/source/core/access/acctable.hxx                  |    4 
 6 files changed, 164 insertions(+), 21 deletions(-)

New commits:
commit 136a2fd6c08193793d546e69108765316c96668b
Author: Michael Stahl <mst...@redhat.com>
Date:   Mon Jun 20 23:38:11 2016 +0200

    compilerplugins: add OWeakObject::release() override check
    
    Change-Id: I767857545d7c91615cf162790c04f0016de9fdf6
    Reviewed-on: https://gerrit.libreoffice.org/26555
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>
    Tested-by: Stephan Bergmann <sberg...@redhat.com>

diff --git a/basic/source/classes/sbxmod.cxx b/basic/source/classes/sbxmod.cxx
index ef6a679..7970f04 100644
--- a/basic/source/classes/sbxmod.cxx
+++ b/basic/source/classes/sbxmod.cxx
@@ -175,21 +175,14 @@ DocObjectWrapper::DocObjectWrapper( SbModule* pVar ) : 
m_pMod( pVar ), mName( pV
 void SAL_CALL
 DocObjectWrapper::acquire() throw ()
 {
-    osl_atomic_increment( &m_refCount );
+    OWeakObject::acquire();
     SAL_INFO("basic","DocObjectWrapper::acquire("<< OUStringToOString( mName, 
RTL_TEXTENCODING_UTF8 ).getStr() << ") 0x" << this << " refcount is now " << 
m_refCount );
 }
 void SAL_CALL
 DocObjectWrapper::release() throw ()
 {
-    if ( osl_atomic_decrement( &m_refCount ) == 0 )
-    {
-        SAL_INFO("basic","DocObjectWrapper::release("<< OUStringToOString( 
mName, RTL_TEXTENCODING_UTF8 ).getStr() << ") 0x" << this << " refcount is now 
" << m_refCount );
-        delete this;
-    }
-    else
-    {
-        SAL_INFO("basic","DocObjectWrapper::release("<< OUStringToOString( 
mName, RTL_TEXTENCODING_UTF8 ).getStr() << ") 0x" << this << " refcount is now 
" << m_refCount );
-    }
+    SAL_INFO("basic","DocObjectWrapper::release("<< OUStringToOString( mName, 
RTL_TEXTENCODING_UTF8 ).getStr() << ") 0x" << this << " decrementing refcount, 
was " << m_refCount );
+    OWeakObject::release();
 }
 
 DocObjectWrapper::~DocObjectWrapper()
diff --git a/compilerplugins/clang/weakobject.cxx 
b/compilerplugins/clang/weakobject.cxx
new file mode 100644
index 0000000..42bdf6e
--- /dev/null
+++ b/compilerplugins/clang/weakobject.cxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "plugin.hxx"
+#include "typecheck.hxx"
+
+/* OWeakObject::release() disposes weak references.  If that isn't done
+ * because a sub-class improperly overrides release() then
+ * OWeakConnectionPoint::m_pObject continues to point to the deleted object
+ * and that could result in use-after-free.
+ */
+
+namespace {
+
+class WeakObject
+    : public clang::RecursiveASTVisitor<WeakObject>
+    , public loplugin::Plugin
+{
+
+public:
+    explicit WeakObject(InstantiationData const& rData) : Plugin(rData) {}
+
+    void run() override {
+        if (compiler.getLangOpts().CPlusPlus) { // no OWeakObject in C
+            TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
+        }
+    }
+
+    bool isDerivedFromOWeakObject(CXXMethodDecl const*const pMethodDecl)
+    {
+        QualType const pClass(pMethodDecl->getParent()->getTypeForDecl(), 0);
+        if (loplugin::TypeCheck(pClass).Class("OWeakObject").Namespace("cppu"))
+        {
+            return true;
+        }
+        // hopefully it's faster to recurse overridden methods than the
+        // thicket of WeakImplHelper32 but that is purely speculation
+        for (auto it = pMethodDecl->begin_overridden_methods();
+             it != pMethodDecl->end_overridden_methods(); ++it)
+        {
+            if (isDerivedFromOWeakObject(*it))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    bool VisitCXXMethodDecl(CXXMethodDecl const*const pMethodDecl)
+    {
+        if (ignoreLocation(pMethodDecl)) {
+            return true;
+        }
+        if (!pMethodDecl->isThisDeclarationADefinition()) {
+            return true;
+        }
+        if (!pMethodDecl->isInstance()) {
+            return true;
+        }
+// this is too "simple", if a NamedDecl class has a getName() member expecting 
it to actually work would clearly be unreasonable    if (pMethodDecl->getName() 
!= "release") {
+        if (auto const i = pMethodDecl->getIdentifier()) {
+            if (i != nullptr && !i->isStr("release")) {
+                return true;
+            }
+        }
+        if (pMethodDecl->getNumParams() != 0) {
+            return true;
+        }
+        if 
(loplugin::TypeCheck(QualType(pMethodDecl->getParent()->getTypeForDecl(), 
0)).Class("OWeakObject").Namespace("cppu"))
+        {
+            return true;
+        }
+
+        CXXMethodDecl const* pOverridden(nullptr);
+        for (auto it = pMethodDecl->begin_overridden_methods();
+             it != pMethodDecl->end_overridden_methods(); ++it)
+        {
+            if (auto const i = (*it)->getIdentifier()) {
+                if (i != nullptr && i->isStr("release")) {
+                    pOverridden = *it;
+                    break;
+                }
+            }
+        }
+        if (pOverridden == nullptr)
+        {
+            return true;
+        }
+        if (!isDerivedFromOWeakObject(pOverridden))
+        {
+            return true;
+        }
+        CompoundStmt const*const pCompoundStatement(
+                dyn_cast<CompoundStmt>(pMethodDecl->getBody()));
+        for (auto const pStmt : pCompoundStatement->body())
+        {
+            // note: this is not a CXXMemberCallExpr
+            CallExpr const*const pCallExpr(dyn_cast<CallExpr>(pStmt));
+            if (pCallExpr)
+            {
+                // note: this is only sometimes a CXXMethodDecl
+                FunctionDecl const*const pCalled(pCallExpr->getDirectCallee());
+                if (pCalled->getName() == "release"
+//this never works  && pCalled == pOverridden
+                    && (pCalled->getParent() == pOverridden->getParent()
+                        // allow this convenient shortcut
+                        || 
loplugin::TypeCheck(QualType(pMethodDecl->getParent()->getTypeForDecl(), 
0)).Class("OWeakObject").Namespace("cppu")
+                        || 
loplugin::TypeCheck(QualType(pMethodDecl->getParent()->getTypeForDecl(), 
0)).Class("OWeakAggObject").Namespace("cppu")))
+                {
+                    return true;
+                }
+                if (pCalled->getName() == "relase_ChildImpl") // FIXME remove 
this lunacy
+                {
+                    return true;
+                }
+            }
+        }
+
+        // whitelist
+        auto const name(pMethodDecl->getParent()->getQualifiedNameAsString());
+        if (   name == "cppu::OWeakAggObject" // conditional call
+            || name == "cppu::WeakComponentImplHelperBase" // extra magic
+            || name == "cppu::WeakAggComponentImplHelperBase" // extra magic
+            || name == "DOM::CDOMImplementation" // a static oddity
+            || name == "SwXTextFrame" // ambiguous, 3 parents
+            || name == "SwXTextDocument" // ambiguous, ~4 parents
+            || name == "SdStyleSheet" // same extra magic as 
WeakComponentImplHelperBase
+            || name == "SdXImpressDocument" // same extra magic as 
WeakComponentImplHelperBase
+           )
+        {
+            return true;
+        }
+
+        report(DiagnosticsEngine::Warning,
+                "override of OWeakObject::release() does not call superclass 
release()",
+                pMethodDecl->getLocation())
+            << pMethodDecl->getSourceRange();
+
+        return true;
+    }
+
+};
+
+loplugin::Plugin::Registration<WeakObject> X("weakobject");
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/ui/inc/exsrcbrw.hxx 
b/dbaccess/source/ui/inc/exsrcbrw.hxx
index 3a533e8..53a10bb 100644
--- a/dbaccess/source/ui/inc/exsrcbrw.hxx
+++ b/dbaccess/source/ui/inc/exsrcbrw.hxx
@@ -50,7 +50,7 @@ namespace dbaui
                 SAL_CALL Create(const css::uno::Reference< 
css::lang::XMultiServiceFactory >&);
 
         // UNO
-        DECLARE_UNO3_DEFAULTS(SbaExternalSourceBrowser, OGenericUnoController)
+        DECLARE_UNO3_DEFAULTS(SbaExternalSourceBrowser, 
SbaXDataBrowserController)
         virtual css::uno::Any  SAL_CALL queryInterface(const css::uno::Type& 
_rType) throw (css::uno::RuntimeException, std::exception) override;
         //  virtual css::uno::Sequence< css::uno::Reference< 
css::reflection::XIdlClass > >  getIdlClasses();
 
diff --git a/extensions/source/propctrlr/composeduiupdate.cxx 
b/extensions/source/propctrlr/composeduiupdate.cxx
index 8ad15cff..5fde3d3 100644
--- a/extensions/source/propctrlr/composeduiupdate.cxx
+++ b/extensions/source/propctrlr/composeduiupdate.cxx
@@ -211,14 +211,13 @@ namespace pcr
 
     void SAL_CALL CachedInspectorUI::acquire() throw()
     {
-        osl_atomic_increment( &m_refCount );
+        CachedInspectorUI_Base::acquire();
     }
 
 
     void SAL_CALL CachedInspectorUI::release() throw()
     {
-        if ( 0 == osl_atomic_decrement( &m_refCount ) )
-            delete this;
+        CachedInspectorUI_Base::release();
     }
 
 
diff --git a/scripting/source/provider/BrowseNodeFactoryImpl.cxx 
b/scripting/source/provider/BrowseNodeFactoryImpl.cxx
index 863860e..a312ed4a 100644
--- a/scripting/source/provider/BrowseNodeFactoryImpl.cxx
+++ b/scripting/source/provider/BrowseNodeFactoryImpl.cxx
@@ -500,15 +500,12 @@ public:
         throw () override
 
     {
-        osl_atomic_increment( &m_refCount );
+        t_BrowseNodeBase::acquire();
     }
     virtual void SAL_CALL release()
         throw () override
     {
-        if ( osl_atomic_decrement( &m_refCount ) == 0 )
-        {
-            delete this;
-        }
+        t_BrowseNodeBase::release();
     }
     // XTypeProvider (implemnented by base, but needs to be overridden for
     //                delegating to aggregate)
diff --git a/sw/source/core/access/acctable.hxx 
b/sw/source/core/access/acctable.hxx
index 84930ef..857636e 100644
--- a/sw/source/core/access/acctable.hxx
+++ b/sw/source/core/access/acctable.hxx
@@ -301,10 +301,10 @@ public:
         throw (css::uno::RuntimeException, std::exception) override;
 
     virtual void SAL_CALL acquire(  ) throw () override
-        { SwAccessibleContext::acquire(); };
+        { SwAccessibleTable::acquire(); };
 
     virtual void SAL_CALL release(  ) throw () override
-        { SwAccessibleContext::release(); };
+        { SwAccessibleTable::release(); };
 
     // XAccessibleContext
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to