summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2024-12-17 16:02:48 +0100
committerXisco Fauli <xiscofauli@libreoffice.org>2024-12-19 11:32:15 +0100
commit5cba5e59da2102607048025a54a34aa6145dd30c (patch)
tree85fbdd143799c17ccc12106a32437e2d359628df
parent2240c2eb36dee04fdf3b8ddd54a482651c4bf5ca (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.cxx33
-rw-r--r--editeng/source/editeng/impedit4.cxx14
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();