sw/qa/extras/layout/data/forcepoint99.html |binary
 sw/qa/extras/layout/layout.cxx             |    6 ++++++
 sw/source/core/text/itrform2.cxx           |   15 +++++++++++----
 sw/source/core/text/itrform2.hxx           |    2 ++
 sw/source/core/text/porlay.cxx             |    4 +++-
 5 files changed, 22 insertions(+), 5 deletions(-)

New commits:
commit 0a34ac386187c5ca328aebc27851c2a2ff38f293
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Fri Apr 1 16:52:06 2022 +0100
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Mon Apr 4 20:57:24 2022 +0200

    forcepoint#99 SwTextFormatter unaware that FirstOfBorderMerge was deleted
    
    READ of size 8 at 0x606000a49e50 thread T0
        #0 0x7f7ab6214bf5 in SwPosSize::Height() const 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/possiz.hxx:49:37
        #1 0x7f7ab636c311 in 
SwTextFormatter::MergeCharacterBorder(SwLinePortion&, SwLinePortion const*, 
SwTextFormatInfo&) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/itrform2.cxx:2807:43
        #2 0x7f7ab636ae08 in SwTextFormatter::InsertPortion(SwTextFormatInfo&, 
SwLinePortion*) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/itrform2.cxx:354:13
        #3 0x7f7ab6371db1 in SwTextFormatter::BuildPortions(SwTextFormatInfo&) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/itrform2.cxx:709:9
        #4 0x7f7ab638b2ac in SwTextFormatter::FormatLine(o3tl::strong_int<int, 
Tag_TextFrameIndex>) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/itrform2.cxx:1701:9
        #5 0x7f7ab62a8ad1 in SwTextFrame::FormatLine(SwTextFormatter&, bool) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/frmform.cxx:1212:44
        #6 0x7f7ab62af1cc in SwTextFrame::Format_(SwTextFormatter&, 
SwTextFormatInfo&, bool) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/frmform.cxx:1571:23
        #7 0x7f7ab62b1f17 in SwTextFrame::Format_(OutputDevice*, 
SwParaPortion*) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/frmform.cxx:1743:5
        #8 0x7f7ab62b5260 in SwTextFrame::Format(OutputDevice*, SwBorderAttrs 
const*) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/frmform.cxx:1932:17
        #9 0x7f7ab5dbdabd in SwContentFrame::MakeAll(OutputDevice*) 
/home/caolan/LibreOffice/core-asan/sw/source/core/layout/calcmove.cxx:1514:17
    
    0x606000a49e50 is located 16 bytes inside of 56-byte region 
[0x606000a49e40,0x606000a49e78)
    freed by thread T0 here:
        #0 0x4fe1f7 in operator delete(void*) 
(/home/caolan/LibreOffice/core-asan/instdir/program/soffice.bin+0x4fe1f7)
        #1 0x7f7ab6486d35 in SwTextPortion::~SwTextPortion() 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/portxt.hxx:26:7
        #2 0x7f7ab63da0c9 in SwLineLayout::CalcLine(SwTextFormatter&, 
SwTextFormatInfo&) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/porlay.cxx:430:21
        #3 0x7f7ab6435413 in SwMultiPortion::CalcSize(SwTextFormatter&, 
SwTextFormatInfo&) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/pormulti.cxx:75:15
        #4 0x7f7ab6457749 in 
SwTextFormatter::BuildMultiPortion(SwTextFormatInfo&, SwMultiPortion&) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/pormulti.cxx:2090:16
        #5 0x7f7ab636f12c in SwTextFormatter::BuildPortions(SwTextFormatInfo&) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/itrform2.cxx:550:21
        #6 0x7f7ab638b2ac in SwTextFormatter::FormatLine(o3tl::strong_int<int, 
Tag_TextFrameIndex>) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/itrform2.cxx:1701:9
        #7 0x7f7ab62a8ad1 in SwTextFrame::FormatLine(SwTextFormatter&, bool) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/frmform.cxx:1212:44
        #8 0x7f7ab62af1cc in SwTextFrame::Format_(SwTextFormatter&, 
SwTextFormatInfo&, bool) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/frmform.cxx:1571:23
        #9 0x7f7ab62b1f17 in SwTextFrame::Format_(OutputDevice*, 
SwParaPortion*) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/frmform.cxx:1743:5
        #10 0x7f7ab62b5260 in SwTextFrame::Format(OutputDevice*, SwBorderAttrs 
const*) 
/home/caolan/LibreOffice/core-asan/sw/source/core/text/frmform.cxx:1932:17
        #11 0x7f7ab5dbdabd in SwContentFrame::MakeAll(OutputDevice*) 
/home/caolan/LibreOffice/core-asan/sw/source/core/layout/calcmove.cxx:1514:17
    
    similar seen in the past as:
    
    commit 96acebb72211b4718eb3038c427df37b55b17b0b
    Date:   Tue May 14 01:49:03 2019 +0800
    
        tdf#124937 reset m_pFirstOfBorderMerge before truncate.
    
    commit ecd855794b22c0f7e6fb2f362b566c4d9c5f624a
    Date:   Mon Jan 15 22:29:31 2018 +0100
    
        tdf#114536 sw: fix use-after-free in 
SwTextFormatter::MergeCharacterBorder()
    
    Change-Id: Iad855f382a0daf50dac2537d4a91bfeaa9ff3799
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132439
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit b46baea4d1cce81c56ee0d82fbdc352921445fa7)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132380
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/qa/extras/layout/data/forcepoint99.html 
b/sw/qa/extras/layout/data/forcepoint99.html
new file mode 100644
index 000000000000..6eb36a616e26
Binary files /dev/null and b/sw/qa/extras/layout/data/forcepoint99.html differ
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index 9ba5927f3e41..c78273685865 100644
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -2566,6 +2566,12 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf118058)
     pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout();
 }
 
+//just care it doesn't crash/assert
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testForcepoint99)
+{
+    createSwWebDoc(DATA_DIRECTORY, "forcepoint99.html");
+}
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf128611)
 {
     createSwDoc(DATA_DIRECTORY, "tdf128611.fodt");
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 6a91d3c37dfc..764c2eced2bd 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -150,6 +150,16 @@ sal_uInt16 SwTextFormatter::GetFrameRstHeight() const
         return sal_uInt16( nHeight );
 }
 
+bool SwTextFormatter::ClearIfIsFirstOfBorderMerge(const SwLinePortion* 
pPortion)
+{
+    if (pPortion == m_pFirstOfBorderMerge)
+    {
+        m_pFirstOfBorderMerge = nullptr;
+        return true;
+    }
+    return false;
+}
+
 SwLinePortion *SwTextFormatter::Underflow( SwTextFormatInfo &rInf )
 {
     // Save values and initialize rInf
@@ -278,11 +288,8 @@ SwLinePortion *SwTextFormatter::Underflow( 
SwTextFormatInfo &rInf )
     SwLinePortion* pNext = pPor->GetNextPortion();
     while (pNext)
     {
-        if (pNext == m_pFirstOfBorderMerge)
-        {
-            m_pFirstOfBorderMerge = nullptr;
+        if (ClearIfIsFirstOfBorderMerge(pNext))
             break;
-        }
         pNext = pNext->GetNextPortion();
     }
     pPor->Truncate();
diff --git a/sw/source/core/text/itrform2.hxx b/sw/source/core/text/itrform2.hxx
index bd986e4be324..d5f0fa550b51 100644
--- a/sw/source/core/text/itrform2.hxx
+++ b/sw/source/core/text/itrform2.hxx
@@ -238,6 +238,8 @@ public:
      * @param   rInf        contain information
     **/
     void MergeCharacterBorder( SwLinePortion& rPortion, SwLinePortion const 
*pPrev, SwTextFormatInfo& rInf );
+
+    bool ClearIfIsFirstOfBorderMerge(SwLinePortion const *pPortion);
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 3db5d2ab0ac3..9db1949870d0 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -397,7 +397,9 @@ void SwLineLayout::CalcLine( SwTextFormatter &rLine, 
SwTextFormatInfo &rInf )
                         if( !GetAscent() )
                             SetAscent( pPos->GetAscent() );
                     }
-                    delete pLast->Cut( pPos );
+                    SwLinePortion* pPortion = pLast->Cut( pPos );
+                    rLine.ClearIfIsFirstOfBorderMerge(pPortion);
+                    delete pPortion;
                     pPos = pLast->GetNextPortion();
                     continue;
                 }

Reply via email to