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

Reply via email to