summaryrefslogtreecommitdiff
path: root/sfx2
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-11-09 16:13:52 +0100
committerMiklos Vajna <vmiklos@collabora.com>2022-11-09 17:25:43 +0100
commita828e6adbb334282b8405a42f20826f5924c58a2 (patch)
tree16f9bd731c5abd2a68667fe3dbdb782d4062f861 /sfx2
parent56db6406b0b63a2d2d99024e7c311ebd874f3893 (diff)
sfx2: fix user-after-free in SfxObjectShell::ExecFile_Impl()
This happened even with an empty Writer document, on File -> Export As -> Export Directly as PDF, since commit 1e007e8f1703851b01c68884e87c906f6bae5a5e (sw: fix merge mail to direct export as pdf, 2022-10-18). The problem is that SfxObjectShell::ExecFile_Impl() gets a SfxBoolItem* returned by GetSlotState(), and then uses it before and after calling SfxStoringHelper::GUIStoreModel(). But as part of opening the file picker for save, ModelData_Impl::OutputFileDialog() indirectly calls Dialog::Execute(), which starts to process user events on the main loop, which leads to SfxItemDisruptor_Impl::Delete(), which deletes that SfxBoolItem*. Fix the problem by storing the bool value on the stack in SfxObjectShell::ExecFile_Impl(), and work with that after our SfxBoolItem* is gone. The "freed by" backtrace from asan is cut quite early in the gtk3 case. The "gen" case is more helpful, though it's still cut at frame 29. Change-Id: Ib97c7df7c1289730dec478eede3d620f3a33ace8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142492 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'sfx2')
-rw-r--r--sfx2/source/doc/objserv.cxx7
1 files changed, 5 insertions, 2 deletions
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index 91493e2eb616..ed8c0bf81a5a 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -969,7 +969,10 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
const SfxBoolItem *pItem = nId != SID_DIRECTEXPORTDOCASPDF ? nullptr :
dynamic_cast<const SfxBoolItem*>( GetSlotState(SID_MAIL_PREPAREEXPORT) );
- if (pItem && pItem->GetValue())
+ // Fetch value from the pool item early, because GUIStoreModel() can free the pool
+ // item as part of spinning the main loop if a dialog is opened.
+ bool bMailPrepareExport = pItem && pItem->GetValue();
+ if (bMailPrepareExport)
{
SfxRequest aRequest(SID_MAIL_PREPAREEXPORT, SfxCallMode::SYNCHRON, GetPool());
aRequest.AppendItem(SfxBoolItem(FN_PARAM_1, true));
@@ -982,7 +985,7 @@ void SfxObjectShell::ExecFile_Impl(SfxRequest &rReq)
bPreselectPassword,
GetDocumentSignatureState() );
- if (pItem && pItem->GetValue())
+ if (bMailPrepareExport)
{
SfxRequest aRequest(SID_MAIL_EXPORT_FINISHED, SfxCallMode::SYNCHRON, GetPool());
ExecuteSlot(aRequest);