tdf#122020 crash in SvTreeList::InvalidateEntry

a PostUserEvent of DBTreeListBox::OnResetEntry with a SvTreeListEntry* pEntry as
payload, then the DBTreeListBox is disposed and then the UserEvent arrives and
the, by now deleted, pEntry is processed by the disposed DBTreeListBox

Change-Id: I951639eb633920aa3536cd44320f36f6b2e910aa
Reviewed-on: https://gerrit.libreoffice.org/65514
Tested-by: Jenkins
Tested-by: Xisco Faulí <xiscofauli@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/dbaccess/source/ui/control/dbtreelistbox.cxx b/dbaccess/source/ui/control/dbtreelistbox.cxx
index d5b169b..085f22a 100644
--- a/dbaccess/source/ui/control/dbtreelistbox.cxx
+++ b/dbaccess/source/ui/control/dbtreelistbox.cxx
@@ -58,7 +58,8 @@ DBTreeListBox::DBTreeListBox( vcl::Window* pParent, WinBits nWinStyle )
    :SvTreeListBox(pParent,nWinStyle)
    ,m_pDragedEntry(nullptr)
    ,m_pActionListener(nullptr)
    ,m_pContextMenuProvider( nullptr )
    ,m_pContextMenuProvider(nullptr)
    ,m_pResetEvent(nullptr)
{
    init();
}
@@ -88,6 +89,11 @@ DBTreeListBox::~DBTreeListBox()

void DBTreeListBox::dispose()
{
    if (m_pResetEvent)
    {
        RemoveUserEvent(m_pResetEvent);
        m_pResetEvent = nullptr;
    }
    implStopSelectionTimer();
    SvTreeListBox::dispose();
}
@@ -118,11 +124,6 @@ SvTreeListEntry* DBTreeListBox::GetEntryPosByName( const OUString& aName, SvTree
    return pEntry;
}

void DBTreeListBox::EnableExpandHandler(SvTreeListEntry* _pEntry)
{
    LINK(this, DBTreeListBox, OnResetEntry).Call(_pEntry);
}

void DBTreeListBox::RequestingChildren( SvTreeListEntry* pParent )
{
    if (m_aPreExpandHandler.IsSet() && !m_aPreExpandHandler.Call(pParent))
@@ -130,7 +131,7 @@ void DBTreeListBox::RequestingChildren( SvTreeListEntry* pParent )
        // an error occurred. The method calling us will reset the entry flags, so it can't be expanded again.
        // But we want that the user may do a second try (i.e. because he mistypes a password in this try), so
        // we have to reset these flags controlling the expand ability
        PostUserEvent(LINK(this, DBTreeListBox, OnResetEntry), pParent, true);
        m_pResetEvent = PostUserEvent(LINK(this, DBTreeListBox, OnResetEntryHdl), pParent, true);
    }
}

@@ -176,15 +177,20 @@ void DBTreeListBox::MouseButtonDown( const MouseEvent& rMEvt )
        SvTreeListBox::MouseButtonDown(rMEvt);
}

IMPL_LINK(DBTreeListBox, OnResetEntry, void*, p, void)
void DBTreeListBox::EnableExpandHandler(SvTreeListEntry* pEntry)
{
    SvTreeListEntry* pEntry = static_cast<SvTreeListEntry*>(p);
    // set the flag which allows if the entry can be expanded
    pEntry->SetFlags( (pEntry->GetFlags() & ~SvTLEntryFlags(SvTLEntryFlags::NO_NODEBMP | SvTLEntryFlags::HAD_CHILDREN)) | SvTLEntryFlags::CHILDREN_ON_DEMAND );
    // redraw the entry
    GetModel()->InvalidateEntry( pEntry );
}

IMPL_LINK(DBTreeListBox, OnResetEntryHdl, void*, p, void)
{
    m_pResetEvent = nullptr;
    EnableExpandHandler(static_cast<SvTreeListEntry*>(p));
}

void DBTreeListBox::ModelHasEntryInvalidated( SvTreeListEntry* _pEntry )
{
    SvTreeListBox::ModelHasEntryInvalidated( _pEntry );
diff --git a/dbaccess/source/ui/inc/dbtreelistbox.hxx b/dbaccess/source/ui/inc/dbtreelistbox.hxx
index 3a969d4..a632e99 100644
--- a/dbaccess/source/ui/inc/dbtreelistbox.hxx
+++ b/dbaccess/source/ui/inc/dbtreelistbox.hxx
@@ -57,6 +57,7 @@ namespace dbaui
        SvTreeListEntry*            m_pDragedEntry;
        IControlActionListener*     m_pActionListener;
        IContextMenuProvider*       m_pContextMenuProvider;
        ImplSVEvent*                m_pResetEvent;
        css::uno::Reference<css::frame::XPopupMenuController> m_xMenuController;

        Link<SvTreeListEntry*,bool> m_aPreExpandHandler;    // handler to be called before a node is expanded
@@ -69,7 +70,7 @@ namespace dbaui
    private:
        void init();
        DECL_LINK( OnTimeOut, Timer*, void );
        DECL_LINK( OnResetEntry, void*, void );
        DECL_LINK( OnResetEntryHdl, void*, void );
        DECL_LINK( ScrollUpHdl, LinkParamNone*, void );
        DECL_LINK( ScrollDownHdl, LinkParamNone*, void );
        DECL_LINK( MenuEventListener, VclMenuEvent&, void );