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