sc/source/filter/xml/xmlexprt.cxx |    7 ++++++-
 sc/source/ui/view/viewfun5.cxx    |    9 +++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

New commits:
commit 5852a98f33000247107808fcc54306343689008a
Author:     Mike Kaganski <[email protected]>
AuthorDate: Tue Feb 3 18:53:38 2026 +0500
Commit:     Balazs Varga <[email protected]>
CommitDate: Wed Mar 4 08:56:41 2026 +0100

    tdf#170567: Avoid resetting destination document's data
    
    When clipboard document is set up in Biff12 paste code, a call to
    ScDocument::ResetClip is required. In nearby code, the destination
    document is used for that, which was why I did the same.
    
    But it turned out, that following call to SfxObjectShell::DoLoad
    called ScDocShell::InitNew, and there some shared pooled items got
    reset, including an ScPatternAttr used for default attributes. It
    included clearing style pattern's, and that change affected target
    document. Then, in export, the document's formatting ranges were
    collected in ScXMLExport::AddStyleFromCells, which checked direct
    properties of each range. The document's default ScPatternAttr was
    missing style, and ScCellRangesBase::GetOnePropertyState returned
    PropertyState_AMBIGUOUS_VALUE, and ScXMLExport::AddStyleFromCells
    got empty aPropStates, without style name (which is documented to
    not have a default, so it must always be present). In the end, the
    default-formatted document ranges didn't create respective entries
    in ScRowFormatRanges::aRowFormatRanges.
    
    Then in ScXMLExport::ExportFormatRanges, trying to export formats
    for the first (default-formatted) rows, calls to GetFormatRanges
    left pRowFormatRanges empty, meaning that nMaxRows were 0, and no
    advance happened in the loop -> hang. (Maybe a similar situation
    caused commit b36a8a532b3ee6521d80277cb32a6936c0b09320 - busy loop
    seen on ods export attempt, 2023-12-07.)
    
    This change avoids unintended modification of the target document,
    by creating a fake "source" document to use in ResetClip.
    
    Also, this changes OSL_ENSURE to an assert, and fails export with
    XMLERROR_CANCEL | XMLERROR_FLAG_SEVERE error, when nMaxRows is 0
    in ScXMLExport::ExportFormatRanges - same as what the mentioned
    commit b36a8a532b3ee6521d80277cb32a6936c0b09320 did in an adjacent
    branch.
    
    cherry-pick from: 17fb6ff6d163c7037e1c66d28c229473ab77717e
    (tdf#170567: Avoid resetting destination document's data)
    Original unit test was not added in this cherry-pick.
    
    Change-Id: I3839ef0d2cb42d33cfc0b36b329658e159022586
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198609
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200892
    Tested-by: allotropia jenkins <[email protected]>
    Reviewed-by: Balazs Varga <[email protected]>

diff --git a/sc/source/filter/xml/xmlexprt.cxx 
b/sc/source/filter/xml/xmlexprt.cxx
index 5a93a64cda43..a6adb69c2c18 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -1578,7 +1578,12 @@ void ScXMLExport::ExportFormatRanges(const sal_Int32 
nStartCol, const sal_Int32
             {
                 pCellStyles->GetFormatRanges(0, 
pSharedData->GetLastColumn(nSheet), nStartRow + nRows, nSheet, 
pRowFormatRanges.get());
                 sal_Int32 nMaxRows = pRowFormatRanges->GetMaxRows();
-                OSL_ENSURE(nMaxRows, "something went wrong");
+                assert(nMaxRows && "ScXMLExport::ExportFormatRanges cannot 
make progress with zero rows, something went wrong");
+                if (!nMaxRows)
+                {
+                    SetError(XMLERROR_CANCEL | XMLERROR_FLAG_SEVERE, {});
+                    break;
+                }
                 if (nMaxRows >= nTotalRows - nRows)
                 {
                     OpenRow(nSheet, nStartRow + nRows, nTotalRows - nRows, 
aRowAttr);
diff --git a/sc/source/ui/view/viewfun5.cxx b/sc/source/ui/view/viewfun5.cxx
index 99e99457f77d..563c4749b0d0 100644
--- a/sc/source/ui/view/viewfun5.cxx
+++ b/sc/source/ui/view/viewfun5.cxx
@@ -601,11 +601,15 @@ bool ScViewFunc::PasteDataFormat( SotClipboardFormatId 
nFormatId,
             SfxFilterMatcher 
aMatcher(ScDocShell::Factory().GetFilterContainer()->GetName());
             if (auto pFilter = 
aMatcher.GetFilter4ClipBoardId(SotClipboardFormatId::BIFF_12))
             {
+                // Do not use rDoc as "source" in the call to ResetClip: 
DoLoad would call InitNew,
+                // which resets many pooled items, shared between source and 
clipboard documents,
+                // which modifies the source. We don't want that, so use a 
temporary document.
+                ScDocument aTmpClipSrc(SCDOCMODE_DOCUMENT);
                 ScDocShellRef pClipShell(new ScDocShell(SfxModelFlags::NONE, 
SCDOCMODE_CLIP));
                 SCTAB nSrcTab = 0;
-                pClipShell->GetDocument().ResetClip(pDoc, nSrcTab);
+                pClipShell->GetDocument().ResetClip(&aTmpClipSrc, nSrcTab);
                 auto pMed = std::make_unique<SfxMedium>();
-                pMed->GetItemSet()->Put(SfxUnoAnyItem(SID_INPUTSTREAM, 
uno::Any(xStm)));
+                pMed->GetItemSet()->Put( SfxUnoAnyItem( SID_INPUTSTREAM, 
uno::Any( xStm ) ) );
                 pMed->SetFilter(pFilter);
 
                 if (pClipShell->DoLoad(pMed.release()))
@@ -614,6 +618,7 @@ bool ScViewFunc::PasteDataFormat( SotClipboardFormatId 
nFormatId,
                                        bAllowDialogs);
                     bRet = true;
                 }
+                pClipShell->DoClose();
             }
         }
     }

Reply via email to