diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2024-12-17 16:02:48 +0100 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2024-12-19 11:32:15 +0100 |
commit | 5cba5e59da2102607048025a54a34aa6145dd30c (patch) | |
tree | 85fbdd143799c17ccc12106a32437e2d359628df | |
parent | 2240c2eb36dee04fdf3b8ddd54a482651c4bf5ca (diff) |
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/+/178703
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
(cherry picked from commit a7a81b6fbe37af938ce461e790fac517be032317)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178718
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
-rw-r--r-- | editeng/qa/editeng/editeng.cxx | 33 | ||||
-rw-r--r-- | editeng/source/editeng/impedit4.cxx | 14 |
2 files changed, 42 insertions, 5 deletions
diff --git a/editeng/qa/editeng/editeng.cxx b/editeng/qa/editeng/editeng.cxx index 71a99414e4aa..7358bca5dd59 100644 --- a/editeng/qa/editeng/editeng.cxx +++ b/editeng/qa/editeng/editeng.cxx @@ -10,6 +10,7 @@ #include <test/bootstrapfixture.hxx> #include <editeng/editeng.hxx> +#include <editeng/wghtitem.hxx> #include <sfx2/app.hxx> #include <svtools/parrtf.hxx> #include <svtools/rtftoken.h> @@ -124,6 +125,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 e6730a64ef86..6c83f2a4e5e2 100644 --- a/editeng/source/editeng/impedit4.cxx +++ b/editeng/source/editeng/impedit4.cxx @@ -464,15 +464,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(); |