sw/qa/extras/ooxmlimport/data/tdf152200-bad_fldChar_end.docx |binary sw/qa/extras/ooxmlimport/ooxmlimport2.cxx | 6 + writerfilter/source/dmapper/DomainMapper_Impl.cxx | 39 ++++++----- 3 files changed, 29 insertions(+), 16 deletions(-)
New commits: commit bcc5f7f8d059a1add749a0e10ef1113e51dbab50 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Thu Nov 24 15:05:43 2022 +0300 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri Nov 25 09:37:51 2022 +0100 tdf#152200: tolerate begin/end fldChar context mismatch We generate such files currently. Fixing that will be another commit. Change-Id: I788501e346cba63c08a767c0e05e063bc1172089 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143223 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> (cherry picked from commit 9a7945f36ce95a48e0d525bc444e722b9ec5c452) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143171 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> diff --git a/sw/qa/extras/ooxmlimport/data/tdf152200-bad_fldChar_end.docx b/sw/qa/extras/ooxmlimport/data/tdf152200-bad_fldChar_end.docx new file mode 100644 index 000000000000..7f77c8d66b2b Binary files /dev/null and b/sw/qa/extras/ooxmlimport/data/tdf152200-bad_fldChar_end.docx differ diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx index afdb0cc27ce1..bf9e298ea4d2 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx @@ -937,6 +937,12 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf126426) } } +CPPUNIT_TEST_FIXTURE(Test, testTdf152200) +{ + load(mpTestDocumentPath, "tdf152200-bad_fldChar_end.docx"); + // Should not crash/hang because of wrong placement of ending fldChar +} + // tests should only be added to ooxmlIMPORT *if* they fail round-tripping in ooxmlEXPORT CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index c97e7229e829..2f7fda4b1388 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -7287,7 +7287,6 @@ void DomainMapper_Impl::PopFieldContext() { try { - uno::Reference< text::XTextCursor > xCrsr = xTextAppend->createTextCursorByRange(pContext->GetStartRange()); uno::Reference< text::XTextContent > xToInsert( pContext->GetTOC(), uno::UNO_QUERY ); if( xToInsert.is() ) { @@ -7349,30 +7348,38 @@ void DomainMapper_Impl::PopFieldContext() } else { + uno::Reference< text::XTextCursor > xCrsr = xTextAppend->createTextCursorByRange(pContext->GetStartRange()); FormControlHelper::Pointer_t pFormControlHelper(pContext->getFormControlHelper()); if (pFormControlHelper) { - uno::Reference< text::XFormField > xFormField( pContext->GetFormField() ); - assert(xCrsr.is()); - if (pFormControlHelper->hasFFDataHandler()) + // xCrsr may be empty e.g. when pContext->GetStartRange() is outside of + // xTextAppend, like when a field started in a parent paragraph is being + // closed inside an anchored text box. It could be possible to throw an + // exception here, and abort import, but Word tolerates such invalid + // input, so it makes sense to do the same (tdf#152200) + if (xCrsr.is()) { - xToInsert.set(xFormField, uno::UNO_QUERY); - if (xFormField.is() && xToInsert.is()) + uno::Reference< text::XFormField > xFormField(pContext->GetFormField()); + if (pFormControlHelper->hasFFDataHandler()) { - PopFieldmark(m_aTextAppendStack, xCrsr, - pContext->GetFieldId()); - pFormControlHelper->processField( xFormField ); + xToInsert.set(xFormField, uno::UNO_QUERY); + if (xFormField.is() && xToInsert.is()) + { + PopFieldmark(m_aTextAppendStack, xCrsr, + pContext->GetFieldId()); + pFormControlHelper->processField(xFormField); + } + else + { + pFormControlHelper->insertControl(xCrsr); + } } else { - pFormControlHelper->insertControl(xCrsr); - } - } - else - { - PopFieldmark(m_aTextAppendStack, xCrsr, + PopFieldmark(m_aTextAppendStack, xCrsr, pContext->GetFieldId()); - uno::Reference<lang::XComponent>(xFormField, uno::UNO_QUERY_THROW)->dispose(); // presumably invalid? + uno::Reference<lang::XComponent>(xFormField, uno::UNO_QUERY_THROW)->dispose(); // presumably invalid? + } } } else if (!pContext->GetHyperlinkURL().isEmpty() && xCrsr.is())