avmedia/source/gstreamer/gstframegrabber.cxx                |   14 -
 cui/source/dialogs/SpellDialog.cxx                          |    2 
 dbaccess/source/core/dataaccess/ModelImpl.cxx               |    3 
 editeng/source/accessibility/AccessibleEditableTextPara.cxx |    3 
 external/python3/ExternalPackage_python3.mk                 |    2 
 framework/qa/cppunit/dispatchtest.cxx                       |    3 
 include/sfx2/docmacromode.hxx                               |    4 
 include/sfx2/objsh.hxx                                      |    6 
 include/sfx2/strings.hrc                                    |    1 
 include/tools/urlobj.hxx                                    |    5 
 sc/source/core/data/global.cxx                              |    7 
 sc/source/ui/drawfunc/drtxtob.cxx                           |    3 
 sc/source/ui/view/editsh.cxx                                |    3 
 sc/source/ui/view/formatsh.cxx                              |    2 
 sc/source/ui/view/viewdata.cxx                              |   34 ++
 sd/qa/unit/tiledrendering/tiledrendering.cxx                |    8 
 sd/source/ui/app/sdmod1.cxx                                 |   29 +-
 sd/source/ui/remotecontrol/Receiver.cxx                     |   21 +
 sfx2/source/doc/docmacromode.cxx                            |    8 
 sfx2/source/doc/iframe.cxx                                  |    5 
 sfx2/source/doc/objmisc.cxx                                 |   35 ++
 sfx2/source/doc/objxtor.cxx                                 |    1 
 sfx2/source/inc/objshimp.hxx                                |    3 
 sw/inc/IDocumentMarkAccess.hxx                              |    3 
 sw/qa/extras/uiwriter/uiwriter.cxx                          |  144 ++++++++++++
 sw/source/core/doc/DocumentContentOperationsManager.cxx     |    3 
 sw/source/core/doc/docbm.cxx                                |   10 
 sw/source/core/frmedt/feshview.cxx                          |    7 
 sw/source/core/inc/MarkManager.hxx                          |    2 
 sw/source/core/inc/mvsave.hxx                               |    3 
 sw/source/core/text/pormulti.cxx                            |   13 -
 sw/source/core/undo/rolbck.cxx                              |   39 +--
 sw/source/core/undo/undel.cxx                               |   26 ++
 sw/source/core/undo/undobj.cxx                              |   16 +
 sw/source/filter/html/htmlplug.cxx                          |    2 
 sw/source/filter/html/htmltab.cxx                           |    2 
 sw/source/filter/xml/xmltexti.cxx                           |    2 
 sw/source/uibase/shells/drwtxtex.cxx                        |    8 
 sw/source/uibase/uiview/viewport.cxx                        |    5 
 sw/source/uibase/wrtsh/wrtsh2.cxx                           |   38 ++-
 tools/source/fsys/urlobj.cxx                                |    9 
 vcl/source/window/window2.cxx                               |    6 
 xmloff/source/draw/ximpshap.cxx                             |    2 
 43 files changed, 434 insertions(+), 108 deletions(-)

New commits:
commit a0a1d909043e0b508804eaa3dbe608925f1c702a
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Nov 23 20:45:09 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:23 2023 +0100

    tdf#148389 sw: fix Delete Undo/Redo of bookmark positions
    
    The main problem is that in SwUndoSaveContent::DelContentIndex() if the
    selection start/end is equal to the bookmark start/end, the bookmark is
    not deleted and no SwHistoryBookmark is created, hence on Undo the
    bookmark positions are not restored.
    
    Since deleting bookmarks in more situations might cause user complaints,
    let's just extend the creation of SwHistoryBookmark to these cases,
    which means we need to take care both here and in
    SwHistoryBookmark::SetInDoc() that there is now a situation where all
    bookmark positions are saved and restored but the bookmark still exists
    in the document because it wasn't deleted.
    
    The next problem is that using Backspace/Delete keys sets the
    ArtificialSelection flag which is stored in SwUndoDelete, but when used
    multiple times the SwUndoDelete::CanGrouping() extends an existing
    SwUndoDelete, and if it previously would not delete a bookmark, the
    extended range might fully contain the bookmark and thus delete it on
    Redo, so check if there are saved bookmark positions and prevent
    grouping in that case.
    
    Another problem is then that SwUndoDelete::RedoImpl() deletes the
    bookmark anyway, as already indicated with a FIXME comment.
    
    This can be prevented by passing the now-existing m_DeleteFlags into
    DelBookmarks() from DeleteRangeImplImpl().
    
    Change-Id: Id5eb1a58927aaa6e7e8b75be82d7f854d8057cfc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159875
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 57974af130e7421da6b07589d4a63a754b757ad6)

diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index c88e51077005..b8d7262120b9 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -229,7 +229,8 @@ class IDocumentMarkAccess
             const SwNodeIndex& rEnd,
             std::vector< ::sw::mark::SaveBookmark>* pSaveBkmk, // Ugly: 
SaveBookmark is core-internal
             const SwIndex* pSttIdx,
-            const SwIndex* pEndIdx) =0;
+            const SwIndex* pEndIdx,
+            bool isReplace) = 0;
 
         /** Deletes a mark.
 
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx 
b/sw/qa/extras/uiwriter/uiwriter.cxx
index 6a08e69a3d06..cdb6a3634552 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -1865,6 +1865,150 @@ void SwUiWriterTest::testBookmarkUndo()
     CPPUNIT_ASSERT_EQUAL(sal_Int32(0), pMarkAccess->getAllMarksCount());
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf148389_Left)
+{
+    SwDoc* const pDoc = createDoc();
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+    pWrtShell->Insert("foo bar baz");
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 4, 
/*bBasicCall=*/false);
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 3, 
/*bBasicCall=*/false);
+    IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+    auto pMark = pMarkAccess->makeMark(*pWrtShell->GetCursor(), "Mark",
+        IDocumentMarkAccess::MarkType::BOOKMARK, ::sw::mark::InsertMode::New);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 4, 
/*bBasicCall=*/false);
+    pWrtShell->DelLeft();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(7), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->DelLeft();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(6), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->DelLeft();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->DelLeft();
+    // historically it wasn't deleted if empty, not sure if it should be
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    // Undo re-creates the mark...
+    pMark = *pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetMarkPos().nContent.GetIndex());
+    // the problem was that the end position was not restored
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Undo();
+    // this undo is no longer grouped, to prevent Redo deleting bookmark
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    // Undo re-creates the mark...
+    pMark = *pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(7), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Redo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Redo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    // Undo re-creates the mark...
+    pMark = *pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    // Undo re-creates the mark...
+    pMark = *pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(7), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+}
+
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf148389_Right)
+{
+    SwDoc* const pDoc = createDoc();
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+    pWrtShell->Insert("foo bar baz");
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 4, 
/*bBasicCall=*/false);
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/true, 3, 
/*bBasicCall=*/false);
+    IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+    auto pMark = pMarkAccess->makeMark(*pWrtShell->GetCursor(), "Mark",
+        IDocumentMarkAccess::MarkType::BOOKMARK, ::sw::mark::InsertMode::New);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 2, 
/*bBasicCall=*/false);
+    pWrtShell->DelRight();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(6), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->DelRight();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->DelRight();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->DelRight();
+    // historically it wasn't deleted if empty, not sure if it should be
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    // Undo re-creates the mark...
+    pMark = *pMarkAccess->getAllMarksBegin();
+    // the problem was that the start position was not restored
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Undo();
+    // this undo is no longer grouped, to prevent Redo deleting bookmark
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    // Undo re-creates the mark...
+    pMark = *pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(6), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Undo();
+    // this undo is no longer grouped, to prevent Redo deleting bookmark
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    // Undo re-creates the mark...
+    pMark = *pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(7), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Redo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(6), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Redo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Redo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    // Undo re-creates the mark...
+    pMark = *pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    // Undo re-creates the mark...
+    pMark = *pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(6), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
+    // Undo re-creates the mark...
+    pMark = *pMarkAccess->getAllMarksBegin();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), 
pMark->GetMarkPos().nContent.GetIndex());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(7), 
pMark->GetOtherMarkPos().nContent.GetIndex());
+}
+
 static void lcl_setWeight(SwWrtShell* pWrtShell, FontWeight aWeight)
 {
     SvxWeightItem aWeightItem(aWeight, EE_CHAR_WEIGHT);
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx 
b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index d90a40b60ea6..1722a52dc312 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -4196,7 +4196,8 @@ bool 
DocumentContentOperationsManager::DeleteRangeImplImpl(SwPaM & rPam, SwDelet
         pEnd->nNode,
         nullptr,
         &pStt->nContent,
-        &pEnd->nContent);
+        &pEnd->nContent,
+        bool(flags & SwDeleteFlags::ArtificialSelection));
 
     SwNodeIndex aSttIdx( pStt->nNode );
     SwContentNode * pCNd = aSttIdx.GetNode().GetContentNode();
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 347ed827694d..19d70d112e8b 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -1066,7 +1066,8 @@ namespace sw { namespace mark
             const SwNodeIndex& rEnd,
             std::vector<SaveBookmark>* pSaveBkmk,
             const SwIndex* pSttIdx,
-            const SwIndex* pEndIdx )
+            const SwIndex* pEndIdx,
+            bool const isReplace)
     {
         std::vector<const_iterator_t> vMarksToDelete;
         bool bIsSortingNeeded = false;
@@ -1089,7 +1090,7 @@ namespace sw { namespace mark
 
             bool bIsPosInRange(false);
             bool bIsOtherPosInRange(false);
-            bool const bDeleteMark = isDeleteMark(pMark, false, rStt, rEnd, 
pSttIdx, pEndIdx, bIsPosInRange, bIsOtherPosInRange);
+            bool const bDeleteMark = isDeleteMark(pMark, isReplace, rStt, 
rEnd, pSttIdx, pEndIdx, bIsPosInRange, bIsOtherPosInRange);
 
             if ( bIsPosInRange
                  && ( bIsOtherPosInRange
@@ -1806,7 +1807,8 @@ void DelBookmarks(
     const SwNodeIndex& rEnd,
     std::vector<SaveBookmark> * pSaveBkmk,
     const SwIndex* pSttIdx,
-    const SwIndex* pEndIdx)
+    const SwIndex* pEndIdx,
+    bool const isReplace)
 {
     // illegal range ??
     if(rStt.GetIndex() > rEnd.GetIndex()
@@ -1814,7 +1816,7 @@ void DelBookmarks(
         return;
     SwDoc* const pDoc = rStt.GetNode().GetDoc();
 
-    pDoc->getIDocumentMarkAccess()->deleteMarks(rStt, rEnd, pSaveBkmk, 
pSttIdx, pEndIdx);
+    pDoc->getIDocumentMarkAccess()->deleteMarks(rStt, rEnd, pSaveBkmk, 
pSttIdx, pEndIdx, isReplace);
 
     // Copy all Redlines which are in the move area into an array
     // which holds all position information as offset.
diff --git a/sw/source/core/inc/MarkManager.hxx 
b/sw/source/core/inc/MarkManager.hxx
index 1efb30f3e121..840d492c2b35 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -63,7 +63,7 @@ namespace sw {
             virtual void correctMarksAbsolute(const SwNodeIndex& rOldNode, 
const SwPosition& rNewPos, const sal_Int32 nOffset) override;
             virtual void correctMarksRelative(const SwNodeIndex& rOldNode, 
const SwPosition& rNewPos, const sal_Int32 nOffset) override;
 
-            virtual void deleteMarks(const SwNodeIndex& rStt, const 
SwNodeIndex& rEnd, std::vector< ::sw::mark::SaveBookmark>* pSaveBkmk, const 
SwIndex* pSttIdx, const SwIndex* pEndIdx) override;
+            virtual void deleteMarks(const SwNodeIndex& rStt, const 
SwNodeIndex& rEnd, std::vector< ::sw::mark::SaveBookmark>* pSaveBkmk, const 
SwIndex* pSttIdx, const SwIndex* pEndIdx, bool isReplace) override;
 
             // deleters
             virtual std::unique_ptr<ILazyDeleter>
diff --git a/sw/source/core/inc/mvsave.hxx b/sw/source/core/inc/mvsave.hxx
index 5b84b5e10819..14b9ee6f6be5 100644
--- a/sw/source/core/inc/mvsave.hxx
+++ b/sw/source/core/inc/mvsave.hxx
@@ -95,7 +95,8 @@ void DelBookmarks(const SwNodeIndex& rStt,
     const SwNodeIndex& rEnd,
     std::vector< ::sw::mark::SaveBookmark> * SaveBkmk =nullptr,
     const SwIndex* pSttIdx =nullptr,
-    const SwIndex* pEndIdx =nullptr);
+    const SwIndex* pEndIdx = nullptr,
+    bool isReplace = false);
 
 /** data structure to temporarily hold fly anchor positions relative to some
  *  location. */
diff --git a/sw/source/core/undo/rolbck.cxx b/sw/source/core/undo/rolbck.cxx
index 50ff24aa4d98..ce36b4a1c37c 100644
--- a/sw/source/core/undo/rolbck.cxx
+++ b/sw/source/core/undo/rolbck.cxx
@@ -599,44 +599,37 @@ void SwHistoryBookmark::SetInDoc( SwDoc* pDoc, bool )
     std::unique_ptr<SwPaM> pPam;
     ::sw::mark::IMark* pMark = nullptr;
 
+    // now the situation is that m_bSavePos and m_bSaveOtherPos don't determine
+    // whether the mark was deleted
+    if (auto const iter = pMarkAccess->findMark(m_aName); iter != 
pMarkAccess->getAllMarksEnd())
+    {
+        pMark = *iter;
+    }
     if(m_bSavePos)
     {
         SwContentNode* const pContentNd = rNds[m_nNode]->GetContentNode();
-        OSL_ENSURE(pContentNd,
-            "<SwHistoryBookmark::SetInDoc(..)>"
-            " - wrong node for a mark");
-
-        // #111660# don't crash when nNode1 doesn't point to content node.
-        if(pContentNd)
-            pPam.reset(new SwPaM(*pContentNd, m_nContent));
+        assert(pContentNd);
+        pPam.reset(new SwPaM(*pContentNd, m_nContent));
     }
     else
     {
-        pMark = *pMarkAccess->findMark(m_aName);
+        assert(pMark);
         pPam.reset(new SwPaM(pMark->GetMarkPos()));
     }
+    assert(pPam);
 
     if(m_bSaveOtherPos)
     {
         SwContentNode* const pContentNd = rNds[m_nOtherNode]->GetContentNode();
-        OSL_ENSURE(pContentNd,
-            "<SwHistoryBookmark::SetInDoc(..)>"
-            " - wrong node for a mark");
-
-        if (pPam != nullptr && pContentNd)
-        {
-            pPam->SetMark();
-            pPam->GetMark()->nNode = m_nOtherNode;
-            pPam->GetMark()->nContent.Assign(pContentNd, m_nOtherContent);
-        }
+        assert(pContentNd);
+        pPam->SetMark();
+        pPam->GetMark()->nNode = m_nOtherNode;
+        pPam->GetMark()->nContent.Assign(pContentNd, m_nOtherContent);
     }
     else if(m_bHadOtherPos)
     {
-        if(!pMark)
-            pMark = *pMarkAccess->findMark(m_aName);
-        OSL_ENSURE(pMark->IsExpanded(),
-            "<SwHistoryBookmark::SetInDoc(..)>"
-            " - missing pos on old mark");
+        assert(pMark);
+        assert(pMark->IsExpanded());
         pPam->SetMark();
         *pPam->GetMark() = pMark->GetOtherMarkPos();
     }
diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
index bee925546d75..dc24ce96e2fd 100644
--- a/sw/source/core/undo/undel.cxx
+++ b/sw/source/core/undo/undel.cxx
@@ -547,6 +547,7 @@ bool SwUndoDelete::CanGrouping( SwDoc* pDoc, const SwPaM& 
rDelPam )
         if( m_bGroup && !m_bBackSp ) return false;
         m_bBackSp = true;
     }
+    // note: compare m_nSttContent here because the text isn't there any more!
     else if( pStt->nContent == m_nSttContent )
     {
         if( m_bGroup && m_bBackSp ) return false;
@@ -575,6 +576,30 @@ bool SwUndoDelete::CanGrouping( SwDoc* pDoc, const SwPaM& 
rDelPam )
         return false;
     }
 
+    if ((m_DeleteFlags & SwDeleteFlags::ArtificialSelection) && m_pHistory)
+    {
+        IDocumentMarkAccess const& rIDMA(*pDoc->getIDocumentMarkAccess());
+        for (auto i = m_pHistory->Count(); 0 < i; )
+        {
+            --i;
+            SwHistoryHint const*const pHistory((*m_pHistory)[i]);
+            if (pHistory->Which() == HSTRY_BOOKMARK)
+            {
+                SwHistoryBookmark const*const pHistoryBM(
+                        static_cast<SwHistoryBookmark const*>(pHistory));
+                auto const ppMark(rIDMA.findMark(pHistoryBM->GetName()));
+                if (ppMark != rIDMA.getAllMarksEnd()
+                    && (m_bBackSp
+                            ? ((**ppMark).GetMarkPos() == *pStt)
+                            : ((**ppMark).IsExpanded()
+                                && (**ppMark).GetOtherMarkPos() == *pEnd)))
+                {   // prevent grouping that would delete this mark on Redo()
+                    return false;
+                }
+            }
+        }
+    }
+
     {
         SwRedlineSaveDatas aTmpSav;
         const bool bSaved = FillSaveData( rDelPam, aTmpSav, false );
@@ -1304,7 +1329,6 @@ void SwUndoDelete::RedoImpl(::sw::UndoRedoContext & 
rContext)
         rDoc.getIDocumentContentOperations().DelFullPara( rPam );
     }
     else
-        // FIXME: this ends up calling DeleteBookmarks() on the entire rPam 
which deletes too many!
         rDoc.getIDocumentContentOperations().DeleteAndJoin(rPam, 
m_DeleteFlags);
 }
 
diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
index b1ed15e3124d..8ff858013b72 100644
--- a/sw/source/core/undo/undobj.cxx
+++ b/sw/source/core/undo/undobj.cxx
@@ -1061,6 +1061,7 @@ void SwUndoSaveContent::DelContentIndex( const 
SwPosition& rMark,
                 // #i81002#
                 bool bSavePos = false;
                 bool bSaveOtherPos = false;
+                bool bDelete = false;
                 const ::sw::mark::IMark *const pBkmk = 
pMarkAccess->getAllMarksBegin()[n];
                 auto const type(IDocumentMarkAccess::GetType(*pBkmk));
 
@@ -1077,6 +1078,7 @@ void SwUndoSaveContent::DelContentIndex( const 
SwPosition& rMark,
                     {
                         bSaveOtherPos = true;
                     }
+                    bDelete = bSavePos && bSaveOtherPos;
                 }
                 else
                 {
@@ -1117,8 +1119,16 @@ void SwUndoSaveContent::DelContentIndex( const 
SwPosition& rMark,
                         {
                             if( bMaybe )
                                 bSavePos = true;
-                            bSaveOtherPos = true;
+                            bDelete = true;
                         }
+                        if (bDelete || pBkmk->GetOtherMarkPos() == *pEnd)
+                        {
+                            bSaveOtherPos = true; // tdf#148389 always undo if 
at end
+                        }
+                    }
+                    if (!bSavePos && bMaybe && pBkmk->IsExpanded() && *pStt == 
pBkmk->GetMarkPos())
+                    {
+                        bSavePos = true; // tdf#148389 always undo if at start
                     }
 
                     if ( !bSavePos && !bSaveOtherPos
@@ -1157,6 +1167,7 @@ void SwUndoSaveContent::DelContentIndex( const 
SwPosition& rMark,
                         {
                             bSavePos = true;
                             bSaveOtherPos = pBkmk->IsExpanded(); //tdf#90138, 
only save the other pos if there is one
+                            bDelete = true;
                         }
                     }
                 }
@@ -1170,8 +1181,7 @@ void SwUndoSaveContent::DelContentIndex( const 
SwPosition& rMark,
                         m_pHistory->Add( *pBkmk, bSavePos, bSaveOtherPos );
                     }
                     if ( bSavePos
-                         && ( bSaveOtherPos
-                              || !pBkmk->IsExpanded() ) )
+                         && (bDelete || !pBkmk->IsExpanded()))
                     {
                         
pMarkAccess->deleteMark(pMarkAccess->getAllMarksBegin()+n, false);
                         n--;
diff --git a/sw/source/filter/html/htmltab.cxx 
b/sw/source/filter/html/htmltab.cxx
index 670ed3ae7aeb..8a7c2c8bbd72 100644
--- a/sw/source/filter/html/htmltab.cxx
+++ b/sw/source/filter/html/htmltab.cxx
@@ -4925,7 +4925,7 @@ void SwHTMLParser::ClearFootnotesMarksInRange(const 
SwNodeIndex& rMkNdIdx, const
 
     //ofz#9733 drop bookmarks in this range
     IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
-    pMarkAccess->deleteMarks(rMkNdIdx, SwNodeIndex(rPtNdIdx, 1), nullptr, 
nullptr, nullptr);
+    pMarkAccess->deleteMarks(rMkNdIdx, SwNodeIndex(rPtNdIdx, 1), nullptr, 
nullptr, nullptr, false);
 
     SwFrameFormats& rTable = *pDoc->GetSpzFrameFormats();
     for ( auto i = rTable.size(); i; )
commit 4938e035ff121ec850d5f8c4bae5ab634653ca12
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Wed Nov 22 21:14:41 2023 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:23 2023 +0100

    reuse AllowedLinkProtocolFromDocument in impress/draw
    
    Change-Id: I73ca4f087946a45dbf92d69a0dc1e769de9b5690
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159843
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit f0942eed2eb328b04856f20613f5226d66b66a20)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159759
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159884
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sd/source/ui/app/sdmod1.cxx b/sd/source/ui/app/sdmod1.cxx
index 3d84ddb0da56..8d42653545ea 100644
--- a/sd/source/ui/app/sdmod1.cxx
+++ b/sd/source/ui/app/sdmod1.cxx
@@ -32,6 +32,7 @@
 #include <sfx2/dispatch.hxx>
 #include <sfx2/request.hxx>
 #include <sfx2/templatedlg.hxx>
+#include <svl/stritem.hxx>
 #include <editeng/eeitem.hxx>
 
 #include <svx/svxids.hrc>
@@ -193,26 +194,32 @@ void SdModule::Execute(SfxRequest& rReq)
         {
             bool bIntercept = false;
             ::sd::DrawDocShell* pDocShell = dynamic_cast< ::sd::DrawDocShell 
*>( SfxObjectShell::Current() );
-            if (pDocShell)
+            ::sd::ViewShell* pViewShell = pDocShell ? 
pDocShell->GetViewShell() : nullptr;
+            if (pViewShell)
             {
-                ::sd::ViewShell* pViewShell = pDocShell->GetViewShell();
-                if (pViewShell)
+                if( sd::SlideShow::IsRunning( pViewShell->GetViewShellBase() ) 
)
                 {
-                    if( sd::SlideShow::IsRunning( 
pViewShell->GetViewShellBase() ) )
+                    // Prevent documents from opening while the slide
+                    // show is running, except when this request comes
+                    // from a shape interaction.
+                    if (rReq.GetArgs() == nullptr)
                     {
-                        // Prevent documents from opening while the slide
-                        // show is running, except when this request comes
-                        // from a shape interaction.
-                        if (rReq.GetArgs() == nullptr)
-                        {
-                            bIntercept = true;
-                        }
+                        bIntercept = true;
                     }
                 }
             }
 
             if (!bIntercept)
             {
+                if (const SfxStringItem* pURLItem = 
rReq.GetArg<SfxStringItem>(SID_FILE_NAME))
+                {
+                    if (!pViewShell || 
!SfxObjectShell::AllowedLinkProtocolFromDocument(pURLItem->GetValue(),
+                                                                               
         pViewShell->GetObjectShell(),
+                                                                               
         pViewShell->GetFrameWeld()))
+                    {
+                        return;
+                    }
+                }
                 SfxGetpApp()->ExecuteSlot(rReq, SfxGetpApp()->GetInterface());
             }
             else
commit 7bd23139442dcd3a9c4aaa4bcfd295c45f49579a
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Wed Nov 15 11:39:24 2023 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    reuse AllowedLinkProtocolFromDocument in writer
    
    reorg calc hyperlink check to reuse elsewhere
    
    Change-Id: I20ae3c5df15502c3a0a366fb4a2924c06ffac3d0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159487
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit e6a7537762e19fde446441edd10d301f9b37ce75)
    
    reuse AllowedLinkProtocolFromDocument in writer
    
    Change-Id: Iacf5e313fc6ca5f7d69ca6986a036f0e1ab1f2a0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159488
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 32535dfa82200b54296838b52285c054fbe5e51d)
    
    combine these hyperlink dispatchers into one call
    
    Change-Id: Icb7822e811013de648ccf2fbb23a5f0be9e29bb0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159489
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 0df175ccc6ea542bc5801f631ff72bed187042eb)
    
    we can have just one LoadURL for writer
    
    Change-Id: Ia0162ee1c275292fcf200bad4662e4c2c6b7b972
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159557
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 521ca9cf6acbae96cf95d9740859c9682212013d)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159858
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit e32b8601dbd63cf01497889601d6c9c1241106d6)

diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index b359e818a9e3..10442bfb5148 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -202,6 +202,9 @@ private:
 
     SAL_DLLPRIVATE bool SaveTo_Impl(SfxMedium &rMedium, const SfxItemSet* pSet 
);
 
+    // true if the document had macros (or similar) on load to trigger warning 
user
+    SAL_DLLPRIVATE bool  GetHadCheckedMacrosOnLoad() const;
+
 protected:
                                 SfxObjectShell(SfxObjectCreateMode);
                                 SfxObjectShell(SfxModelFlags);    // see 
sfxmodelfactory.hxx
@@ -418,8 +421,8 @@ public:
     void                        SetMacroCallsSeenWhileLoading();
     bool                        GetMacroCallsSeenWhileLoading() const;
 
-    // true if the document had macros (or similar) on load to trigger warning 
user
-    bool                        GetHadCheckedMacrosOnLoad() const;
+    // true if this type of link, from a document, is allowed by the user to 
be passed to uno:OpenDoc
+    static bool                 AllowedLinkProtocolFromDocument(const 
OUString& rUrl, SfxObjectShell* pObjShell, weld::Window* pDialogParent);
 
     const css::uno::Sequence< css::beans::PropertyValue >& 
GetModifyPasswordInfo() const;
     bool                        SetModifyPasswordInfo( const 
css::uno::Sequence< css::beans::PropertyValue >& aInfo );
diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx
index 9696f7d9414d..3295a38a0243 100644
--- a/sc/source/core/data/global.cxx
+++ b/sc/source/core/data/global.cxx
@@ -26,9 +26,7 @@
 #include <sfx2/docfile.hxx>
 #include <sfx2/dispatch.hxx>
 #include <sfx2/objsh.hxx>
-#include <sfx2/sfxresid.hxx>
 #include <sfx2/sfxsids.hrc>
-#include <sfx2/strings.hrc>
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/viewsh.hxx>
 #include <svl/intitem.hxx>
@@ -827,34 +825,8 @@ void ScGlobal::OpenURL(const OUString& rURL, const 
OUString& rTarget, bool bIgno
             aUrlName = aNewUrlName;
     }
 
-    if (INetURLObject(aUrlName).IsExoticProtocol())
-    {
-        // Default to ignoring exotic protocols
-        bool bAllow = false;
-        if (pObjShell)
-        {
-            // If the document had macros when loaded then follow the allowed 
macro-mode
-            if (pObjShell->GetHadCheckedMacrosOnLoad())
-                bAllow = pObjShell->AdjustMacroMode();
-            else // otherwise ask the user, defaulting to cancel
-            {
-                assert(pFrame && "if we have pObjShell we have pFrame");
-                //Reuse URITools::onOpenURI warning string
-                std::unique_ptr<weld::MessageDialog> 
xQueryBox(Application::CreateMessageDialog(pFrame->GetWindow().GetFrameWeld(),
-                                                               
VclMessageType::Warning, VclButtonsType::YesNo,
-                                                               
SfxResId(STR_DANGEROUS_TO_OPEN)));
-                
xQueryBox->set_primary_text(xQueryBox->get_primary_text().replaceFirst("$(ARG1)",
-                    INetURLObject::decode(aUrlName, 
INetURLObject::DecodeMechanism::Unambiguous)));
-                xQueryBox->set_default_response(RET_NO);
-                bAllow = xQueryBox->run() == RET_YES;
-            }
-        }
-        if (!bAllow)
-        {
-            SAL_WARN("sc", "ScGlobal::OpenURL ignoring: " << aUrlName);
-            return;
-        }
-    }
+    if (!SfxObjectShell::AllowedLinkProtocolFromDocument(aUrlName, pObjShell, 
pFrame ? pFrame->GetWindow().GetFrameWeld() : nullptr))
+        return;
 
     SfxStringItem aUrl( SID_FILE_NAME, aUrlName );
     SfxStringItem aTarget( SID_TARGETNAME, rTarget );
diff --git a/sfx2/source/doc/objmisc.cxx b/sfx2/source/doc/objmisc.cxx
index 8be1eae0ad08..9ff78bff6eea 100644
--- a/sfx2/source/doc/objmisc.cxx
+++ b/sfx2/source/doc/objmisc.cxx
@@ -982,6 +982,33 @@ bool SfxObjectShell::GetHadCheckedMacrosOnLoad() const
     return pImpl->m_bHadCheckedMacrosOnLoad;
 }
 
+bool SfxObjectShell::AllowedLinkProtocolFromDocument(const OUString& rUrl, 
SfxObjectShell* pObjShell, weld::Window* pDialogParent)
+{
+    if (!INetURLObject(rUrl).IsExoticProtocol())
+        return true;
+    // Default to ignoring exotic protocols
+    bool bAllow = false;
+    if (pObjShell)
+    {
+        // If the document had macros when loaded then follow the allowed 
macro-mode
+        if (pObjShell->GetHadCheckedMacrosOnLoad())
+            bAllow = pObjShell->AdjustMacroMode();
+        else // otherwise ask the user, defaulting to cancel
+        {
+            //Reuse URITools::onOpenURI warning string
+            std::unique_ptr<weld::MessageDialog> 
xQueryBox(Application::CreateMessageDialog(pDialogParent,
+                                                           
VclMessageType::Warning, VclButtonsType::YesNo,
+                                                           
SfxResId(STR_DANGEROUS_TO_OPEN)));
+            
xQueryBox->set_primary_text(xQueryBox->get_primary_text().replaceFirst("$(ARG1)",
+                INetURLObject::decode(rUrl, 
INetURLObject::DecodeMechanism::Unambiguous)));
+            xQueryBox->set_default_response(RET_NO);
+            bAllow = xQueryBox->run() == RET_YES;
+        }
+    }
+    SAL_WARN_IF(!bAllow, "sfx.appl", 
"SfxObjectShell::AllowedLinkProtocolFromDocument ignoring: " << rUrl);
+    return bAllow;
+}
+
 void SfxObjectShell::CheckEncryption_Impl( const uno::Reference< 
task::XInteractionHandler >& xHandler )
 {
     OUString aVersion;
diff --git a/sw/source/uibase/shells/drwtxtex.cxx 
b/sw/source/uibase/shells/drwtxtex.cxx
index 60bdf16380be..0e3ba07c3973 100644
--- a/sw/source/uibase/shells/drwtxtex.cxx
+++ b/sw/source/uibase/shells/drwtxtex.cxx
@@ -545,12 +545,8 @@ void SwDrawTextShell::Execute( SfxRequest &rReq )
             const SvxFieldData* pField = pOLV->GetFieldAtCursor();
             if (const SvxURLField* pURLField = dynamic_cast<const 
SvxURLField*>(pField))
             {
-                SfxStringItem aUrl(SID_FILE_NAME, pURLField->GetURL());
-                SfxStringItem aTarget(SID_TARGETNAME, 
pURLField->GetTargetFrame());
-                SfxBoolItem aNewView(SID_OPEN_NEW_VIEW, false);
-                SfxBoolItem aBrowsing(SID_BROWSE, true);
-                GetView().GetViewFrame()->GetDispatcher()->ExecuteList(
-                    SID_OPENDOC, SfxCallMode::SYNCHRON, { &aUrl, &aTarget, 
&aNewView, &aBrowsing });
+                ::LoadURL(GetShell(), pURLField->GetURL(), LoadUrlFlags::NONE,
+                          pURLField->GetTargetFrame());
             }
         }
         break;
diff --git a/sw/source/uibase/wrtsh/wrtsh2.cxx 
b/sw/source/uibase/wrtsh/wrtsh2.cxx
index 82d7c27cb0c6..543644d3b997 100644
--- a/sw/source/uibase/wrtsh/wrtsh2.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh2.cxx
@@ -488,30 +488,24 @@ bool SwWrtShell::ClickToINetGrf( const Point& rDocPt, 
LoadUrlFlags nFilter )
     return bRet;
 }
 
-void LoadURL( SwViewShell& rVSh, const OUString& rURL, LoadUrlFlags nFilter,
-              const OUString& rTargetFrameName )
+static void LoadURL(SwView& rView, const OUString& rURL, LoadUrlFlags nFilter,
+                    const OUString& rTargetFrameName)
 {
-    OSL_ENSURE( !rURL.isEmpty(), "what should be loaded here?" );
-    if( rURL.isEmpty() )
-        return ;
+    SwDocShell* pDShell = rView.GetDocShell();
+    OSL_ENSURE( pDShell, "No DocShell?!");
+    SfxViewFrame* pViewFrame = rView.GetViewFrame();
 
-    // The shell could be 0 also!!!!!
-    if ( dynamic_cast<const SwCursorShell*>( &rVSh) ==  nullptr )
+    if (!SfxObjectShell::AllowedLinkProtocolFromDocument(rURL, pDShell, 
pViewFrame->GetWindow().GetFrameWeld()))
         return;
 
     // We are doing tiledRendering, let the client handles the URL loading,
     // unless we are jumping to a TOC mark.
     if (comphelper::LibreOfficeKit::isActive() && !rURL.startsWith("#"))
     {
-        
rVSh.GetSfxViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED,
 rURL.toUtf8().getStr());
+        rView.libreOfficeKitViewCallback(LOK_CALLBACK_HYPERLINK_CLICKED, 
rURL.toUtf8().getStr());
         return;
     }
 
-    //A CursorShell is always a WrtShell
-    SwWrtShell &rSh = static_cast<SwWrtShell&>(rVSh);
-
-    SwDocShell* pDShell = rSh.GetView().GetDocShell();
-    OSL_ENSURE( pDShell, "No DocShell?!");
     OUString sTargetFrame(rTargetFrameName);
     if (sTargetFrame.isEmpty() && pDShell)
     {
@@ -526,7 +520,6 @@ void LoadURL( SwViewShell& rVSh, const OUString& rURL, 
LoadUrlFlags nFilter,
     OUString sReferer;
     if( pDShell && pDShell->GetMedium() )
         sReferer = pDShell->GetMedium()->GetName();
-    SfxViewFrame* pViewFrame = rSh.GetView().GetViewFrame();
     SfxFrameItem aView( SID_DOCFRAME, pViewFrame );
     SfxStringItem aName( SID_FILE_NAME, rURL );
     SfxStringItem aTargetFrameName( SID_TARGETNAME, sTargetFrame );
@@ -552,6 +545,23 @@ void LoadURL( SwViewShell& rVSh, const OUString& rURL, 
LoadUrlFlags nFilter,
             SfxCallMode::ASYNCHRON|SfxCallMode::RECORD );
 }
 
+void LoadURL( SwViewShell& rVSh, const OUString& rURL, LoadUrlFlags nFilter,
+              const OUString& rTargetFrameName )
+{
+    OSL_ENSURE( !rURL.isEmpty(), "what should be loaded here?" );
+    if( rURL.isEmpty() )
+        return ;
+
+    // The shell could be 0 also!!!!!
+    if ( dynamic_cast<const SwCursorShell*>( &rVSh) ==  nullptr )
+        return;
+
+    //A CursorShell is always a WrtShell
+    SwWrtShell &rSh = static_cast<SwWrtShell&>(rVSh);
+
+    ::LoadURL(rSh.GetView(), rURL, nFilter, rTargetFrameName);
+}
+
 void SwWrtShell::NavigatorPaste( const NaviContentBookmark& rBkmk,
                                     const sal_uInt16 nAction )
 {
commit 09833101c989ead8dc751a611a27489ed2f1bcf1
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Fri Nov 3 17:26:25 2023 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    default to ignoring libreoffice special-purpose protocols in calc hyperlink
    
    Change-Id: Ib9f62be3acc05f24ca234dec0fec21e24579e9de
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158911
    Tested-by: Jenkins
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit b6062623b4d69c79e90e9365ac7c5e7f11986793)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159045
    Reviewed-by: Eike Rathke <er...@redhat.com>
    (cherry picked from commit 672716d09c54cb6fdd59baa7da4b8393cf104cd2)

diff --git a/dbaccess/source/core/dataaccess/ModelImpl.cxx 
b/dbaccess/source/core/dataaccess/ModelImpl.cxx
index 9681254b8262..625422812960 100644
--- a/dbaccess/source/core/dataaccess/ModelImpl.cxx
+++ b/dbaccess/source/core/dataaccess/ModelImpl.cxx
@@ -1142,7 +1142,8 @@ bool ODatabaseModelImpl::checkMacrosOnLoading()
 {
     Reference< XInteractionHandler > xInteraction;
     xInteraction = m_aMediaDescriptor.getOrDefault( "InteractionHandler", 
xInteraction );
-    return m_aMacroMode.checkMacrosOnLoading( xInteraction );
+    const bool bHasMacros = m_aMacroMode.hasMacros();
+    return m_aMacroMode.checkMacrosOnLoading(xInteraction, false 
/*HasValidContentSignature*/, bHasMacros);
 }
 
 void ODatabaseModelImpl::resetMacroExecutionMode()
diff --git a/include/sfx2/docmacromode.hxx b/include/sfx2/docmacromode.hxx
index bd4f13fb016c..0cfca92db308 100644
--- a/include/sfx2/docmacromode.hxx
+++ b/include/sfx2/docmacromode.hxx
@@ -261,6 +261,8 @@ namespace sfx2
         */
         static bool storageHasMacros( const css::uno::Reference< 
css::embed::XStorage >& _rxStorage );
 
+        bool hasMacros() const;
+
         static bool containerHasBasicMacros( const css::uno::Reference< 
css::script::XLibraryContainer >& xContainter );
         /** checks the macro execution mode while loading the document.
 
@@ -288,7 +290,7 @@ namespace sfx2
         bool
                 checkMacrosOnLoading(
                     const css::uno::Reference< css::task::XInteractionHandler 
>& _rxInteraction,
-                    bool bHasValidContentSignature = false
+                    bool bHasValidContentSignature, bool bHasMacros
                 );
 
     private:
diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index 2be6c0a1e22c..b359e818a9e3 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -418,6 +418,9 @@ public:
     void                        SetMacroCallsSeenWhileLoading();
     bool                        GetMacroCallsSeenWhileLoading() const;
 
+    // true if the document had macros (or similar) on load to trigger warning 
user
+    bool                        GetHadCheckedMacrosOnLoad() const;
+
     const css::uno::Sequence< css::beans::PropertyValue >& 
GetModifyPasswordInfo() const;
     bool                        SetModifyPasswordInfo( const 
css::uno::Sequence< css::beans::PropertyValue >& aInfo );
 
diff --git a/include/sfx2/strings.hrc b/include/sfx2/strings.hrc
index 1db36e733c0c..29950ba68ca1 100644
--- a/include/sfx2/strings.hrc
+++ b/include/sfx2/strings.hrc
@@ -103,6 +103,7 @@
 #define STR_GB                                  NC_("STR_GB", "GB")
 #define STR_QUERY_LASTVERSION                   NC_("STR_QUERY_LASTVERSION", 
"Cancel all changes?")
 #define STR_NO_WEBBROWSER_FOUND                 NC_("STR_NO_WEBBROWSER_FOUND", 
"Opening \"$(ARG1)\" failed with error code $(ARG2) and message: 
\"$(ARG3)\"\nMaybe no web browser could be found on your system. In that case, 
please check your Desktop Preferences or install a web browser (for example, 
Firefox) in the default location requested during the browser installation.")
+#define STR_DANGEROUS_TO_OPEN                   NC_("STR_DANGEROUS_TO_OPEN", 
"It might be dangerous to open \"$(ARG1)\".\nDo you really want to open it?")
 #define STR_NO_ABS_URI_REF                      NC_("STR_NO_ABS_URI_REF", 
"\"$(ARG1)\" is not an absolute URL that can be passed to an external 
application to open it.")
 #define STR_GID_INTERN                          NC_("STR_GID_INTERN", 
"Internal")
 #define STR_GID_APPLICATION                     NC_("STR_GID_APPLICATION", 
"Application")
diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx
index 050fd823b4ee..9696f7d9414d 100644
--- a/sc/source/core/data/global.cxx
+++ b/sc/source/core/data/global.cxx
@@ -26,7 +26,9 @@
 #include <sfx2/docfile.hxx>
 #include <sfx2/dispatch.hxx>
 #include <sfx2/objsh.hxx>
+#include <sfx2/sfxresid.hxx>
 #include <sfx2/sfxsids.hrc>
+#include <sfx2/strings.hrc>
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/viewsh.hxx>
 #include <svl/intitem.hxx>
@@ -37,6 +39,8 @@
 #include <vcl/virdev.hxx>
 #include <vcl/settings.hxx>
 #include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <vcl/window.hxx>
 #include <unotools/charclass.hxx>
 #include <unotools/securityoptions.hxx>
 #include <osl/diagnose.h>
@@ -789,7 +793,7 @@ void ScGlobal::OpenURL(const OUString& rURL, const 
OUString& rTarget, bool bIgno
 
     OUString aUrlName( rURL );
     SfxViewFrame* pFrame = nullptr;
-    const SfxObjectShell* pObjShell = nullptr;
+    SfxObjectShell* pObjShell = nullptr;
     OUString aReferName;
     if ( pScActiveViewShell )
     {
@@ -823,6 +827,35 @@ void ScGlobal::OpenURL(const OUString& rURL, const 
OUString& rTarget, bool bIgno
             aUrlName = aNewUrlName;
     }
 
+    if (INetURLObject(aUrlName).IsExoticProtocol())
+    {
+        // Default to ignoring exotic protocols
+        bool bAllow = false;
+        if (pObjShell)
+        {
+            // If the document had macros when loaded then follow the allowed 
macro-mode
+            if (pObjShell->GetHadCheckedMacrosOnLoad())
+                bAllow = pObjShell->AdjustMacroMode();
+            else // otherwise ask the user, defaulting to cancel
+            {
+                assert(pFrame && "if we have pObjShell we have pFrame");
+                //Reuse URITools::onOpenURI warning string
+                std::unique_ptr<weld::MessageDialog> 
xQueryBox(Application::CreateMessageDialog(pFrame->GetWindow().GetFrameWeld(),
+                                                               
VclMessageType::Warning, VclButtonsType::YesNo,
+                                                               
SfxResId(STR_DANGEROUS_TO_OPEN)));
+                
xQueryBox->set_primary_text(xQueryBox->get_primary_text().replaceFirst("$(ARG1)",
+                    INetURLObject::decode(aUrlName, 
INetURLObject::DecodeMechanism::Unambiguous)));
+                xQueryBox->set_default_response(RET_NO);
+                bAllow = xQueryBox->run() == RET_YES;
+            }
+        }
+        if (!bAllow)
+        {
+            SAL_WARN("sc", "ScGlobal::OpenURL ignoring: " << aUrlName);
+            return;
+        }
+    }
+
     SfxStringItem aUrl( SID_FILE_NAME, aUrlName );
     SfxStringItem aTarget( SID_TARGETNAME, rTarget );
     if ( nScClickMouseModifier & KEY_SHIFT )     // control-click -> into new 
window
diff --git a/sfx2/source/doc/docmacromode.cxx b/sfx2/source/doc/docmacromode.cxx
index 2fa7b968fc41..8a617b1785c6 100644
--- a/sfx2/source/doc/docmacromode.cxx
+++ b/sfx2/source/doc/docmacromode.cxx
@@ -404,8 +404,12 @@ namespace sfx2
         return bHasMacros;
     }
 
+    bool DocumentMacroMode::hasMacros() const
+    {
+        return m_xData->m_rDocumentAccess.documentStorageHasMacros() || 
hasMacroLibrary() || m_xData->m_rDocumentAccess.macroCallsSeenWhileLoading();
+    }
 
-    bool DocumentMacroMode::checkMacrosOnLoading( const Reference< 
XInteractionHandler >& rxInteraction, bool bHasValidContentSignature )
+    bool DocumentMacroMode::checkMacrosOnLoading( const Reference< 
XInteractionHandler >& rxInteraction, bool bHasValidContentSignature, bool 
bHasMacros )
     {
         bool bAllow = false;
         if ( SvtSecurityOptions().IsMacroDisabled() )
@@ -415,7 +419,7 @@ namespace sfx2
         }
         else
         {
-            if (m_xData->m_rDocumentAccess.documentStorageHasMacros() || 
hasMacroLibrary() || m_xData->m_rDocumentAccess.macroCallsSeenWhileLoading())
+            if (bHasMacros)
             {
                 if (m_xData->m_rDocumentAccess.macroCallsSeenWhileLoading())
                     m_bNeedsContentSigned = true;
diff --git a/sfx2/source/doc/objmisc.cxx b/sfx2/source/doc/objmisc.cxx
index 2b6b361b1231..8be1eae0ad08 100644
--- a/sfx2/source/doc/objmisc.cxx
+++ b/sfx2/source/doc/objmisc.cxx
@@ -972,9 +972,15 @@ void SfxObjectShell::CheckSecurityOnLoading_Impl()
 
     // check macro security
     const bool bHasValidContentSignature = HasValidSignatures();
-    pImpl->aMacroMode.checkMacrosOnLoading( xInteraction, 
bHasValidContentSignature );
+    const bool bHasMacros = pImpl->aMacroMode.hasMacros();
+    pImpl->aMacroMode.checkMacrosOnLoading( xInteraction, 
bHasValidContentSignature, bHasMacros );
+    pImpl->m_bHadCheckedMacrosOnLoad = bHasMacros;
 }
 
+bool SfxObjectShell::GetHadCheckedMacrosOnLoad() const
+{
+    return pImpl->m_bHadCheckedMacrosOnLoad;
+}
 
 void SfxObjectShell::CheckEncryption_Impl( const uno::Reference< 
task::XInteractionHandler >& xHandler )
 {
diff --git a/sfx2/source/doc/objxtor.cxx b/sfx2/source/doc/objxtor.cxx
index 29171a3e4e9a..ecac02074ea2 100644
--- a/sfx2/source/doc/objxtor.cxx
+++ b/sfx2/source/doc/objxtor.cxx
@@ -237,6 +237,7 @@ SfxObjectShell_Impl::SfxObjectShell_Impl( SfxObjectShell& 
_rDocShell )
     ,m_bAllowShareControlFileClean( true )
     ,m_bConfigOptionsChecked( false )
     ,m_bMacroCallsSeenWhileLoading( false )
+    ,m_bHadCheckedMacrosOnLoad( false )
     ,lErr(ERRCODE_NONE)
     ,nEventId ( SfxEventHintId::NONE )
     ,nLoadedFlags ( SfxLoadedFlags::ALL )
diff --git a/sfx2/source/inc/objshimp.hxx b/sfx2/source/inc/objshimp.hxx
index 3d7b0b69c945..4afdd706d05e 100644
--- a/sfx2/source/inc/objshimp.hxx
+++ b/sfx2/source/inc/objshimp.hxx
@@ -91,7 +91,8 @@ struct SfxObjectShell_Impl : public 
::sfx2::IMacroDocumentAccess
                         m_bSharedXMLFlag:1, // whether the document should be 
edited in shared mode
                         m_bAllowShareControlFileClean:1, // whether the flag 
should be stored in xml file
                         m_bConfigOptionsChecked:1, // whether or not the user 
options are checked after the Options dialog is closed.
-                        m_bMacroCallsSeenWhileLoading:1; // whether or not the 
user options are checked after the Options dialog is closed.
+                        m_bMacroCallsSeenWhileLoading:1, // whether or not 
macro calls were seen when loading document.
+                        m_bHadCheckedMacrosOnLoad:1; // if document contained 
macros (or calls) when loaded
 
     IndexBitSet         aBitSet;
     ErrCode             lErr;
commit 16ac4b571c7b1c236a47e15ed162c594abdd89be
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Sat Nov 4 19:57:51 2023 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    warn about exotic protocols as well
    
    Change-Id: I50dcf4f36cd20d75f5ad3876353143268740a50f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151834
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 1305f70cff8a81a58a5a6d9c96c5bb032005389e)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159034
    Reviewed-by: Eike Rathke <er...@redhat.com>
    (cherry picked from commit 2e1bcbb550d54278b366ec619cc5280d44d6aba4)

diff --git a/sw/source/filter/html/htmlplug.cxx 
b/sw/source/filter/html/htmlplug.cxx
index eb707040adb2..112975f98511 100644
--- a/sw/source/filter/html/htmlplug.cxx
+++ b/sw/source/filter/html/htmlplug.cxx
@@ -1089,7 +1089,7 @@ void SwHTMLParser::InsertFloatingFrame()
 
                 OUString sHRef = aFrameDesc.GetURL().GetMainURL( 
INetURLObject::DecodeMechanism::NONE );
 
-                if (INetURLObject(sHRef).GetProtocol() == INetProtocol::Macro)
+                if (INetURLObject(sHRef).IsExoticProtocol())
                     NotifyMacroEventRead();
 
                 xSet->setPropertyValue("FrameURL", uno::makeAny( sHRef ) );
diff --git a/sw/source/filter/xml/xmltexti.cxx 
b/sw/source/filter/xml/xmltexti.cxx
index 169cbdc1534d..caf300f239c6 100644
--- a/sw/source/filter/xml/xmltexti.cxx
+++ b/sw/source/filter/xml/xmltexti.cxx
@@ -856,7 +856,7 @@ uno::Reference< XPropertySet > 
SwXMLTextImportHelper::createAndInsertFloatingFra
                 OUString sHRef = URIHelper::SmartRel2Abs(
                             INetURLObject( GetXMLImport().GetBaseURL() ), 
rHRef );
 
-                if (INetURLObject(sHRef).GetProtocol() == INetProtocol::Macro)
+                if (INetURLObject(sHRef).IsExoticProtocol())
                     GetXMLImport().NotifyMacroEventRead();
 
                 xSet->setPropertyValue("FrameURL",
diff --git a/tools/source/fsys/urlobj.cxx b/tools/source/fsys/urlobj.cxx
index ab6e885639db..1ef2b7e0b2af 100644
--- a/tools/source/fsys/urlobj.cxx
+++ b/tools/source/fsys/urlobj.cxx
@@ -4776,7 +4776,8 @@ bool INetURLObject::IsExoticProtocol() const
     return m_eScheme == INetProtocol::Slot ||
            m_eScheme == INetProtocol::Macro ||
            m_eScheme == INetProtocol::Uno ||
-           isSchemeEqualTo(u"vnd.sun.star.script");
+           isSchemeEqualTo(u"vnd.sun.star.script") ||
+           isSchemeEqualTo(u"service");
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx
index 44b5177501f1..30c303690d97 100644
--- a/xmloff/source/draw/ximpshap.cxx
+++ b/xmloff/source/draw/ximpshap.cxx
@@ -3269,7 +3269,7 @@ void SdXMLFloatingFrameShapeContext::StartElement( const 
css::uno::Reference< cs
 
             if( !maHref.isEmpty() )
             {
-                if (INetURLObject(maHref).GetProtocol() == INetProtocol::Macro)
+                if (INetURLObject(maHref).IsExoticProtocol())
                     GetImport().NotifyMacroEventRead();
 
                 xProps->setPropertyValue("FrameURL", Any(maHref) );
commit 63db48ec3ece943af59558464165b9f5c560e9c0
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Fri Nov 3 17:14:26 2023 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    add some protocols that don't make sense as floating frame targets
    
    Change-Id: Id900a5eef248731d1184c1df501a2cf7a2de7eb9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158910
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 11ebdfef16501c6d35c3e3d0d62507f706557c71)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158900
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit bab433911bdecb344f7ea94dbd00690241a08c54)

diff --git a/include/tools/urlobj.hxx b/include/tools/urlobj.hxx
index 522dcca35fcd..67f241376537 100644
--- a/include/tools/urlobj.hxx
+++ b/include/tools/urlobj.hxx
@@ -920,6 +920,11 @@ public:
 
     void changeScheme(INetProtocol eTargetScheme);
 
+    // INetProtocol::Macro, INetProtocol::Uno, INetProtocol::Slot,
+    // vnd.sun.star.script, etc. All the types of URLs which shouldn't
+    // be accepted from an outside controlled source
+    bool IsExoticProtocol() const;
+
 private:
     // General Structure:
 
diff --git a/sfx2/source/doc/iframe.cxx b/sfx2/source/doc/iframe.cxx
index bc60a86b3317..23c2defd92d8 100644
--- a/sfx2/source/doc/iframe.cxx
+++ b/sfx2/source/doc/iframe.cxx
@@ -169,8 +169,11 @@ sal_Bool SAL_CALL IFrameObject::load(
         xTrans->parseStrict( aTargetURL );
 
         INetURLObject aURLObject(aTargetURL.Complete);
-        if (aURLObject.GetProtocol() == INetProtocol::Macro || 
aURLObject.isSchemeEqualTo(u"vnd.sun.star.script"))
+        if (aURLObject.IsExoticProtocol())
+        {
+            SAL_WARN("sfx", "IFrameObject::load ignoring: " << 
aTargetURL.Complete);
             return false;
+        }
 
         uno::Reference<frame::XFramesSupplier> xParentFrame = 
xFrame->getCreator();
         SfxObjectShell* pDoc = SfxMacroLoader::GetObjectShell(xParentFrame);
diff --git a/tools/source/fsys/urlobj.cxx b/tools/source/fsys/urlobj.cxx
index 64daa11c9415..ab6e885639db 100644
--- a/tools/source/fsys/urlobj.cxx
+++ b/tools/source/fsys/urlobj.cxx
@@ -4771,4 +4771,12 @@ OUString INetURLObject::CutExtension()
         ? aTheExtension : OUString();
 }
 
+bool INetURLObject::IsExoticProtocol() const
+{
+    return m_eScheme == INetProtocol::Slot ||
+           m_eScheme == INetProtocol::Macro ||
+           m_eScheme == INetProtocol::Uno ||
+           isSchemeEqualTo(u"vnd.sun.star.script");
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 5fbfd860172e43d232bf106c4aa6ab05a0511447
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Fri Nov 3 14:20:07 2023 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    escape url passed to gstreamer
    
    Change-Id: I3c93ee34800cc8563370f75ef3ef6f8a9220e6ec
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158894
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit f41dcadf6492a6ffd32696d50f818e44355b9ad9)

diff --git a/avmedia/source/gstreamer/gstframegrabber.cxx 
b/avmedia/source/gstreamer/gstframegrabber.cxx
index bc183d563332..0135a78ed597 100644
--- a/avmedia/source/gstreamer/gstframegrabber.cxx
+++ b/avmedia/source/gstreamer/gstframegrabber.cxx
@@ -51,11 +51,9 @@ void FrameGrabber::disposePipeline()
 FrameGrabber::FrameGrabber( const OUString &rURL ) :
     FrameGrabber_BASE()
 {
-    gchar *pPipelineStr;
-    pPipelineStr = g_strdup_printf(
-        "uridecodebin uri=%s ! videoconvert ! videoscale ! appsink "
-        "name=sink caps=\"video/x-raw,format=RGB,pixel-aspect-ratio=1/1\"",
-        OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 ).getStr() );
+    const char pPipelineStr[] =
+        "uridecodebin name=source ! videoconvert ! videoscale ! appsink "
+        "name=sink caps=\"video/x-raw,format=RGB,pixel-aspect-ratio=1/1\"";
 
     GError *pError = nullptr;
     mpPipeline = gst_parse_launch( pPipelineStr, &pError );
@@ -66,6 +64,12 @@ FrameGrabber::FrameGrabber( const OUString &rURL ) :
     }
 
     if( mpPipeline ) {
+
+        if (GstElement *pUriDecode = gst_bin_get_by_name(GST_BIN(mpPipeline), 
"source"))
+            g_object_set(pUriDecode, "uri", OUStringToOString(rURL, 
RTL_TEXTENCODING_UTF8).getStr(), nullptr);
+        else
+            g_warning("Missing 'source' element in gstreamer pipeline");
+
         // pre-roll
         switch( gst_element_set_state( mpPipeline, GST_STATE_PAUSED ) ) {
         case GST_STATE_CHANGE_FAILURE:
commit 1a1921ce8733ce95dab9f6e56ccdaf147fb75cb4
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Nov 17 15:22:37 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    sd: remote: check that received commands have expected arguments
    
    Change-Id: If4b5fe0362a40d14d68829bffb79f91ae9745835
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159590
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 8d87164becccc230e1e0ad5ac51bf645744165a2)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159578
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    (cherry picked from commit 99b8559471c4429df70803cdb358da41888f8d03)

diff --git a/sd/source/ui/remotecontrol/Receiver.cxx 
b/sd/source/ui/remotecontrol/Receiver.cxx
index 3c0309e9e461..815c53ef4d35 100644
--- a/sd/source/ui/remotecontrol/Receiver.cxx
+++ b/sd/source/ui/remotecontrol/Receiver.cxx
@@ -78,6 +78,12 @@ void Receiver::executeCommand( const std::vector<OString> 
&aCommand )
     {
     }
 
+    if (aCommand.empty())
+    {
+        SAL_WARN("sdremote", "Receiver::executeCommand: no command");
+        return;
+    }
+
     if ( aCommand[0] ==  "transition_next" )
     {
         if ( xSlideShowController.is() )
@@ -90,6 +96,11 @@ void Receiver::executeCommand( const std::vector<OString> 
&aCommand )
     }
     else if ( aCommand[0] == "goto_slide" )
     {
+        if (aCommand.size() < 2)
+        {
+            SAL_WARN("sdremote", "Receiver::executeCommand: invalid 
goto_slide");
+            return;
+        }
         // FIXME: if 0 returned, then not a valid number
         sal_Int32 aSlide = aCommand[1].toInt32();
         if ( xSlideShowController.is() &&
@@ -122,6 +133,11 @@ void Receiver::executeCommand( const std::vector<OString> 
&aCommand )
     }
     else if (aCommand[0] == "pointer_started" )
     {
+        if (aCommand.size() < 3)
+        {
+            SAL_WARN("sdremote", "Receiver::executeCommand: invalid 
pointer_started");
+            return;
+        }
         // std::cerr << "pointer_started" << std::endl;
         float x = aCommand[1].toFloat();
         float y = aCommand[2].toFloat();
@@ -176,6 +192,11 @@ void Receiver::executeCommand( const std::vector<OString> 
&aCommand )
     }
     else if (aCommand[0] == "pointer_coordination" )
     {
+        if (aCommand.size() < 3)
+        {
+            SAL_WARN("sdremote", "Receiver::executeCommand: invalid 
pointer_coordination");
+            return;
+        }
         float x = aCommand[1].toFloat();
         float y = aCommand[2].toFloat();
 
commit 6d721bac67e5d43fb1aeaa73b8a9a554d98843e1
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Sun Nov 12 19:49:40 2023 +0000
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    ofz#64106 Null-dereference READ
    
    Change-Id: Ie279f9f54fa6cc7fcc6add9b737d2c5dc248a236
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159349
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 9fc42afd17e9115b488401f64804479e7a76a300)

diff --git a/sw/source/uibase/uiview/viewport.cxx 
b/sw/source/uibase/uiview/viewport.cxx
index 2fa7e12f5afe..fb40aa453798 100644
--- a/sw/source/uibase/uiview/viewport.cxx
+++ b/sw/source/uibase/uiview/viewport.cxx
@@ -323,8 +323,9 @@ void SwView::SetVisArea( const Point &rPt, bool 
bUpdateScrollbar )
 
 void SwView::CheckVisArea()
 {
-    m_pHScrollbar->SetAuto( m_pWrtShell->GetViewOptions()->getBrowseMode() &&
-                            !GetViewFrame()->GetFrame().IsInPlace() );
+    if (m_pHScrollbar)
+        m_pHScrollbar->SetAuto( m_pWrtShell->GetViewOptions()->getBrowseMode() 
&&
+                                !GetViewFrame()->GetFrame().IsInPlace() );
     if ( IsDocumentBorder() )
     {
         if ( m_aVisArea.Left() != DOCUMENTBORDER ||
commit c1ed305aa98a6295dad4e3e57328d118521d38a9
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Thu Oct 26 12:47:21 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    null-deref seen in ScTabView::UpdateEditView
    
     #0  0x00007f2bcc41df63 in ScViewData::GetCurYForTab 
(this=this@entry=0x3502d0b8, nTabIndex=nTabIndex@entry=6)
         at libreoffice/sc/source/ui/view/viewdata.cxx:1443
     #1  0x00007f2bcc3ebf02 in ScTabView::UpdateEditView 
(this=this@entry=0x3502d0b0) at libreoffice/sc/source/ui/view/tabview3.cxx:2185
     #2  0x00007f2bcc3ec636 in ScTabView::UpdateFormulas 
(this=this@entry=0x3502d0b0, nStartCol=nStartCol@entry=-1, 
nStartRow=nStartRow@entry=-1, nEndCol=nEndCol@entry=-1,
         nEndRow=nEndRow@entry=-1) at 
libreoffice/sc/source/ui/view/tabview3.cxx:2327
     #3  0x00007f2bcc40735c in ScTabViewShell::Notify (this=0x3502cf20, 
rBC=..., rHint=...) at libreoffice/sc/source/ui/view/tabvwsh5.cxx:216
     #4  0x00007f2bdc1885a9 in SfxBroadcaster::Broadcast 
(this=this@entry=0x31e31430, rHint=...)
         at libreoffice/svl/source/notify/SfxBroadcaster.cxx:40
     #5  0x00007f2bcc022e6d in ScDocShell::PostDataChanged 
(this=this@entry=0x31e31430) at libreoffice/sc/source/ui/docshell/docsh3.cxx:95
     #6  0x00007f2bcc0101aa in ScDocShell::SetDocumentModified 
(this=0x31e31430) at libreoffice/sc/source/ui/docshell/docsh.cxx:3015
     #7  0x00007f2bcc010df3 in ScDocShellModificator::SetDocumentModified 
(this=this@entry=0x7fff2d168da0)
         at libreoffice/sc/source/ui/docshell/docsh.cxx:3330
     #8  0x00007f2bcc040c1a in ScDocShell::MoveTable 
(this=this@entry=0x31e31430, nSrcTab=<optimized out>, nDestTab=<optimized out>, 
bCopy=bCopy@entry=false, bRecord=bRecord@entry=false)
         at libreoffice/sc/source/ui/docshell/docsh5.cxx:1010
     #9  0x00007f2bcc441a41 in ScViewFunc::MoveTable 
(this=this@entry=0x333d0fe0, nDestDocNo=nDestDocNo@entry=0, 
nDestTab=nDestTab@entry=7, bCopy=bCopy@entry=false,
         pNewTabName=pNewTabName@entry=0x7fff2d169068) at 
libreoffice/sc/source/ui/view/viewfun2.cxx:3117
     #10 0x00007f2bcc418459 in ScTabViewShell::ExecuteTable (this=0x333d0e50, 
rReq=...) at libreoffice/sc/source/ui/view/tabvwshf.cxx:593
     #11 0x00007f2bdbd3d96f in SfxDispatcher::Call_Impl 
(this=this@entry=0x33379ed0, rShell=..., rSlot=..., rReq=..., 
bRecord=<optimized out>)
         at libreoffice/sfx2/source/control/dispatch.cxx:254
     #12 0x00007f2bdbd427ee in SfxDispatcher::Execute_ 
(this=this@entry=0x33379ed0, rShell=..., rSlot=..., rReq=..., 
eCallMode=eCallMode@entry=SfxCallMode::RECORD)
         at libreoffice/sfx2/source/control/dispatch.cxx:753
     #13 0x00007f2bdbd45a33 in SfxDispatcher::Execute (this=0x33379ed0, 
nSlot=<optimized out>, nCall=nCall@entry=SfxCallMode::RECORD, 
pArgs=pArgs@entry=0x7fff2d1694a0,
         pInternalArgs=pInternalArgs@entry=0x7fff2d169460, nModi=nModi@entry=0) 
at libreoffice/sfx2/source/control/dispatch.cxx:813
     #14 0x00007f2bdbd83c0f in SfxDispatchController_Impl::dispatch 
(this=<optimized out>, aURL=..., aArgs=..., rListener=...)
    
    we have nulls in here for hidden sheets
    
    Change-Id: I8f1295e67552f3ec9306a031aaecd0838e18d98d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158502
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit ce8920448c05594f37f09c7a42ae3f3c7ccb7a1e)

diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx
index 0ea25ebce6de..9103af9811a8 100644
--- a/sc/source/ui/view/viewdata.cxx
+++ b/sc/source/ui/view/viewdata.cxx
@@ -1342,7 +1342,13 @@ SCCOL ScViewData::GetCurXForTab( SCTAB nTabIndex ) const
     if (!ValidTab(nTabIndex) || (nTabIndex >= 
static_cast<SCTAB>(maTabData.size())))
         return -1;
 
-    return maTabData[nTabIndex]->nCurX;
+    ScViewDataTable* pTabData = maTabData[nTabIndex].get();
+    if (!pTabData)
+    {
+        SAL_WARN("sc.viewdata", "ScViewData::GetCurXForTab : hidden sheet = " 
<< nTabIndex);
+        return -1;
+    }
+    return pTabData->nCurX;
 }
 
 SCROW ScViewData::GetCurYForTab( SCTAB nTabIndex ) const
@@ -1350,7 +1356,13 @@ SCROW ScViewData::GetCurYForTab( SCTAB nTabIndex ) const
     if (!ValidTab(nTabIndex) || (nTabIndex >= 
static_cast<SCTAB>(maTabData.size())))
             return -1;
 
-    return maTabData[nTabIndex]->nCurY;
+    ScViewDataTable* pTabData = maTabData[nTabIndex].get();
+    if (!pTabData)
+    {
+        SAL_WARN("sc.viewdata", "ScViewData::GetCurYForTab : hidden sheet = " 
<< nTabIndex);
+        return -1;
+    }
+    return pTabData->nCurY;
 }
 
 void ScViewData::SetCurXForTab( SCCOL nNewCurX, SCTAB nTabIndex )
@@ -1358,7 +1370,14 @@ void ScViewData::SetCurXForTab( SCCOL nNewCurX, SCTAB 
nTabIndex )
     if (!ValidTab(nTabIndex) || (nTabIndex >= 
static_cast<SCTAB>(maTabData.size())))
             return;
 
-    maTabData[nTabIndex]->nCurX = nNewCurX;
+    ScViewDataTable* pTabData = maTabData[nTabIndex].get();
+    if (!pTabData)
+    {
+        SAL_WARN("sc.viewdata", "ScViewData::SetCurXForTab : hidden sheet = " 
<< nTabIndex);
+        return;
+    }
+
+    pTabData->nCurX = nNewCurX;
 }
 
 void ScViewData::SetCurYForTab( SCCOL nNewCurY, SCTAB nTabIndex )
@@ -1366,7 +1385,14 @@ void ScViewData::SetCurYForTab( SCCOL nNewCurY, SCTAB 
nTabIndex )
     if (!ValidTab(nTabIndex) || (nTabIndex >= 
static_cast<SCTAB>(maTabData.size())))
             return;
 
-    maTabData[nTabIndex]->nCurY = nNewCurY;
+    ScViewDataTable* pTabData = maTabData[nTabIndex].get();
+    if (!pTabData)
+    {
+        SAL_WARN("sc.viewdata", "ScViewData::SetCurYForTab : hidden sheet = " 
<< nTabIndex);
+        return;
+    }
+
+    pTabData->nCurY = nNewCurY;
 }
 
 void ScViewData::SetMaxTiledCol( SCCOL nNewMaxCol )
commit 97ad996805c747783cc0ebfa9e3839f953d6230f
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Thu Oct 26 12:18:37 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    crash seen in Window::ImplTrackTimerHdl
    
     #0  vcl::Window::ImplTrackTimerHdl (this=0x3403b0a0, pTimer=<optimized 
out>) at libreoffice/vcl/source/window/window2.cxx:231
     #1  0x00007f2bdd31f5e7 in Scheduler::CallbackTaskScheduling () at 
libreoffice/vcl/source/app/scheduler.cxx:485
     #2  0x00007f2bdd4e5176 in SalTimer::CallCallback (this=<optimized out>) at 
libreoffice/vcl/inc/saltimer.hxx:54
     #3  SvpSalInstance::CheckTimeout (this=this@entry=0x261ef40, 
bExecuteTimers=bExecuteTimers@entry=true)
         at libreoffice/vcl/headless/svpinst.cxx:212
     #4  0x00007f2bdd4e713d in SvpSalInstance::ImplYield 
(this=this@entry=0x261ef40, bWait=bWait@entry=true, 
bHandleAllCurrentEvents=bHandleAllCurrentEvents@entry=false)
         at libreoffice/vcl/headless/svpinst.cxx:453
     #5  0x00007f2bdd4e74a0 in SvpSalInstance::DoYield (this=0x261ef40, 
bWait=<optimized out>, bHandleAllCurrentEvents=<optimized out>)
        at libreoffice/vcl/headless/svpinst.cxx:525
    
    Change-Id: I66ec56603aeb8a7fe855253b961dafb0bc7b875e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158441
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 455a1775ccef305cfb96cc5f67c8ee47b7f3a2ae)

diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx
index e2c306fdab1b..db4c1aaf0bc2 100644
--- a/vcl/source/window/window2.cxx
+++ b/vcl/source/window/window2.cxx
@@ -219,6 +219,12 @@ void Window::InvertTracking( const tools::Rectangle& 
rRect, ShowTrackFlags nFlag
 
 IMPL_LINK( Window, ImplTrackTimerHdl, Timer*, pTimer, void )
 {
+    if (!mpWindowImpl)
+    {
+        SAL_WARN("vcl", "ImplTrackTimerHdl has outlived dispose");
+        return;
+    }
+
     ImplSVData* pSVData = ImplGetSVData();
 
     // if Button-Repeat we have to change the timeout
commit 9324eb0ddbf312bdbd2448576189deaaf74d738e
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Wed Oct 18 16:47:20 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    crashreporting: svx::SentenceEditWindow_Impl::CreateSpellPortions()
    
    cui/source/dialogs/SpellDialog.cxx:2005
    aRet[ aRet.size() - 1 ].sText += aLeftOverText;
    
    presumably aRet is empty() here
    
    a) don't bother appending if aLeftOverText is empty()
    b) don't crah if aRet is empty() and aLeftOverText is not
    
    Change-Id: Ie9a9585f572d8afb17183b479fb6f2cce5952aa7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158124
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit e7e5b43c4906d9f0e199f689addc29aa98916e6e)

diff --git a/cui/source/dialogs/SpellDialog.cxx 
b/cui/source/dialogs/SpellDialog.cxx
index 204a0b308a2e..58558b660c6e 100644
--- a/cui/source/dialogs/SpellDialog.cxx
+++ b/cui/source/dialogs/SpellDialog.cxx
@@ -1973,7 +1973,7 @@ svx::SpellPortions 
SentenceEditWindow_Impl::CreateSpellPortions() const
                 aPortion2.sText = aLeftOverText.makeStringAndClear();
                 aRet.push_back( aPortion2 );
             }
-            else
+            else if (!aLeftOverText.isEmpty() && !aRet.empty())
             {   // we just need to append the left-over text to the last 
portion (which had no errors)
                 aRet[ aRet.size() - 1 ].sText += aLeftOverText;
             }
commit 70ccb4e299c147e6ea44ea22bebc9c7f5617cc3d
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Mon Oct 16 17:01:59 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:22 2023 +0100

    ofz#63295 Null-dereference READ
    
    Change-Id: Ib8bfa814099c1c1f3d65b18026ea812c80b6e9c9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158058
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 00904f994a2f03638ec7f284396aeb730746e68d)

diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index 86e4381819b8..9ef4c25ccf85 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -2477,7 +2477,7 @@ SwLinePortion* SwTextFormatter::MakeRestPortion( const 
SwLineLayout* pLine,
             pTmp = new SwDoubleLinePortion( *pCreate, nMultiPos );
         else if( pHelpMulti->IsBidi() )
             pTmp = new SwBidiPortion( nMultiPos, pCreate->nLevel );
-        else if (IsIncompleteRuby(*pHelpMulti))
+        else if (IsIncompleteRuby(*pHelpMulti) && pCreate->pAttr)
         {
             TextFrameIndex nRubyOffset = static_cast<const 
SwRubyPortion*>(pHelpMulti)->GetRubyOffset();
             pTmp = new SwRubyPortion( *pCreate, *GetInfo().GetFont(),
commit 2905930f8047d32cd19f34b2551296dd2c6fa045
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Tue Oct 10 21:23:43 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:21 2023 +0100

    make CppunitTest_framework_dispatch reliable
    
    the appearance of 2 interceptions is reproducible for me on linux with
    
    make CppunitTest_framework_dispatch VALGRIND=memcheck
    
    1st time
     #1 (anonymous 
namespace)::MyInterceptor::queryDispatch(com::sun::star::util::URL const&, 
rtl::OUString const&, int) at core/framework/qa/cppunit/dispatchtest.cxx:139
     #2 non-virtual thunk to (anonymous 
namespace)::MyInterceptor::queryDispatch(com::sun::star::util::URL const&, 
rtl::OUString const&, int) at core/framework/qa/cppunit/dispatchtest.cxx:0
     #3 framework::InterceptionHelper::queryDispatch(com::sun::star::util::URL 
const&, rtl::OUString const&, int) at 
core/framework/source/dispatch/interceptionhelper.cxx:87
     #4 non-virtual thunk to 
framework::InterceptionHelper::queryDispatch(com::sun::star::util::URL const&, 
rtl::OUString const&, int) at 
core/framework/source/dispatch/interceptionhelper.cxx:0
     #5 (anonymous 
namespace)::XFrameImpl::queryDispatch(com::sun::star::util::URL const&, 
rtl::OUString const&, int) at core/framework/source/services/frame.cxx:2329
     #6 non-virtual thunk to (anonymous 
namespace)::XFrameImpl::queryDispatch(com::sun::star::util::URL const&, 
rtl::OUString const&, int) at core/framework/source/services/frame.cxx:0
     #7 
framework::DispatchHelper::executeDispatch(com::sun::star::uno::Reference<com::sun::star::frame::XDispatchProvider>
 const&, rtl::OUString const&, rtl::OUString const&, int, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at 
core/framework/source/services/dispatchhelper.cxx:110
     #8 non-virtual thunk to 
framework::DispatchHelper::executeDispatch(com::sun::star::uno::Reference<com::sun::star::frame::XDispatchProvider>
 const&, rtl::OUString const&, rtl::OUString const&, int, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at 
core/framework/source/services/dispatchhelper.cxx:0
     #9 
unotest::MacrosTest::dispatchCommand(com::sun::star::uno::Reference<com::sun::star::lang::XComponent>
 const&, rtl::OUString const&, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at 
core/unotest/source/cpp/macros_test.cxx:94
     #10 (anonymous namespace)::testInterception::TestBody() at 
core/framework/qa/cppunit/dispatchtest.cxx:172
    
    2nd time
     #1 (anonymous 
namespace)::MyInterceptor::queryDispatch(com::sun::star::util::URL const&, 
rtl::OUString const&, int) at core/framework/qa/cppunit/dispatchtest.cxx:139
     #2 non-virtual thunk to (anonymous 
namespace)::MyInterceptor::queryDispatch(com::sun::star::util::URL const&, 
rtl::OUString const&, int) at core/framework/qa/cppunit/dispatchtest.cxx:0
     #3 framework::InterceptionHelper::queryDispatch(com::sun::star::util::URL 
const&, rtl::OUString const&, int) at 
core/framework/source/dispatch/interceptionhelper.cxx:87
     #4 non-virtual thunk to 
framework::InterceptionHelper::queryDispatch(com::sun::star::util::URL const&, 
rtl::OUString const&, int) at 
core/framework/source/dispatch/interceptionhelper.cxx:0
     #5 (anonymous 
namespace)::XFrameImpl::queryDispatch(com::sun::star::util::URL const&, 
rtl::OUString const&, int) at core/framework/source/services/frame.cxx:2329
     #6 non-virtual thunk to (anonymous 
namespace)::XFrameImpl::queryDispatch(com::sun::star::util::URL const&, 
rtl::OUString const&, int) at core/framework/source/services/frame.cxx:0
     #7 SfxStateCache::GetSlotServer(SfxDispatcher&, 
com::sun::star::uno::Reference<com::sun::star::frame::XDispatchProvider> 
const&) at core/sfx2/source/control/statcach.cxx:263
     #8 SfxBindings::UpdateSlotServer_Impl() at 
core/sfx2/source/control/bindings.cxx:1083
     #9 SfxBindings::NextJob_Impl(Timer const*) at 
core/sfx2/source/control/bindings.cxx:1254
     #10 SfxBindings::NextJob(Timer*) at 
core/sfx2/source/control/bindings.cxx:1222
     #11 SfxBindings::LinkStubNextJob(void*, Timer*) at 
core/sfx2/source/control/bindings.cxx:1219
     #12 Link<Timer*, void>::Call(Timer*) const at 
core/include/tools/link.hxx:111
     #13 Timer::Invoke() at core/vcl/source/app/timer.cxx:76
     #14 Scheduler::CallbackTaskScheduling() at 
core/vcl/source/app/scheduler.cxx:480
     #15 SalTimer::CallCallback() at core/vcl/inc/saltimer.hxx:55
     #16 SvpSalInstance::CheckTimeout(bool) at core/vcl/headless/svpinst.cxx:161
     #17 SvpSalInstance::ImplYield(bool, bool) at 
core/vcl/headless/svpinst.cxx:399
     #18 SvpSalInstance::DoYield(bool, bool) at 
core/vcl/headless/svpinst.cxx:471
     #19 ImplYield(bool, bool) at core/vcl/source/app/svapp.cxx:377
     #20 Scheduler::ProcessEventsToIdle() at core/vcl/source/app/svapp.cxx:407
     #21 
unotest::MacrosTest::dispatchCommand(com::sun::star::uno::Reference<com::sun::star::lang::XComponent>
 const&, rtl::OUString const&, 
com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at 
core/unotest/source/cpp/macros_test.cxx:95
     #22 (anonymous namespace)::testInterception::TestBody() at 
core/framework/qa/cppunit/dispatchtest.cxx:172
    
    setting bold/italic will invalidate the slot for the property and timer
    starts to update the normal listeners to those properties which might
    kick in on a slower run.
    
    Change-Id: Ib37e61c0fbed463f8974d476158e54a0160a2c92
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157798
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 30c582a7202b1403e260af933258d456e7280a19)

diff --git a/framework/qa/cppunit/dispatchtest.cxx 
b/framework/qa/cppunit/dispatchtest.cxx
index 7903715e4113..68d68f63f872 100644
--- a/framework/qa/cppunit/dispatchtest.cxx
+++ b/framework/qa/cppunit/dispatchtest.cxx
@@ -184,10 +184,9 @@ CPPUNIT_TEST_FIXTURE(DispatchTest, testInterception)
     
xRegistration->registerDispatchProviderInterceptor(uno::Reference<frame::XDispatchProviderInterceptor>(pInterceptor.get()));
 
     dispatchCommand(mxComponent, ".uno:Bold", {});
-    CPPUNIT_ASSERT_EQUAL(1, pInterceptor->getExpected());
+    CPPUNIT_ASSERT_GREATER(0, pInterceptor->getExpected());
     CPPUNIT_ASSERT_EQUAL(0, pInterceptor->getUnexpected());
     dispatchCommand(mxComponent, ".uno:Italic", {});
-    CPPUNIT_ASSERT_EQUAL(1, pInterceptor->getExpected());
     // This was 1: MyInterceptor::queryDispatch() was called for .uno:Italic.
     CPPUNIT_ASSERT_EQUAL(0, pInterceptor->getUnexpected());
 }
commit c03f522db21f009fefd41665fc6fe8130fe5bf1a
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Tue Oct 10 16:29:16 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:21 2023 +0100

    tdf#154142 null-deref in SfxUndoManager::SetMaxUndoActionCount
    
    Change-Id: I09cfbccb5f2ffa009a3e40157c9373b7e10864dc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157764
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 6cfd36a392ec3710304ff3df3cb0f42e0d8b53d9)

diff --git a/sc/source/ui/view/formatsh.cxx b/sc/source/ui/view/formatsh.cxx
index 3460d6e3d927..fc3983efce81 100644
--- a/sc/source/ui/view/formatsh.cxx
+++ b/sc/source/ui/view/formatsh.cxx
@@ -138,7 +138,7 @@ ScFormatShell::ScFormatShell(ScViewData* pData) :
     SetPool( &pTabViewShell->GetPool() );
     SfxUndoManager* pMgr = pViewData->GetSfxDocShell()->GetUndoManager();
     SetUndoManager( pMgr );
-    if ( !pViewData->GetDocument()->IsUndoEnabled() )
+    if (pMgr && !pViewData->GetDocument()->IsUndoEnabled())
     {
         pMgr->SetMaxUndoActionCount( 0 );
     }
commit b937306a5019b493e1f6f19d19140a69975c9f27
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Mon Sep 25 11:15:36 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:21 2023 +0100

    ofz#62688 Null-dereference READ in SwRubyPortion::SwRubyPortion
    
    seen with fodt2pdf fuzzer
    
    Change-Id: If761f5ecc473f4c936db82f3fcb7dd891e82573f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157243
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit cc564cea7eda29ed7e98ea27056f3ab57a6e2027)

diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index 3bd45fee2180..86e4381819b8 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -2357,6 +2357,11 @@ bool SwTextFormatter::BuildMultiPortion( 
SwTextFormatInfo &rInf,
     return bRet;
 }
 
+static bool IsIncompleteRuby(const SwMultiPortion& rHelpMulti)
+{
+    return rHelpMulti.IsRuby() && static_cast<const 
SwRubyPortion&>(rHelpMulti).GetRubyOffset() < TextFrameIndex(COMPLETE_STRING);
+}
+
 // When a fieldportion at the end of line breaks and needs a following
 // fieldportion in the next line, then the "restportion" of the formatinfo
 // has to be set. Normally this happens during the formatting of the first
@@ -2465,19 +2470,19 @@ SwLinePortion* SwTextFormatter::MakeRestPortion( const 
SwLineLayout* pLine,
     if (!pCreate)
         return pRest;
 
-    if( pRest || nMultiPos > nPosition || ( pHelpMulti->IsRuby() &&
-        static_cast<const SwRubyPortion*>(pHelpMulti)->GetRubyOffset() < 
TextFrameIndex(COMPLETE_STRING)))
+    if( pRest || nMultiPos > nPosition || IsIncompleteRuby(*pHelpMulti))
     {
         SwMultiPortion* pTmp;
         if( pHelpMulti->IsDouble() )
             pTmp = new SwDoubleLinePortion( *pCreate, nMultiPos );
         else if( pHelpMulti->IsBidi() )
             pTmp = new SwBidiPortion( nMultiPos, pCreate->nLevel );
-        else if( pHelpMulti->IsRuby() )
+        else if (IsIncompleteRuby(*pHelpMulti))
         {
+            TextFrameIndex nRubyOffset = static_cast<const 
SwRubyPortion*>(pHelpMulti)->GetRubyOffset();
             pTmp = new SwRubyPortion( *pCreate, *GetInfo().GetFont(),
                                        
m_pFrame->GetDoc().getIDocumentSettingAccess(),
-                                       nMultiPos, static_cast<const 
SwRubyPortion*>(pHelpMulti)->GetRubyOffset(),
+                                       nMultiPos, nRubyOffset,
                                        GetInfo() );
         }
         else if( pHelpMulti->HasRotation() )
commit c803721ad3d1b1d75e4115c9336da81b5ebeb8a3
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Thu Sep 14 20:18:55 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:21 2023 +0100

    crashreporting: apparent null deref at 
SwFEShell::IsShapeDefaultHoriTextDirR2L
    
    https: 
//crashreport.libreoffice.org/stats/crash_details/73028951-19a0-409b-89d2-a080495df925
    Change-Id: I440465a3c7d5b98ecdd1c5f1973a2b8f64d6772e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156931
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 105d1c010c4dc3caedf66a2080045c9c5f6fb9e3)

diff --git a/sw/source/core/frmedt/feshview.cxx 
b/sw/source/core/frmedt/feshview.cxx
index fd0a930a95a0..65e684e1af06 100644
--- a/sw/source/core/frmedt/feshview.cxx
+++ b/sw/source/core/frmedt/feshview.cxx
@@ -3243,8 +3243,11 @@ bool SwFEShell::IsShapeDefaultHoriTextDirR2L() const
             if ( dynamic_cast<const SwVirtFlyDrawObj*>( pSdrObj) ==  nullptr )
             {
                 // determine page frame of the frame the shape is anchored.
-                const SwFrame* pAnchorFrame =
-                        
static_cast<SwDrawContact*>(GetUserCall(pSdrObj))->GetAnchorFrame( pSdrObj );
+                const SwContact* pContact = GetUserCall(pSdrObj);
+                OSL_ENSURE( pContact, 
"<SwFEShell::IsShapeDefaultHoriTextDirR2L(..)> - missing contact!" );
+                if (!pContact)
+                    return false;
+                const SwFrame* pAnchorFrame = static_cast<const 
SwDrawContact*>(pContact)->GetAnchorFrame( pSdrObj );
                 OSL_ENSURE( pAnchorFrame, "inconsistent model - no anchor at 
shape!");
                 if ( pAnchorFrame )
                 {
commit 7191131075e257eb41684df44d9d4fc40d0d1207
Author:     Stephan Bergmann <sberg...@redhat.com>
AuthorDate: Thu Nov 3 09:14:18 2022 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:21 2023 +0100

    -Werror=dangling-reference
    
    In
    
<https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=d2249cd9adf5ae638577139177a50f7e62d8abd9>
    "c++: Implement -Wdangling-reference [PR106393]" grew a new warning, 
included in
    -Wall, and based on some more-or-less shaky heuristics, that warns about
    "possibly dangling reference to a temporary".  It produces quite a number of
    false positives, but for these uses of SfxItemSet::Get it does look 
plausible
    that the returned item references could, at least in theory, point at data 
that
    is destroyed along with the temporary SfxItemSet.
    
    Change-Id: I11afc4512db488f73170c6cfa706e9e094209550
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142217
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>
    (cherry picked from commit e0121b2478526d803681d57d59af0cbf9cf602b4)
    (cherry picked from commit 6231cbaf9dfc558cf7238b976970c86955e27f35)

diff --git a/editeng/source/accessibility/AccessibleEditableTextPara.cxx 
b/editeng/source/accessibility/AccessibleEditableTextPara.cxx
index c68c79ebea8f..c87071b97324 100644
--- a/editeng/source/accessibility/AccessibleEditableTextPara.cxx
+++ b/editeng/source/accessibility/AccessibleEditableTextPara.cxx
@@ -1527,8 +1527,7 @@ namespace accessibility
             // NumberingLevel
             if (rRes.Name == "NumberingLevel")
             {
-                const SvxNumBulletItem& rNumBullet = 
rCacheTF.GetParaAttribs(GetParagraphIndex()).Get(EE_PARA_NUMBULLET);
-                if(rNumBullet.GetNumRule()->GetLevelCount()==0)
+                
if(rCacheTF.GetParaAttribs(GetParagraphIndex()).Get(EE_PARA_NUMBULLET).GetNumRule()->GetLevelCount()==0)
                 {
                     rRes.Value <<= sal_Int16(-1);
                     rRes.Handle = -1;
diff --git a/sc/source/ui/drawfunc/drtxtob.cxx 
b/sc/source/ui/drawfunc/drtxtob.cxx
index 2cdf432edc11..dd06436be6b9 100644
--- a/sc/source/ui/drawfunc/drtxtob.cxx
+++ b/sc/source/ui/drawfunc/drtxtob.cxx
@@ -205,7 +205,8 @@ void ScDrawTextObjectBar::Execute( SfxRequest &rReq )
 
         case SID_CHARMAP:
             {
-                const SvxFontItem& rItem = 
pOutView->GetAttribs().Get(EE_CHAR_FONTINFO);
+                auto const attribs = pOutView->GetAttribs();
+                const SvxFontItem& rItem = attribs.Get(EE_CHAR_FONTINFO);
 
                 OUString aString;
                 std::shared_ptr<SvxFontItem> 
aNewItem(std::make_shared<SvxFontItem>(EE_CHAR_FONTINFO));
diff --git a/sc/source/ui/view/editsh.cxx b/sc/source/ui/view/editsh.cxx
index 61888c663ef4..413041e0d0e0 100644
--- a/sc/source/ui/view/editsh.cxx
+++ b/sc/source/ui/view/editsh.cxx
@@ -385,8 +385,9 @@ void ScEditShell::Execute( SfxRequest& rReq )
                 sal_uInt16 nFontWhich = ( nScript == SvtScriptType::ASIAN ) ? 
EE_CHAR_FONTINFO_CJK :
                                 ( ( nScript == SvtScriptType::COMPLEX ) ? 
EE_CHAR_FONTINFO_CTL :
                                                                         
EE_CHAR_FONTINFO );
+                auto const attribs = pTableView->GetAttribs();
                 const SvxFontItem& rItem = static_cast<const SvxFontItem&>(
-                            pTableView->GetAttribs().Get(nFontWhich));
+                            attribs.Get(nFontWhich));
 
                 OUString aString;
                 std::shared_ptr<SvxFontItem> 
aNewItem(std::make_shared<SvxFontItem>(EE_CHAR_FONTINFO));
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx 
b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index ff379531338f..a576c2a236bc 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -1337,8 +1337,8 @@ void SdTiledRenderingTest::testTdf102223()
     EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
     rEditView.SetSelection(ESelection(0, 0, 0, 3)); // start para, start char, 
end para, end char.
     CPPUNIT_ASSERT_EQUAL(OUString("Red"), rEditView.GetSelected());
-    const SvxFontHeightItem& rItem = 
rEditView.GetAttribs().Get(EE_CHAR_FONTHEIGHT);
-    CPPUNIT_ASSERT_EQUAL(int(1411), static_cast<int>(rItem.GetHeight()));
+    CPPUNIT_ASSERT_EQUAL(
+        int(1411), 
static_cast<int>(rEditView.GetAttribs().Get(EE_CHAR_FONTHEIGHT).GetHeight()));
 
     // cut contents of cell
     uno::Sequence<beans::PropertyValue> aArgs;
@@ -1349,8 +1349,8 @@ void SdTiledRenderingTest::testTdf102223()
     CPPUNIT_ASSERT(pView->GetTextEditObject());
     EditView& rEditView2 = pView->GetTextEditOutlinerView()->GetEditView();
     rEditView2.SetSelection(ESelection(0, 0, 0, 1)); // start para, start 
char, end para, end char.
-    const SvxFontHeightItem& rItem2 = 
rEditView2.GetAttribs().Get(EE_CHAR_FONTHEIGHT);
-    CPPUNIT_ASSERT_EQUAL(int(1411), static_cast<int>(rItem2.GetHeight()));
+    CPPUNIT_ASSERT_EQUAL(
+        int(1411), 
static_cast<int>(rEditView2.GetAttribs().Get(EE_CHAR_FONTHEIGHT).GetHeight()));
 }
 
 void SdTiledRenderingTest::testPostKeyEventInvalidation()
commit 314bc7b9ac0a52e19a28fe7ebf10751ef84db86f
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Nov 8 11:55:51 2023 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Nov 24 21:58:21 2023 +0100

    python3: name gdb pretty-printer after .so, not .bin
    
    So it works not only with instdir/program/python but also with
    soffice in-process python.
    
    Change-Id: I5c3643ef4a7ca0f25df3c6f51d11ff98c27f4bd8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159148
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit a2fabc78a4ba12ad8df6b040783be0fa22aefa54)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159049
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    (cherry picked from commit c4a57f59d56312bbdcb507ecbf13b75c6c6db1dc)

diff --git a/external/python3/ExternalPackage_python3.mk 
b/external/python3/ExternalPackage_python3.mk
index f7b8d67f25b2..833fe24f7bb3 100644
--- a/external/python3/ExternalPackage_python3.mk
+++ b/external/python3/ExternalPackage_python3.mk
@@ -42,7 +42,7 @@ else
 $(eval $(call 
gb_ExternalPackage_add_file,python3,$(LIBO_BIN_FOLDER)/python.bin,python))
 $(eval $(call 
gb_ExternalPackage_add_file,python3,$(LIBO_BIN_FOLDER)/libpython$(PYTHON_VERSION_MAJOR).so,libpython$(PYTHON_VERSION_MAJOR).so))
 $(eval $(call 
gb_ExternalPackage_add_file,python3,$(LIBO_BIN_FOLDER)/libpython$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR).so.1.0,libpython$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR).so))
-$(eval $(call 
gb_ExternalPackage_add_file,python3,$(LIBO_BIN_FOLDER)/python-gdb.py,Tools/gdb/libpython.py))
+$(eval $(call 
gb_ExternalPackage_add_file,python3,$(LIBO_BIN_FOLDER)/libpython$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR).so.1.0-gdb.py,Tools/gdb/libpython.py))
 
 # Unfortunately the python build system does not allow to explicitly enable or
 # disable these, it just tries to build them and then prints which did not

Reply via email to