Hi, I have submitted a patch for review:
https://gerrit.libreoffice.org/2179 To pull it, you can do: git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/79/2179/1 fdo#60732: SwTxtNode: limit to less than STRING_LEN chars It's not a good idea to have STRING_LEN characters in a SwTxtNode because then there is no valid SwPosition at the end of the paragraph. Also it turns out that LO 3.6 and 4.0 do rather stupid things with a full SwTxtNode. So enforce a limit, at first in the usual places that are used during file import, SwTxtNode::InsertText() and SwCntntNode::CanJoinPrev()/CanJoinNext(). Change-Id: Icb0f44acd20aa81635d42b84d4ae0f9b693a661c (cherry picked from commit 549c0f785d4b6d4bc1b39b22827d77d66f48430a) --- M sw/inc/ndtxt.hxx M sw/source/core/docnode/node.cxx M sw/source/core/txtnode/ndtxt.cxx 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx index 2b0d8cd..0865fa3 100644 --- a/sw/inc/ndtxt.hxx +++ b/sw/inc/ndtxt.hxx @@ -70,6 +70,11 @@ typedef std::set< xub_StrLen > SwSoftPageBreakList; +// do not fill the String up to the max - need to be able to have a +// SwPosition "behind" the last character, i.e., at index TXTNODE_MAX + 1 +// (also STRING_LEN is often used for "not found") +const xub_StrLen TXTNODE_MAX = STRING_LEN - 2; + /// SwTxtNode is a paragraph in the document model. class SW_DLLPUBLIC SwTxtNode: public SwCntntNode, public ::sfx2::Metadatable { diff --git a/sw/source/core/docnode/node.cxx b/sw/source/core/docnode/node.cxx index 132282f..b1b19d3 100644 --- a/sw/source/core/docnode/node.cxx +++ b/sw/source/core/docnode/node.cxx @@ -1623,12 +1623,26 @@ return pFnd; } +static bool lcl_CheckMaxLength(SwNode const& rPrev, SwNode const& rNext) +{ + if (rPrev.GetNodeType() != rNext.GetNodeType()) + { + return false; + } + if (!rPrev.IsTxtNode()) + { + return true; + } + size_t const nSum( static_cast<const SwTxtNode&>(rPrev).GetTxt().Len() + + static_cast<const SwTxtNode&>(rNext).GetTxt().Len()); + return (nSum <= TXTNODE_MAX); +} + // Can we join two Nodes? // We can return the 2nd position in pIdx. int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const { const SwNodes& rNds = GetNodes(); - sal_uInt8 nNdType = GetNodeType(); SwNodeIndex aIdx( *this, 1 ); const SwNode* pNd = this; @@ -1637,16 +1651,11 @@ ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() ))) ++aIdx; - if( pNd->GetNodeType() != nNdType || rNds.Count()-1 == aIdx.GetIndex() ) + if (rNds.Count()-1 == aIdx.GetIndex()) return sal_False; - if( IsTxtNode() ) - { // Do not merge strings if the result exceeds the allowed string length - const SwTxtNode* pTxtNd = static_cast<const SwTxtNode*>(this); - sal_uInt64 nSum = pTxtNd->GetTxt().Len(); - pTxtNd = static_cast<const SwTxtNode*>(pNd); - nSum += pTxtNd->GetTxt().Len(); - if( nSum > STRING_LEN ) - return sal_False; + if (!lcl_CheckMaxLength(*this, *pNd)) + { + return false; } if( pIdx ) *pIdx = aIdx; @@ -1657,7 +1666,6 @@ // We can return the 2nd position in pIdx. int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const { - sal_uInt8 nNdType = GetNodeType(); SwNodeIndex aIdx( *this, -1 ); const SwNode* pNd = this; @@ -1666,8 +1674,12 @@ ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() ))) aIdx--; - if( pNd->GetNodeType() != nNdType || 0 == aIdx.GetIndex() ) + if (0 == aIdx.GetIndex()) return sal_False; + if (!lcl_CheckMaxLength(*pNd, *this)) + { + return false; + } if( pIdx ) *pIdx = aIdx; return sal_True; diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx index eb2dd25..f634571 100644 --- a/sw/source/core/txtnode/ndtxt.cxx +++ b/sw/source/core/txtnode/ndtxt.cxx @@ -1713,7 +1713,11 @@ xub_StrLen aPos = rIdx.GetIndex(); xub_StrLen nLen = m_Text.Len() - aPos; - m_Text.Insert( rStr, aPos ); + ssize_t const nOverflow(static_cast<ssize_t>(m_Text.Len()) + + static_cast<ssize_t>(rStr.Len()) - TXTNODE_MAX); + m_Text.Insert((nOverflow > 0) ? rStr.Copy(0, rStr.Len() - nOverflow) : rStr, + aPos); + assert(m_Text.Len() <= TXTNODE_MAX); nLen = m_Text.Len() - aPos - nLen; if ( !nLen ) return; -- To view, visit https://gerrit.libreoffice.org/2179 To unsubscribe, visit https://gerrit.libreoffice.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Icb0f44acd20aa81635d42b84d4ae0f9b693a661c Gerrit-PatchSet: 1 Gerrit-Project: core Gerrit-Branch: libreoffice-4-0 Gerrit-Owner: Michael Stahl <mst...@redhat.com> _______________________________________________ LibreOffice mailing list LibreOffice@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice