sfx2/source/doc/objserv.cxx |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

New commits:
commit a828e6adbb334282b8405a42f20826f5924c58a2
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Nov 9 16:13:52 2022 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Nov 9 17:25:43 2022 +0100

    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 <vmik...@collabora.com>

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);

Reply via email to