filter/source/svg/svgexport.cxx | 13 ++++- sd/source/ui/unoidl/unomodel.cxx | 13 +++-- sw/source/uibase/uno/unotxdoc.cxx | 7 +- ucb/source/ucp/webdav-curl/CurlUri.cxx | 4 + xmloff/qa/unit/data/listRestartAfterBreak.fodt | 25 ++++++++++ xmloff/qa/unit/text.cxx | 61 +++++++++++++++++++++++++ xmloff/source/text/txtparae.cxx | 33 ++++++------- 7 files changed, 128 insertions(+), 28 deletions(-)
New commits: commit c855acaa4a026713d9b24569faaf6815f6435734 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Mon Jun 12 20:51:41 2023 +0100 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Fri Jun 16 09:29:46 2023 +0200 turn off undo while creating SdrGrafObj in svg export filter otherwise in the SdrGrafObj ctor onGraphicChanged is called which can put us into the undo stack. presumably as we haven't finished constructing yet the ref count isn't right ==20597==ERROR: AddressSanitizer: heap-use-after-free instdir/program/libmergedlo.so SdrObject::SetTitle(rtl::OUString const&) libreoffice/svx/source/svdraw/svdobj.cxx:811 instdir/program/libmergedlo.so SdrGrafObj::onGraphicChanged() libreoffice/svx/source/svdraw/svdograf.cxx:172 instdir/program/libmergedlo.so SdrGrafObj libreoffice/svx/source/svdraw/svdograf.cxx:272 instdir/program/../program/libsvgfilterlo.so SVGFilter::implExportWriterTextGraphic(com::sun::star::uno::Reference<com::sun::star::view::XSelectionSupplier> const&) libreoffice/filter/source/svg/svgexport.cxx:863 instdir/program/../program/libsvgfilterlo.so SVGFilter::filterWriterOrCalc(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) libreoffice/filter/source/svg/svgfilter.cxx:590 instdir/program/../program/libsvgfilterlo.so SVGFilter::filter(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) libreoffice/filter/source/svg/svgfilter.cxx:135 instdir/program/libmergedlo.so SfxObjectShell::ExportTo(SfxMedium&) libreoffice/sfx2/source/doc/objstor.cxx:2494 freed by thread T0 here: instdir/program/libmergedlo.so ~SdrUndoObj libreoffice/svx/source/svdraw/svdundo.cxx:203 previously allocated by thread T0 here: instdir/program/libuno_sal.so.3 rtl_allocateMemory libreoffice/sal/rtl/alloc_global.cxx:38 instdir/program/../program/libsvgfilterlo.so cppu::OWeakObject::operator new(unsigned long) libreoffice/include/cppuhelper/weak.hxx:89 instdir/program/../program/libsvgfilterlo.so SVGFilter::filterWriterOrCalc(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) libreoffice/filter/source/svg/svgfilter.cxx:590 instdir/program/../program/libsvgfilterlo.so SVGFilter::filter(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) libreoffice/filter/source/svg/svgfilter.cxx:135 instdir/program/libmergedlo.so SfxObjectShell::ExportTo(SfxMedium&) libreoffice/sfx2/source/doc/objstor.cxx:2494 Change-Id: Ife225b4250fda53514110b176f35e5278d23f287 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152935 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> (cherry picked from commit bd4d9056cbc40af6b097727d3649ff1e5da09a53) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152989 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx index a8afae2c6461..5e63db81b70c 100644 --- a/filter/source/svg/svgexport.cxx +++ b/filter/source/svg/svgexport.cxx @@ -44,6 +44,7 @@ #include <editeng/flditem.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/propertyvalue.hxx> +#include <comphelper/scopeguard.hxx> #include <comphelper/sequenceashashmap.hxx> #include <i18nlangtag/lang.h> #include <svl/numformat.hxx> @@ -860,7 +861,17 @@ bool SVGFilter::implExportWriterTextGraphic( const Reference< view::XSelectionSu if(pSvxDrawPage == nullptr || pSvxDrawPage->GetSdrPage() == nullptr) return false; - rtl::Reference<SdrGrafObj> pGraphicObj = new SdrGrafObj(pSvxDrawPage->GetSdrPage()->getSdrModelFromSdrPage(), aGraphic, tools::Rectangle( aPos, aSize )); + SdrModel& rModel = pSvxDrawPage->GetSdrPage()->getSdrModelFromSdrPage(); + const bool bUndoEnable = rModel.IsUndoEnabled(); + if (bUndoEnable) + rModel.EnableUndo(false); + comphelper::ScopeGuard guard([bUndoEnable, &rModel]() { + // restore when leaving + if (bUndoEnable) + rModel.EnableUndo(false); + }); + + rtl::Reference<SdrGrafObj> pGraphicObj = new SdrGrafObj(rModel, aGraphic, tools::Rectangle( aPos, aSize )); uno::Reference< drawing::XShape > xShape = GetXShapeForSdrObject(pGraphicObj.get()); uno::Reference< XPropertySet > xShapePropSet(xShape, uno::UNO_QUERY); xShapePropSet->setPropertyValue("Graphic", uno::Any(xGraphic)); commit fe0c1dadc56d72eda1bc699de573ec52e17cbbce Author: Luigi Iucci <luigi.iu...@collabora.com> AuthorDate: Fri May 26 11:49:59 2023 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Fri Jun 16 09:29:42 2023 +0200 sd: fix crash deleting 2 slides during paintTile pPageView was null in SdXImpressDocument::paintTile while trying to paint form controls, which is a corner case in most cases then we skip painting in order to avoid a crash Change-Id: I6c166035220c058fac276f2b7746a8ebc9651f81 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152379 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit c183934835a6ab5e74643a671b65e9468592d216) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153079 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index dd2c897b4930..e05aee0f91c0 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -2306,11 +2306,14 @@ void SdXImpressDocument::paintTile( VirtualDevice& rDevice, // Draw Form controls SdrView* pDrawView = pViewSh->GetDrawView(); SdrPageView* pPageView = pDrawView->GetSdrPageView(); - SdrPage* pPage = pPageView->GetPage(); - ::sd::Window* pActiveWin = pViewSh->GetActiveWindow(); - ::tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight)); - Size aOutputSize(nOutputWidth, nOutputHeight); - LokControlHandler::paintControlTile(pPage, pDrawView, *pActiveWin, rDevice, aOutputSize, aTileRect); + if (pPageView != nullptr) + { + SdrPage* pPage = pPageView->GetPage(); + ::sd::Window* pActiveWin = pViewSh->GetActiveWindow(); + ::tools::Rectangle aTileRect(Point(nTilePosX, nTilePosY), Size(nTileWidth, nTileHeight)); + Size aOutputSize(nOutputWidth, nOutputHeight); + LokControlHandler::paintControlTile(pPage, pDrawView, *pActiveWin, rDevice, aOutputSize, aTileRect); + } comphelper::LibreOfficeKit::setTiledPainting(false); } commit 7c3c3e2bc1f214b00d460e8825865d5eca7bfd7e Author: Stephan Bergmann <sberg...@redhat.com> AuthorDate: Wed Jun 14 16:05:54 2023 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Fri Jun 16 09:29:38 2023 +0200 ooo#41037 Reject URLs containing unencoded NUL characters Change-Id: I45bbd342734f190ce918b610441ca911a47830b4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153062 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sberg...@redhat.com> (cherry picked from commit 977878814a3573627026e31edb8a51c8f30c8a0c) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153086 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/ucb/source/ucp/webdav-curl/CurlUri.cxx b/ucb/source/ucp/webdav-curl/CurlUri.cxx index c5440423a2db..3ee218d5aca3 100644 --- a/ucb/source/ucp/webdav-curl/CurlUri.cxx +++ b/ucb/source/ucp/webdav-curl/CurlUri.cxx @@ -115,6 +115,10 @@ CurlUri::CurlUri(::std::u16string_view const rURI) } // use curl to parse the URI, to get a consistent interpretation + if (rURI.find(u'\0') != std::u16string_view::npos) + { + throw DAVException(DAVException::DAV_INVALID_ARG); + } OString const utf8URI(OUStringToOString(rURI, RTL_TEXTENCODING_UTF8)); auto uc = curl_url_set(m_pUrl.get(), CURLUPART_URL, utf8URI.getStr(), 0); if (uc != CURLUE_OK) commit f18499c7e722f3649bd6999fdd756819c81e3d3d Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Thu Jun 15 10:34:41 2023 +0300 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Fri Jun 16 09:29:34 2023 +0200 ODF export: simplify restart handling to skip list id where possible This continues to minimize cases where random ids are written, helping to make the output more deterministic; it builds upon commits 8f48f91009caa86d896f247059874242ed18bf39 (ODT export: omit unreferenced <text:list xml:id="...">, 2022-03-10), and 82bbf63582bdf28e7918e58ebf6657a9144bc9f3 (tdf#155823: Improve the check if the list id is not required, 2023-06-14). The previous code used to write 'text:continue-list' when the list is restarted. It is unnecessary when there is no other condition requiring such a reference (like style change, or interleaving lists); so relax the conditions allowing to put simple 'text:continue-numbering="true"'. This also allows to simplify a bit the code around 'ShouldSkipListId'. Change-Id: Idf8be455953d08fd578266bda22f3a55d7b9ee23 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153104 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> (cherry picked from commit 7db19db341608ba2059543a3c8d61cd458470602) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153135 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx index 51c777ee47da..e68d468e3fff 100644 --- a/sw/source/uibase/uno/unotxdoc.cxx +++ b/sw/source/uibase/uno/unotxdoc.cxx @@ -1974,8 +1974,8 @@ Any SwXTextDocument::getPropertyValue(const OUString& rPropertyName) // A hack to avoid writing random list ids to ODF when they are not referred later // see XMLTextParagraphExport::DocumentListNodes ctor - // Sequence of nodes, each of them represented by four-element sequence: - // [ index, styleIntPtr, list_id, isRestart ] + // Sequence of nodes, each of them represented by three-element sequence: + // [ index, styleIntPtr, list_id ] std::vector<css::uno::Sequence<css::uno::Any>> nodes; const SwDoc& rDoc = *m_pDocShell->GetDoc(); @@ -1989,9 +1989,8 @@ Any SwXTextDocument::getPropertyValue(const OUString& rPropertyName) { css::uno::Any index(pTextNode->GetIndex().get()); css::uno::Any list_id(pTextNode->GetListId()); - css::uno::Any isRestart(pTextNode->IsListRestart()); - nodes.push_back({ index, styleIntPtr, list_id, isRestart }); + nodes.push_back({ index, styleIntPtr, list_id }); } } return css::uno::Any(comphelper::containerToSequence(nodes)); diff --git a/xmloff/qa/unit/data/listRestartAfterBreak.fodt b/xmloff/qa/unit/data/listRestartAfterBreak.fodt new file mode 100644 index 000000000000..7ae5c84d7060 --- /dev/null +++ b/xmloff/qa/unit/data/listRestartAfterBreak.fodt @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:body> + <office:text> + <text:list text:style-name="Numbering 123"> + <text:list-item> + <text:p>Item1</text:p> + </text:list-item> + </text:list> + <text:p/> + <text:list text:continue-numbering="true" text:style-name="Numbering 123"> + <text:list-item> + <text:p>Item2</text:p> + </text:list-item> + </text:list> + <text:p/> + <text:list text:continue-numbering="true" text:style-name="Numbering 123"> + <text:list-item text:start-value="1"> + <text:p>Item3 (restarted)</text:p> + </text:list-item> + </text:list> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/xmloff/qa/unit/text.cxx b/xmloff/qa/unit/text.cxx index bff3f8b14821..abd4a0e07dea 100644 --- a/xmloff/qa/unit/text.cxx +++ b/xmloff/qa/unit/text.cxx @@ -347,6 +347,67 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testListIdState) CPPUNIT_ASSERT(!id.isEmpty()); } +CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testListIdOnRestart) +{ + // Test that a restart of a continued list, by itself, does not introduce a unneeded xml:id + // and text:continue-list, but uses text:continue-numbering, and is imported correctly. + + // Given a document with a list with a restart after break: + loadFromURL(u"listRestartAfterBreak.fodt"); + + auto xTextDocument(mxComponent.queryThrow<css::text::XTextDocument>()); + auto xParaEnumAccess(xTextDocument->getText().queryThrow<css::container::XEnumerationAccess>()); + auto xParaEnum(xParaEnumAccess->createEnumeration()); + + auto xPara(xParaEnum->nextElement().queryThrow<beans::XPropertySet>()); + auto aActual(xPara->getPropertyValue("ListLabelString").get<OUString>()); + CPPUNIT_ASSERT_EQUAL(OUString("1."), aActual); + OUString list_id = xPara->getPropertyValue("ListId").get<OUString>(); + xParaEnum->nextElement(); // Skip empty intermediate paragraph + xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY_THROW); + aActual = xPara->getPropertyValue("ListLabelString").get<OUString>(); + CPPUNIT_ASSERT_EQUAL(OUString("2."), aActual); + CPPUNIT_ASSERT_EQUAL(list_id, xPara->getPropertyValue("ListId").get<OUString>()); + xParaEnum->nextElement(); // Skip empty intermediate paragraph + xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY); + aActual = xPara->getPropertyValue("ListLabelString").get<OUString>(); + // Check that restart was applied correctly, with simple 'text:continue-numbering="true"' + CPPUNIT_ASSERT_EQUAL(OUString("1."), aActual); + CPPUNIT_ASSERT_EQUAL(list_id, xPara->getPropertyValue("ListId").get<OUString>()); + + // When storing that document as ODF: + saveAndReload("writer8"); + + xTextDocument.set(mxComponent, uno::UNO_QUERY_THROW); + xParaEnumAccess.set(xTextDocument->getText(), uno::UNO_QUERY_THROW); + xParaEnum.set(xParaEnumAccess->createEnumeration()); + + xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY_THROW); + aActual = xPara->getPropertyValue("ListLabelString").get<OUString>(); + CPPUNIT_ASSERT_EQUAL(OUString("1."), aActual); + list_id = xPara->getPropertyValue("ListId").get<OUString>(); + xParaEnum->nextElement(); // Skip empty intermediate paragraph + xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY_THROW); + aActual = xPara->getPropertyValue("ListLabelString").get<OUString>(); + CPPUNIT_ASSERT_EQUAL(OUString("2."), aActual); + CPPUNIT_ASSERT_EQUAL(list_id, xPara->getPropertyValue("ListId").get<OUString>()); + xParaEnum->nextElement(); // Skip empty intermediate paragraph + xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY_THROW); + aActual = xPara->getPropertyValue("ListLabelString").get<OUString>(); + CPPUNIT_ASSERT_EQUAL(OUString("1."), aActual); + CPPUNIT_ASSERT_EQUAL(list_id, xPara->getPropertyValue("ListId").get<OUString>()); + + // Then make sure that no xml:id="..." attribute is written, even in restarted case: + xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); + CPPUNIT_ASSERT(pXmlDoc); + assertXPath(pXmlDoc, "//text:list", 3); + assertXPathNoAttribute(pXmlDoc, "//text:list[1]", "id"); + assertXPathNoAttribute(pXmlDoc, "//text:list[2]", "id"); + assertXPathNoAttribute(pXmlDoc, "//text:list[3]", "id"); + assertXPathNoAttribute(pXmlDoc, "//text:list[3]", "continue-list"); + assertXPath(pXmlDoc, "//text:list[3]", "continue-numbering", "true"); +} + CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testClearingBreakExport) { // Given a document with a clearing break: diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx index c78c504bfa50..34e12aec02b2 100644 --- a/xmloff/source/text/txtparae.cxx +++ b/xmloff/source/text/txtparae.cxx @@ -1104,8 +1104,7 @@ void XMLTextParagraphExport::exportListChange( mpTextListsHelper->GetListStyleOfLastProcessedList() && // Inconsistent behavior regarding lists (#i92811#) sContinueListId == - mpTextListsHelper->GetLastProcessedListId() && - !rNextInfo.IsRestart() ) + mpTextListsHelper->GetLastProcessedListId() ) { GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_CONTINUE_NUMBERING, @@ -1120,15 +1119,15 @@ void XMLTextParagraphExport::exportListChange( XML_CONTINUE_LIST, sContinueListId ); } + } - if ( rNextInfo.IsRestart() && - ( nListLevelsToBeOpened != 1 || - !rNextInfo.HasStartValue() ) ) - { - bRestartNumberingAtContinuedList = true; - nRestartValueForContinuedList = - rNextInfo.GetListLevelStartValue(); - } + if ( rNextInfo.IsRestart() && + ( nListLevelsToBeOpened != 1 || + !rNextInfo.HasStartValue() ) ) + { + bRestartNumberingAtContinuedList = true; + nRestartValueForContinuedList = + rNextInfo.GetListLevelStartValue(); } mpTextListsHelper->KeepListAsProcessed( sNewListId, @@ -1804,12 +1803,11 @@ struct XMLTextParagraphExport::DocumentListNodes sal_Int32 index; // see SwNode::GetIndex and SwNodeOffset sal_uInt64 style_id; // actually a pointer to NumRule OUString list_id; - bool isRestart; }; std::vector<NodeData> docListNodes; DocumentListNodes(const css::uno::Reference<css::frame::XModel>& xModel) { - // Sequence of nodes, each of them represented by four-element sequence, + // Sequence of nodes, each of them represented by three-element sequence, // corresponding to NodeData members css::uno::Sequence<css::uno::Sequence<css::uno::Any>> nodes; if (auto xPropSet = xModel.query<css::beans::XPropertySet>()) @@ -1828,9 +1826,9 @@ struct XMLTextParagraphExport::DocumentListNodes docListNodes.reserve(nodes.getLength()); for (const auto& node : nodes) { - assert(node.getLength() == 4); + assert(node.getLength() == 3); docListNodes.push_back({ node[0].get<sal_Int32>(), node[1].get<sal_uInt64>(), - node[2].get<OUString>(), node[3].get<bool>() }); + node[2].get<OUString>() }); } std::sort(docListNodes.begin(), docListNodes.end(), @@ -1884,10 +1882,9 @@ struct XMLTextParagraphExport::DocumentListNodes if (it->index + 1 != next->index) { // we have a gap before the next node with the same list and style, - // with no other lists in between. There will be a continuation; - // in case of restart, there will be a reference to the id; - // otherwise, there will be simple 'text:continue-numbering="true"'. - return !next->isRestart; + // with no other lists in between. There will be a continuation with a + // simple 'text:continue-numbering="true"'. + return true; } it = next; // walk through adjacent nodes of the same list }