sc/inc/conditio.hxx | 5 ++--- sc/source/core/data/conditio.cxx | 23 ++++++++++++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-)
New commits: commit 5438e2fd66a0038a00692d2457d6c89b5bd14695 Author: Dennis Francis <[email protected]> AuthorDate: Fri Nov 7 22:41:15 2025 +0530 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Tue Nov 11 14:08:08 2025 +0100 cool#13378: fix oom with conditional formatting oom results when whole rows with conditional formatting is copied and pasted. This is because for every column in the row a listening 'mpCache' is created and the doc-broadcaster has to accomodate them before exhausting all memory. See ctor of ScColorFormatCache. One particular reproducer is: 1. Create a new Calc spreadsheet and enter a value in a cell, say 42. 2. Select the whole sheet. 3. Conditional > Manage > Add, and create a condition where cell value is equal to the value in the cell from step 1. 4. Click on the row header containing 42 and copy that row and paste it onto another row. Signed-off-by: Dennis Francis <[email protected]> Change-Id: Ifee510fe39131ed3c03febc3bed983f4962e546e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193589 Reviewed-by: Tomaž Vajngerl <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx index fe708bc6e356..9a7a3f2f263e 100644 --- a/sc/inc/conditio.hxx +++ b/sc/inc/conditio.hxx @@ -546,15 +546,14 @@ private: class ScColorFormatCache final : public SvtListener { -private: - ScDocument& mrDoc; - public: explicit ScColorFormatCache(ScDocument& rDoc, const ScRangeList& rRanges); virtual ~ScColorFormatCache() override; void Notify( const SfxHint& rHint ) override; + ScDocument& mrDoc; + ScRangeList maRanges; std::vector<double> maValues; }; diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx index 97b1c73b0e08..dfbeed483166 100644 --- a/sc/source/core/data/conditio.cxx +++ b/sc/source/core/data/conditio.cxx @@ -1740,7 +1740,7 @@ void ScCondDateFormatEntry::endRendering() } ScColorFormatCache::ScColorFormatCache(ScDocument& rDoc, const ScRangeList& rRanges) : - mrDoc(rDoc) + mrDoc(rDoc), maRanges(rRanges) { if (mrDoc.IsClipOrUndo()) return; @@ -2144,8 +2144,29 @@ void ScConditionalFormat::CalcAll() } } +/// whether rRlist1 contains rRlist2. +static bool lcl_RangeContains(const ScRangeList& rRlist1, const ScRangeList& rRlist2) +{ + for (const auto& rRange: rRlist2) + { + if (!rRlist1.Contains(rRange)) + return false; + } + + return true; +} + void ScConditionalFormat::ResetCache() const { + if (mpCache && mpDoc == &mpCache->mrDoc && lcl_RangeContains(mpCache->maRanges, maRanges)) + { + // Cache is already listening to a super-set of maRanges. + // Don't shrink the range of mpCache yet as it is expensive. + // Just clear the cache. + mpCache->maValues.clear(); + return; + } + if (!maRanges.empty() && mpDoc) mpCache = std::make_unique<ScColorFormatCache>(*mpDoc, maRanges); else
