Kaydet (Commit) eb9321d5 authored tarafından Michael Stahl's avatar Michael Stahl Kaydeden (comit) Caolán McNamara

sc: fix crash in ScVbaEventListener::processWindowResizeEvent()

This was crashing in CppunitTest_sc_macros_test on Windows with
--enable-mergelibs (release build), because the first invocation of
processWindowResizeEvent() deleted the vcl::Window, and the
maControllers.count(pWindow) test creates a VclPtr for it, so ends up
with a double-free.

TODO: is processWindowResizeEvent() supposed to be idempotent?
It would be possible to detect that there is already an event posted by
checking m_PostedWindows in postWindowResizeEvent().

Change-Id: I7b72f2baf21bb8223e9fe4bd929d826217b920e5
(cherry picked from commit 520514cf)
Reviewed-on: https://gerrit.libreoffice.org/19022Reviewed-by: 's avatarCaolán McNamara <caolanm@redhat.com>
Tested-by: 's avatarCaolán McNamara <caolanm@redhat.com>
üst 2d213a44
...@@ -169,7 +169,7 @@ private: ...@@ -169,7 +169,7 @@ private:
uno::Reference< frame::XModel > mxModel; uno::Reference< frame::XModel > mxModel;
ScDocShell* mpDocShell; ScDocShell* mpDocShell;
WindowControllerMap maControllers; /// Maps VCL top windows to their controllers. WindowControllerMap maControllers; /// Maps VCL top windows to their controllers.
std::set< VclPtr<vcl::Window> > maPostedWindows; /// Keeps processWindowResizeEvent windows from being deleted between postWindowResizeEvent and processWindowResizeEvent std::multiset< VclPtr<vcl::Window> > m_PostedWindows; /// Keeps processWindowResizeEvent windows from being deleted between postWindowResizeEvent and processWindowResizeEvent
VclPtr<vcl::Window> mpActiveWindow; /// Currently activated window, to prevent multiple (de)activation. VclPtr<vcl::Window> mpActiveWindow; /// Currently activated window, to prevent multiple (de)activation.
bool mbWindowResized; /// True = window resize system event processed. bool mbWindowResized; /// True = window resize system event processed.
bool mbBorderChanged; /// True = borders changed system event processed. bool mbBorderChanged; /// True = borders changed system event processed.
...@@ -471,7 +471,7 @@ void ScVbaEventListener::postWindowResizeEvent( vcl::Window* pWindow ) ...@@ -471,7 +471,7 @@ void ScVbaEventListener::postWindowResizeEvent( vcl::Window* pWindow )
{ {
mbWindowResized = mbBorderChanged = false; mbWindowResized = mbBorderChanged = false;
acquire(); // ensure we don't get deleted before the timer fires acquire(); // ensure we don't get deleted before the timer fires
maPostedWindows.insert(pWindow); m_PostedWindows.insert(pWindow);
Application::PostUserEvent( LINK( this, ScVbaEventListener, processWindowResizeEvent ), pWindow ); Application::PostUserEvent( LINK( this, ScVbaEventListener, processWindowResizeEvent ), pWindow );
} }
} }
...@@ -504,7 +504,14 @@ IMPL_LINK( ScVbaEventListener, processWindowResizeEvent, vcl::Window*, pWindow ) ...@@ -504,7 +504,14 @@ IMPL_LINK( ScVbaEventListener, processWindowResizeEvent, vcl::Window*, pWindow )
} }
} }
} }
maPostedWindows.erase(pWindow); {
// note: there may be multiple processWindowResizeEvent outstanding
// for pWindow, so it may have been added to m_PostedWindows multiple
// times - so this must delete exactly one of these elements!
auto const iter(m_PostedWindows.find(pWindow));
assert(iter != m_PostedWindows.end());
m_PostedWindows.erase(iter);
}
release(); release();
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment