fix a regression crash from commit 5082d50

The commit generated crashes in the crashtest documents
7711 bugtrackers/docx/fdo78333-1.docx and
695 forums/docx/forum-mso-en-4096.docx.
This was due to "m_xFieldStartRange", the start of the text
portion of the block SDT, being recorded too early. This led to
including characters that shouldn't be there in the generated
content control.
This patch moves the calls to setFieldStartRange to just before
the first appendTextPortion call.

Change-Id: I7230346fee9a37ebac70beb9bcafd9d7b612eb00
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159816
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/writerfilter/qa/cppunittests/dmapper/DomainMapper.cxx b/writerfilter/qa/cppunittests/dmapper/DomainMapper.cxx
index 7cafcd1..ec771ba 100644
--- a/writerfilter/qa/cppunittests/dmapper/DomainMapper.cxx
+++ b/writerfilter/qa/cppunittests/dmapper/DomainMapper.cxx
@@ -149,6 +149,12 @@ CPPUNIT_TEST_FIXTURE(Test, testSdtBlockText)
    xContentControlProps->getPropertyValue("Alias") >>= aAlias;
    CPPUNIT_ASSERT_EQUAL(OUString("myalias"), aAlias);
}

CPPUNIT_TEST_FIXTURE(Test, testFdo78333)
{
    // just care that it doesn't crash/assert
    loadFromURL(u"fdo78333-1-minimized.docx");
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/qa/cppunittests/dmapper/data/fdo78333-1-minimized.docx b/writerfilter/qa/cppunittests/dmapper/data/fdo78333-1-minimized.docx
new file mode 100644
index 0000000..0c4a5bc
--- /dev/null
+++ b/writerfilter/qa/cppunittests/dmapper/data/fdo78333-1-minimized.docx
Binary files differ
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index e2ef4ec..70fc782 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -1192,9 +1192,6 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
                m_pImpl->PushSdt();
                break;
            }
            if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText
                && GetCurrentTextRange().is())
                m_pImpl->m_pSdtHelper->setFieldStartRange(GetCurrentTextRange()->getEnd());
            m_pImpl->SetSdt(true);
        }
        break;
@@ -4229,7 +4226,6 @@ void DomainMapper::lcl_utext(const sal_Unicode *const data_, size_t len)
        {
            m_pImpl->m_pSdtHelper->createPlainTextControl();
            finishParagraph();
            m_pImpl->m_pSdtHelper->setFieldStartRange(GetCurrentTextRange()->getEnd());
            return;
        }
    }
@@ -4487,10 +4483,9 @@ void DomainMapper::lcl_utext(const sal_Unicode *const data_, size_t len)
                m_pImpl->clearDeferredBreaks();
            }

            bool bSdtBlockUnusedText
                = m_pImpl->m_pSdtHelper->GetSdtType() != NS_ooxml::LN_CT_SdtRun_sdtContent
                  && m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText
                  && m_pImpl->m_pSdtHelper->hasUnusedText();
            bool bInSdtBlockText
                = m_pImpl->m_pSdtHelper->GetSdtType() == NS_ooxml::LN_CT_SdtBlock_sdtContent
                  && m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText;
            if (pContext && pContext->GetFootnote().is())
            {
                pContext->GetFootnote()->setLabel( sText );
@@ -4500,32 +4495,29 @@ void DomainMapper::lcl_utext(const sal_Unicode *const data_, size_t len)
            }
            else if (m_pImpl->IsOpenFieldCommand() && !m_pImpl->IsForceGenericFields())
            {
                if (bSdtBlockUnusedText)
                if (bInSdtBlockText && m_pImpl->m_pSdtHelper->hasUnusedText())
                    m_pImpl->m_pSdtHelper->createPlainTextControl();
                m_pImpl->AppendFieldCommand(sText);
                if (bSdtBlockUnusedText)
                    m_pImpl->m_pSdtHelper->setFieldStartRange(GetCurrentTextRange()->getEnd());
            }
            else if( m_pImpl->IsOpenField() && m_pImpl->IsFieldResultAsString())
            {
                if (bSdtBlockUnusedText)
                if (bInSdtBlockText && m_pImpl->m_pSdtHelper->hasUnusedText())
                    m_pImpl->m_pSdtHelper->createPlainTextControl();
                /*depending on the success of the field insert operation this result will be
                  set at the field or directly inserted into the text*/
                m_pImpl->AppendFieldResult(sText);
                if (bSdtBlockUnusedText)
                    m_pImpl->m_pSdtHelper->setFieldStartRange(GetCurrentTextRange()->getEnd());
            }
            else
            {
                if (pContext == nullptr)
                    pContext = new PropertyMap();

                if (bInSdtBlockText && !m_pImpl->m_pSdtHelper->hasUnusedText())
                    m_pImpl->m_pSdtHelper->setFieldStartRange(GetCurrentTextRange()->getEnd());

                m_pImpl->appendTextPortion( sText, pContext );

                if (m_pImpl->m_pSdtHelper->GetSdtType() == NS_ooxml::LN_CT_SdtBlock_sdtContent
                    && m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText
                    && !sText.isEmpty())
                if (bInSdtBlockText && !sText.isEmpty())
                    m_pImpl->m_pSdtHelper->setHasUnusedText(true);
            }

diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx
index c7f9987..922ac5b 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -604,6 +604,7 @@ void SdtHelper::clear()
    m_nId = 0;
    m_nTabIndex = 0;
    m_aLock.clear();
    m_xFieldStartRange.clear();
}

void SdtHelper::SetPlaceholderDocPart(const OUString& rPlaceholderDocPart)