editeng/qa/editeng/editeng.cxx | 32 ++++++++++++++++++++++++++++++++ editeng/source/editeng/impedit4.cxx | 14 +++++++++----- 2 files changed, 41 insertions(+), 5 deletions(-)
New commits: commit 4eac1d004898a2063b21a83a7e5785e22c50ba8a Author: Miklos Vajna <[email protected]> AuthorDate: Tue Dec 17 16:02:48 2024 +0100 Commit: Caolán McNamara <[email protected]> CommitDate: Tue Dec 17 17:45:51 2024 +0100 tdf#164359 editeng RTF export: track unused parent styles recursively Start edit mode for the shape in the document, double-click on a word which has a "level 2" bullet associated with it -> crash. This is a regression from c8b607b7c0096c58dc5187262bf0133dee728d50 (tdf#163883 editeng RTF export: fix broken offsets into the para style table, 2024-11-19), the direct cause is that ImpEditEngine::WriteRTF() maps all style pointers to a style ID and once we write the parent property in the style table, we unconditionally dereference our search result, because we know all styles should be in that map. The root of the problem seems to be that once parent styles are marked as used for the "only write used styles for the clipboard" case, those parents themselves can have parents, and we didn't mark those as used. Combined with the unconditional dereference, this leads to a crash. Fix this by walking up the parent chain till we get no parent. This assumes that importers create a valid document model, so there can't be loops while walking the parent chain. If that would be a problem in practice, we could check for that in the future. Change-Id: I4b416e78f26bf455040d95ee8ed220cfe870e33a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178677 Reviewed-by: Caolán McNamara <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> Tested-by: Caolán McNamara <[email protected]> diff --git a/editeng/qa/editeng/editeng.cxx b/editeng/qa/editeng/editeng.cxx index 5a4ed4d051cc..6c44c557d9b3 100644 --- a/editeng/qa/editeng/editeng.cxx +++ b/editeng/qa/editeng/editeng.cxx @@ -128,6 +128,38 @@ CPPUNIT_TEST_FIXTURE(Test, testRTFStyleExportReferToStyle) // i.e. \s2 was used to refer to \s1, so the paragraph style was lost. CPPUNIT_ASSERT_EQUAL(xReader->m_aStyleValues[0], xReader->m_aStyleValues[1]); } + +CPPUNIT_TEST_FIXTURE(Test, testRTFStyleExportParentRecursive) +{ + // Given a document with text that has a paragraph style with a parent that itself has a parent: + EditEngine aEditEngine(mpItemPool.get()); + rtl::Reference<SfxStyleSheetPool> xStyles(new SfxStyleSheetPool(*mpItemPool)); + xStyles->Make("mystyle1", SfxStyleFamily::Para); + xStyles->Make("mystyle2", SfxStyleFamily::Para); + xStyles->Make("mystyle3", SfxStyleFamily::Para); + auto pStyle1 = static_cast<SfxStyleSheet*>(xStyles->Find("mystyle1", SfxStyleFamily::Para)); + auto pStyle2 = static_cast<SfxStyleSheet*>(xStyles->Find("mystyle2", SfxStyleFamily::Para)); + pStyle2->SetParent(pStyle1->GetName()); + auto pStyle3 = static_cast<SfxStyleSheet*>(xStyles->Find("mystyle3", SfxStyleFamily::Para)); + pStyle3->SetParent(pStyle2->GetName()); + pStyle3->GetItemSet().SetRanges(svl::Items<WEIGHT_BOLD, EE_CHAR_WEIGHT>); + SvxWeightItem aItem(WEIGHT_BOLD, EE_CHAR_WEIGHT); + pStyle3->GetItemSet().Put(aItem); + aEditEngine.SetStyleSheetPool(xStyles.get()); + OUString aText = u"mytest"_ustr; + aEditEngine.SetText(aText); + aEditEngine.SetStyleSheet(0, pStyle3); + + // When copying to the clipboard as RTF: + // Without the accompanying fix in place, this test would have crashed here: + uno::Reference<datatransfer::XTransferable> xData + = aEditEngine.CreateTransferable(ESelection(0, 0, 0, aText.getLength())); + + // Then make sure we produce RTF and not crash: + auto pData = dynamic_cast<EditDataObject*>(xData.get()); + SvMemoryStream& rStream = pData->GetRTFStream(); + CPPUNIT_ASSERT_GREATER(static_cast<sal_uInt64>(0), rStream.remainingSize()); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx index 1a5685256536..17d3c8cd7495 100644 --- a/editeng/source/editeng/impedit4.cxx +++ b/editeng/source/editeng/impedit4.cxx @@ -443,15 +443,19 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel, bool bCl aUsedParagraphStyles.insert(pParaStyle); - const OUString& rParent = pParaStyle->GetParent(); - if (!rParent.isEmpty()) + // Collect parents of the style recursively. + OUString aParent = pParaStyle->GetParent(); + while (!aParent.isEmpty()) { auto pParent = static_cast<SfxStyleSheet*>( - GetStyleSheetPool()->Find(rParent, pParaStyle->GetFamily())); - if (pParent) + GetStyleSheetPool()->Find(aParent, pParaStyle->GetFamily())); + if (!pParent) { - aUsedParagraphStyles.insert(pParent); + break; } + + aUsedParagraphStyles.insert(pParent); + aParent = pParent->GetParent(); } const OUString& rFollow = pParaStyle->GetFollow();
