summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAron Budea <aron.budea@collabora.com>2017-04-03 02:21:28 +0200
committerAron Budea <aron.budea@collabora.com>2017-04-05 18:06:52 +0000
commit9fcb6cb86893b991ceb6395fbabba63c962f59db (patch)
treeebca63dc2945b5908609a91ede938a88a43c263f
parent137ad218db262fb3531215adbc88b7093b4999c7 (diff)
tdf#104686: do not crash if Menu has been somehow disposed
The rare crashes in MenuFloatingWindow::ImplGetStartY() and MenuFloatingWindow::ImplScroll(bool) likely happen because of a disposed Menu. Let's guard against invalid accesses. Change-Id: Ie31240abbc48c06edd40d0a95f319725cdb3db16 Reviewed-on: https://gerrit.libreoffice.org/36026 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Michael Meeks <michael.meeks@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/36151 Reviewed-by: Aron Budea <aron.budea@collabora.com>
-rw-r--r--include/vcl/menu.hxx4
-rw-r--r--vcl/source/window/menu.cxx4
-rw-r--r--vcl/source/window/menufloatingwindow.cxx74
-rw-r--r--vcl/source/window/menuitemlist.cxx7
-rw-r--r--vcl/source/window/menuitemlist.hxx1
5 files changed, 58 insertions, 32 deletions
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index 3c132cc32e07..1c2e82a69683 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -133,7 +133,7 @@ class VCL_DLLPUBLIC Menu : public Resource, public VclReferenceBase
friend struct ImplMenuDelData;
private:
ImplMenuDelData* mpFirstDel;
- MenuItemList* pItemList; // Liste mit den MenuItems
+ std::unique_ptr<MenuItemList> pItemList; // list with MenuItems
MenuLogo* pLogo;
VclPtr<Menu> pStartedFrom;
VclPtr<vcl::Window> pWindow;
@@ -359,7 +359,7 @@ public:
// Fuer Menu-'Funktionen'
MenuItemList* GetItemList() const
{
- return pItemList;
+ return pItemList.get();
}
// returns the system's menu handle if native menus are supported
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index b327f3d10e7e..012131f33962 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -175,9 +175,11 @@ void Menu::dispose()
bKilled = true;
- delete pItemList;
+ pItemList->Clear();
delete pLogo;
+ pLogo = nullptr;
delete mpLayoutData;
+ mpLayoutData = nullptr;
// Native-support: destroy SalMenu
ImplSetSalMenu( nullptr );
diff --git a/vcl/source/window/menufloatingwindow.cxx b/vcl/source/window/menufloatingwindow.cxx
index 366aeed1ad1d..6bf2fde56e3e 100644
--- a/vcl/source/window/menufloatingwindow.cxx
+++ b/vcl/source/window/menufloatingwindow.cxx
@@ -152,6 +152,12 @@ long MenuFloatingWindow::ImplGetStartY() const
long nY = 0;
if( pMenu )
{
+ // avoid crash if somehow menu got disposed, and MenuItemList is empty (workaround for tdf#104686)
+ if ( nFirstEntry > 0 && !pMenu->GetItemList()->GetDataFromPos(nFirstEntry - 1) )
+ {
+ return 0;
+ }
+
for ( sal_uInt16 n = 0; n < nFirstEntry; n++ )
nY += pMenu->GetItemList()->GetDataFromPos( n )->aSz.Height();
nY -= pMenu->GetTitleHeight();
@@ -606,45 +612,55 @@ void MenuFloatingWindow::ImplScroll( bool bUp )
nFirstEntry = pMenu->ImplGetPrevVisible( nFirstEntry );
SAL_WARN_IF( nFirstEntry == ITEMPOS_INVALID, "vcl", "Scroll?!" );
- long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
-
- if ( !bScrollDown )
+ // avoid crash if somehow menu got disposed, and MenuItemList is empty (workaround for tdf#104686)
+ const auto pItemData = pMenu->GetItemList()->GetDataFromPos( nFirstEntry );
+ if ( pItemData )
{
- bScrollDown = true;
- Invalidate();
- }
+ long nScrollEntryHeight = pItemData->aSz.Height();
- if ( pMenu->ImplGetPrevVisible( nFirstEntry ) == ITEMPOS_INVALID )
- {
- bScrollUp = false;
- Invalidate();
- }
+ if ( !bScrollDown )
+ {
+ bScrollDown = true;
+ Invalidate();
+ }
+
+ if ( pMenu->ImplGetPrevVisible( nFirstEntry ) == ITEMPOS_INVALID )
+ {
+ bScrollUp = false;
+ Invalidate();
+ }
- Scroll( 0, nScrollEntryHeight, ImplCalcClipRegion( false ).GetBoundRect(), ScrollFlags::Clip );
+ Scroll( 0, nScrollEntryHeight, ImplCalcClipRegion( false ).GetBoundRect(), ScrollFlags::Clip );
+ }
}
else if ( bScrollDown && !bUp )
{
- long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
+ // avoid crash if somehow menu got disposed, and MenuItemList is empty (workaround for tdf#104686)
+ const auto pItemData = pMenu->GetItemList()->GetDataFromPos( nFirstEntry );
+ if ( pItemData )
+ {
+ long nScrollEntryHeight = pItemData->aSz.Height();
- nFirstEntry = pMenu->ImplGetNextVisible( nFirstEntry );
- SAL_WARN_IF( nFirstEntry == ITEMPOS_INVALID, "vcl", "Scroll?!" );
+ nFirstEntry = pMenu->ImplGetNextVisible( nFirstEntry );
+ SAL_WARN_IF( nFirstEntry == ITEMPOS_INVALID, "vcl", "Scroll?!" );
- if ( !bScrollUp )
- {
- bScrollUp = true;
- Invalidate();
- }
+ if ( !bScrollUp )
+ {
+ bScrollUp = true;
+ Invalidate();
+ }
- long nHeight = GetOutputSizePixel().Height();
- sal_uInt16 nLastVisible;
- static_cast<PopupMenu*>(pMenu.get())->ImplCalcVisEntries( nHeight, nFirstEntry, &nLastVisible );
- if ( pMenu->ImplGetNextVisible( nLastVisible ) == ITEMPOS_INVALID )
- {
- bScrollDown = false;
- Invalidate();
- }
+ long nHeight = GetOutputSizePixel().Height();
+ sal_uInt16 nLastVisible;
+ static_cast<PopupMenu*>(pMenu.get())->ImplCalcVisEntries( nHeight, nFirstEntry, &nLastVisible );
+ if ( pMenu->ImplGetNextVisible( nLastVisible ) == ITEMPOS_INVALID )
+ {
+ bScrollDown = false;
+ Invalidate();
+ }
- Scroll( 0, -nScrollEntryHeight, ImplCalcClipRegion( false ).GetBoundRect(), ScrollFlags::Clip );
+ Scroll( 0, -nScrollEntryHeight, ImplCalcClipRegion( false ).GetBoundRect(), ScrollFlags::Clip );
+ }
}
Invalidate();
diff --git a/vcl/source/window/menuitemlist.cxx b/vcl/source/window/menuitemlist.cxx
index 44757a4778ba..30bd874d9763 100644
--- a/vcl/source/window/menuitemlist.cxx
+++ b/vcl/source/window/menuitemlist.cxx
@@ -135,6 +135,13 @@ void MenuItemList::Remove( size_t nPos )
}
}
+void MenuItemList::Clear()
+{
+ for (MenuItemData* i : maItemList)
+ delete i;
+ maItemList.resize(0);
+}
+
MenuItemData* MenuItemList::GetData( sal_uInt16 nSVId, size_t& rPos ) const
{
for( size_t i = 0, n = maItemList.size(); i < n; ++i )
diff --git a/vcl/source/window/menuitemlist.hxx b/vcl/source/window/menuitemlist.hxx
index 89befc106e28..556a5a049597 100644
--- a/vcl/source/window/menuitemlist.hxx
+++ b/vcl/source/window/menuitemlist.hxx
@@ -116,6 +116,7 @@ public:
);
void InsertSeparator(const OString &rIdent, size_t nPos);
void Remove( size_t nPos );
+ void Clear();
MenuItemData* GetData( sal_uInt16 nSVId, size_t& rPos ) const;
MenuItemData* GetData( sal_uInt16 nSVId ) const