external/icu/UnpackedTarball_icu.mk                           |    3 
 external/icu/cec7de7a390dd6907b0ea0feb4488ed3934ee71d.patch.2 |   94 ++++++++++
 external/icu/e450fa50fc242282551f56b941dc93b9a8a0bcbb.patch.2 |   39 ++++
 sw/source/core/inc/layact.hxx                                 |    8 
 sw/source/core/layout/layact.cxx                              |   65 ++++++
 sw/source/core/layout/objectformattertxtfrm.cxx               |    2 
 sw/source/core/layout/pagechg.cxx                             |    2 
 7 files changed, 205 insertions(+), 8 deletions(-)

New commits:
commit 59c7bc4387b51bd9749bb758a2499cd0a56b4047
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Nov 5 18:33:07 2021 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Sun Feb 20 10:22:16 2022 +0100

    icu: add patch for CVE-2021-30535
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124779
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 35eef8ec9b122a761400f3c6590ca1f9a187d772)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124701
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    (cherry picked from commit 105c258fcdd69f617de64b780ffcdb8304ff262c)
    
    Change-Id: I398596f77aa47ab6d4db01b94422262048cffd3e

diff --git a/external/icu/UnpackedTarball_icu.mk 
b/external/icu/UnpackedTarball_icu.mk
index 435382fa7988..ef08f2e25d4c 100644
--- a/external/icu/UnpackedTarball_icu.mk
+++ b/external/icu/UnpackedTarball_icu.mk
@@ -39,8 +39,11 @@ $(eval $(call gb_UnpackedTarball_add_patches,icu,\
        external/icu/icu4c-khmerbreakengine.patch.1 \
        external/icu/strict_ansi.patch \
        external/icu/icu4c-windows-cygwin-cross.patch.1 \
+       external/icu/cec7de7a390dd6907b0ea0feb4488ed3934ee71d.patch.2 \
+       external/icu/e450fa50fc242282551f56b941dc93b9a8a0bcbb.patch.2 \
        external/icu/icu4c-$(if $(filter ANDROID,$(OS)),android,rpath).patch.1 \
        $(if $(filter-out 
ANDROID,$(OS)),external/icu/icu4c-icudata-stdlibs.patch.1) \
+
 ))
 
 $(eval $(call 
gb_UnpackedTarball_add_file,icu,source/data/brkitr/khmerdict.dict,external/icu/khmerdict.dict))
diff --git a/external/icu/cec7de7a390dd6907b0ea0feb4488ed3934ee71d.patch.2 
b/external/icu/cec7de7a390dd6907b0ea0feb4488ed3934ee71d.patch.2
new file mode 100644
index 000000000000..1ded56abf524
--- /dev/null
+++ b/external/icu/cec7de7a390dd6907b0ea0feb4488ed3934ee71d.patch.2
@@ -0,0 +1,94 @@
+From cec7de7a390dd6907b0ea0feb4488ed3934ee71d Mon Sep 17 00:00:00 2001
+From: Frank Tang <ft...@chromium.org>
+Date: Tue, 16 Mar 2021 22:08:29 -0700
+Subject: [PATCH] ICU-21537 Fix invalid free by long locale name
+
+Do not free baseName if it is pointing to fullNameBuffer.
+
+Better Fix
+---
+ icu4c/source/common/locid.cpp                |  9 +++++----
+ icu4c/source/test/intltest/collationtest.cpp | 10 ++++++++++
+ 2 files changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp
+index 5d604350ecd..e16fbb724a4 100644
+--- a/icu4c/source/common/locid.cpp
++++ b/icu4c/source/common/locid.cpp
+@@ -254,7 +254,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Locale)
+ 
+ Locale::~Locale()
+ {
+-    if (baseName != fullName) {
++    if ((baseName != fullName) && (baseName != fullNameBuffer)) {
+         uprv_free(baseName);
+     }
+     baseName = NULL;
+@@ -466,7 +466,7 @@ Locale& Locale::operator=(const Locale& other) {
+ }
+ 
+ Locale& Locale::operator=(Locale&& other) U_NOEXCEPT {
+-    if (baseName != fullName) uprv_free(baseName);
++    if ((baseName != fullName) && (baseName != fullNameBuffer)) 
uprv_free(baseName);
+     if (fullName != fullNameBuffer) uprv_free(fullName);
+ 
+     if (other.fullName == other.fullNameBuffer) {
+@@ -1850,7 +1850,7 @@ Locale& Locale::init(const char* localeID, UBool 
canonicalize)
+ {
+     fIsBogus = FALSE;
+     /* Free our current storage */
+-    if (baseName != fullName) {
++    if ((baseName != fullName) && (baseName != fullNameBuffer)) {
+         uprv_free(baseName);
+     }
+     baseName = NULL;
+@@ -1886,6 +1886,7 @@ Locale& Locale::init(const char* localeID, UBool 
canonicalize)
+             uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err);
+ 
+         if(err == U_BUFFER_OVERFLOW_ERROR || length >= 
(int32_t)sizeof(fullNameBuffer)) {
++            U_ASSERT(baseName == nullptr);
+             /*Go to heap for the fullName if necessary*/
+             fullName = (char *)uprv_malloc(sizeof(char)*(length + 1));
+             if(fullName == 0) {
+@@ -2039,7 +2040,7 @@ Locale::hashCode() const
+ void
+ Locale::setToBogus() {
+     /* Free our current storage */
+-    if(baseName != fullName) {
++    if((baseName != fullName) && (baseName != fullNameBuffer)) {
+         uprv_free(baseName);
+     }
+     baseName = NULL;
+diff --git a/icu4c/source/test/intltest/collationtest.cpp 
b/icu4c/source/test/intltest/collationtest.cpp
+index de51eece5c4..4f1fee9375e 100644
+--- a/icu4c/source/test/intltest/collationtest.cpp
++++ b/icu4c/source/test/intltest/collationtest.cpp
+@@ -78,6 +78,7 @@ class CollationTest : public IntlTest {
+     void TestRootElements();
+     void TestTailoredElements();
+     void TestDataDriven();
++    void TestLongLocale();
+ 
+ private:
+     void checkFCD(const char *name, CollationIterator &ci, CodePointIterator 
&cpi);
+@@ -148,6 +149,7 @@ void CollationTest::runIndexedTest(int32_t index, UBool 
exec, const char *&name,
+     TESTCASE_AUTO(TestRootElements);
+     TESTCASE_AUTO(TestTailoredElements);
+     TESTCASE_AUTO(TestDataDriven);
++    TESTCASE_AUTO(TestLongLocale);
+     TESTCASE_AUTO_END;
+ }
+ 
+@@ -1852,4 +1854,12 @@ void CollationTest::TestDataDriven() {
+     }
+ }
+ 
++void CollationTest::TestLongLocale() {
++    IcuTestErrorCode errorCode(*this, "TestLongLocale");
++    Locale 
longLocale("sie__1G_C_CEIE_CEZCX_CSUE_E_EIESZNI2_GB_LM_LMCSUE_LMCSX_"
++                      "LVARIANT_MMCSIE_STEU_SU1GCEIE_SU6G_SU6SU6G_U_UBGE_UC_"
++                      "UCEZCSI_UCIE_UZSIU_VARIANT_X@collation=bcs-ukvsz");
++    LocalPointer<Collator> coll(Collator::createInstance(longLocale, 
errorCode));
++}
++
+ #endif  // !UCONFIG_NO_COLLATION
diff --git a/external/icu/e450fa50fc242282551f56b941dc93b9a8a0bcbb.patch.2 
b/external/icu/e450fa50fc242282551f56b941dc93b9a8a0bcbb.patch.2
new file mode 100644
index 000000000000..4709cd8c37fd
--- /dev/null
+++ b/external/icu/e450fa50fc242282551f56b941dc93b9a8a0bcbb.patch.2
@@ -0,0 +1,39 @@
+From e450fa50fc242282551f56b941dc93b9a8a0bcbb Mon Sep 17 00:00:00 2001
+From: Frank Tang <ft...@chromium.org>
+Date: Tue, 13 Apr 2021 15:16:50 -0700
+Subject: [PATCH] ICU-21587 Fix memory bug w/ baseName
+
+Edge cases not fixed in assign and move assign operator
+while the locale is long and call setKeywordValue with incorrect
+keyword/values.
+---
+ icu4c/source/common/locid.cpp          | 11 +++++++++--
+ icu4c/source/test/intltest/loctest.cpp | 26 ++++++++++++++++++++++++++
+ icu4c/source/test/intltest/loctest.h   |  2 ++
+ 3 files changed, 37 insertions(+), 2 deletions(-)
+
+diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp
+index 02cd82a7b8e..3c6e5b06690 100644
+--- a/icu4c/source/common/locid.cpp
++++ b/icu4c/source/common/locid.cpp
+@@ -469,14 +469,18 @@ Locale& Locale::operator=(Locale&& other) U_NOEXCEPT {
+     if ((baseName != fullName) && (baseName != fullNameBuffer)) 
uprv_free(baseName);
+     if (fullName != fullNameBuffer) uprv_free(fullName);
+ 
+-    if (other.fullName == other.fullNameBuffer) {
++    if (other.fullName == other.fullNameBuffer || other.baseName == 
other.fullNameBuffer) {
+         uprv_strcpy(fullNameBuffer, other.fullNameBuffer);
++    }
++    if (other.fullName == other.fullNameBuffer) {
+         fullName = fullNameBuffer;
+     } else {
+         fullName = other.fullName;
+     }
+ 
+-    if (other.baseName == other.fullName) {
++    if (other.baseName == other.fullNameBuffer) {
++        baseName = fullNameBuffer;
++    } else if (other.baseName == other.fullName) {
+         baseName = fullName;
+     } else {
+         baseName = other.baseName;
commit 152e5eeb613efe50190a1cdf18cb5bb06c46d9d7
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Fri Jul 16 12:45:21 2021 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Sun Feb 20 09:40:46 2022 +0100

    crashtesting: UaF on layout of fdo53985-1.docx
    
    Change-Id: Id8ca0d277f485347e21bd8d6d68de2a7de13de48
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119060
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/sw/source/core/inc/layact.hxx b/sw/source/core/inc/layact.hxx
index fefe964eb97e..5445d26dfa76 100644
--- a/sw/source/core/inc/layact.hxx
+++ b/sw/source/core/inc/layact.hxx
@@ -66,6 +66,9 @@ class SwLayAction
 
     std::unique_ptr<SwWait> m_pWait;
 
+    std::vector<SwFrame*> m_aFrameStack;
+    std::vector<std::unique_ptr<SwFrameDeleteGuard>> m_aFrameDeleteGuards;
+
     // If a paragraph (or anything else) moved more than one page when
     // formatting, it adds its new page number here.
     // The InternalAction can then take the appropriate steps.
@@ -119,6 +122,9 @@ class SwLayAction
 
     bool RemoveEmptyBrowserPages();
 
+    void PushFormatLayout(SwFrame* pLow);
+    void PopFormatLayout();
+
     inline void CheckIdleEnd();
 
 public:
@@ -150,7 +156,7 @@ public:
     void SetReschedule  ( bool bNew )   { m_bReschedule = bNew; }
     void SetWaitAllowed ( bool bNew )   { m_bWaitAllowed = bNew; }
 
-    void SetAgain(bool bAgain) { m_bAgain = bAgain; }
+    void SetAgain(bool bAgain);
     void SetUpdateExpFields() {m_bUpdateExpFields = true; }
 
     inline void SetCheckPageNum( sal_uInt16 nNew );
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index 7acaf1495144..8d763fc22ce8 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -320,6 +320,53 @@ bool SwLayAction::RemoveEmptyBrowserPages()
     return bRet;
 }
 
+void SwLayAction::SetAgain(bool bAgain)
+{
+    if (bAgain == m_bAgain)
+        return;
+
+    m_bAgain = bAgain;
+
+    assert(m_aFrameStack.size() == m_aFrameDeleteGuards.size());
+    size_t nCount = m_aFrameStack.size();
+    if (m_bAgain)
+    {
+        // LayAction::FormatLayout is now flagged to exit early and will avoid
+        // dereferencing any SwFrames in the stack of FormatLayouts so allow
+        // their deletion
+        for (size_t i = 0; i < nCount; ++i)
+            m_aFrameDeleteGuards[i].reset();
+    }
+    else
+    {
+        // LayAction::FormatLayout is now continue normally and will
+        // dereference the top SwFrame in the stack of m_aFrameStack as each
+        // FormatLevel returns so disallow their deletion
+        for (size_t i = 0; i < nCount; ++i)
+            m_aFrameDeleteGuards[i] = 
std::make_unique<SwFrameDeleteGuard>(m_aFrameStack[i]);
+    }
+}
+
+void SwLayAction::PushFormatLayout(SwFrame* pLow)
+{
+    /* Workaround crash seen in crashtesting with fdo53985-1.docx
+
+       Lock pLow against getting deleted when it will be dereferenced
+       after FormatLayout
+
+       If SetAgain is called to make SwLayAction exit early to avoid that
+       dereference, then it clears these guards
+    */
+    m_aFrameStack.push_back(pLow);
+    m_aFrameDeleteGuards.push_back(std::make_unique<SwFrameDeleteGuard>(pLow));
+}
+
+void SwLayAction::PopFormatLayout()
+{
+    m_aFrameDeleteGuards.pop_back();
+    m_aFrameStack.pop_back();
+}
+
 void SwLayAction::Action(OutputDevice* pRenderContext)
 {
     m_bActionInProgress = true;
@@ -1384,7 +1431,11 @@ bool SwLayAction::FormatLayout( OutputDevice 
*pRenderContext, SwLayoutFrame *pLa
             }
             // Skip the ones already registered for deletion
             else if( !pLow->IsSctFrame() || 
static_cast<SwSectionFrame*>(pLow)->GetSection() )
+            {
+                PushFormatLayout(pLow);
                 bChanged |= FormatLayout( pRenderContext, 
static_cast<SwLayoutFrame*>(pLow), bAddRect );
+                PopFormatLayout();
+            }
         }
         else if ( m_pImp->GetShell()->IsPaintLocked() )
             // Shortcut to minimize the cycles. With Lock, the
commit 34f6c8c2b355f48623b0e94ee9d88501a1f3a6fd
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu Jul 15 14:13:35 2021 +0100
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Sun Feb 20 09:39:55 2022 +0100

    Only change SwLayAction::m_bAgain via SetAgain
    
    no logic change intended
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118983
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 3a5383892e1f0e22558cd56cb77d56a09c515b7a)
    
    Change-Id: Ib0174f8040faa3efde7b9c5ba9b062bac5a35da3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125291
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/source/core/inc/layact.hxx b/sw/source/core/inc/layact.hxx
index 6680949b3eff..fefe964eb97e 100644
--- a/sw/source/core/inc/layact.hxx
+++ b/sw/source/core/inc/layact.hxx
@@ -150,7 +150,7 @@ public:
     void SetReschedule  ( bool bNew )   { m_bReschedule = bNew; }
     void SetWaitAllowed ( bool bNew )   { m_bWaitAllowed = bNew; }
 
-    void SetAgain()         { m_bAgain = true; }
+    void SetAgain(bool bAgain) { m_bAgain = bAgain; }
     void SetUpdateExpFields() {m_bUpdateExpFields = true; }
 
     inline void SetCheckPageNum( sal_uInt16 nNew );
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index c8924882b5fd..7acaf1495144 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -283,12 +283,13 @@ SwLayAction::~SwLayAction()
 
 void SwLayAction::Reset()
 {
+    SetAgain(false);
     m_pOptTab = nullptr;
     m_nStartTicks = std::clock();
     m_nInputType = VclInputFlags::NONE;
     m_nEndPage = m_nPreInvaPage = m_nCheckPageNum = USHRT_MAX;
     m_bPaint = m_bComplete = m_bWaitAllowed = m_bCheckPages = true;
-    m_bInput = m_bAgain = m_bNextCycle = m_bCalcLayout = m_bIdle = 
m_bReschedule =
+    m_bInput = m_bNextCycle = m_bCalcLayout = m_bIdle = m_bReschedule =
     m_bUpdateExpFields = m_bBrowseActionStop = false;
 }
 
@@ -345,12 +346,15 @@ void SwLayAction::Action(OutputDevice* pRenderContext)
         SetCheckPages( false );
 
     InternalAction(pRenderContext);
-    m_bAgain |= RemoveEmptyBrowserPages();
+    if (RemoveEmptyBrowserPages())
+        SetAgain(true);
     while ( IsAgain() )
     {
-        m_bAgain = m_bNextCycle = false;
+        SetAgain(false);
+        m_bNextCycle = false;
         InternalAction(pRenderContext);
-        m_bAgain |= RemoveEmptyBrowserPages();
+        if (RemoveEmptyBrowserPages())
+            SetAgain(true);
     }
     m_pRoot->DeleteEmptySct();
 
@@ -641,7 +645,7 @@ void SwLayAction::InternalAction(OutputDevice* 
pRenderContext)
             {
                 bool bOld = IsAgain();
                 m_pRoot->RemoveSuperfluous();
-                m_bAgain = bOld;
+                SetAgain(bOld);
             }
             if ( IsAgain() )
             {
diff --git a/sw/source/core/layout/objectformattertxtfrm.cxx 
b/sw/source/core/layout/objectformattertxtfrm.cxx
index 14cf0e9c66b5..f4e9905d21c1 100644
--- a/sw/source/core/layout/objectformattertxtfrm.cxx
+++ b/sw/source/core/layout/objectformattertxtfrm.cxx
@@ -316,7 +316,7 @@ bool SwObjectFormatterTextFrame::DoFormatObjs()
         {
             // notify layout action, thus is can restart the layout process on
             // a previous page.
-            GetLayAction()->SetAgain();
+            GetLayAction()->SetAgain(true);
         }
         else
         {
diff --git a/sw/source/core/layout/pagechg.cxx 
b/sw/source/core/layout/pagechg.cxx
index 88c197cc6298..7b885474f135 100644
--- a/sw/source/core/layout/pagechg.cxx
+++ b/sw/source/core/layout/pagechg.cxx
@@ -285,7 +285,7 @@ void SwPageFrame::DestroyImpl()
             SwViewShellImp *pImp = pSh->Imp();
             pImp->SetFirstVisPageInvalid();
             if ( pImp->IsAction() )
-                pImp->GetLayAction().SetAgain();
+                pImp->GetLayAction().SetAgain(true);
             // #i9719# - retouche area of page
             // including border and shadow area.
             const bool bRightSidebar = (SidebarPosition() == 
sw::sidebarwindows::SidebarPosition::RIGHT);

Reply via email to