Kaydet (Commit) 549c0f78 authored tarafından Michael Stahl's avatar Michael Stahl

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
üst 18d37cf9
...@@ -70,6 +70,11 @@ namespace com { namespace sun { namespace star { ...@@ -70,6 +70,11 @@ namespace com { namespace sun { namespace star {
typedef std::set< xub_StrLen > SwSoftPageBreakList; 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. /// SwTxtNode is a paragraph in the document model.
class SW_DLLPUBLIC SwTxtNode: public SwCntntNode, public ::sfx2::Metadatable class SW_DLLPUBLIC SwTxtNode: public SwCntntNode, public ::sfx2::Metadatable
{ {
......
...@@ -1624,12 +1624,26 @@ const SfxPoolItem* SwCntntNode::GetNoCondAttr( sal_uInt16 nWhich, ...@@ -1624,12 +1624,26 @@ const SfxPoolItem* SwCntntNode::GetNoCondAttr( sal_uInt16 nWhich,
return pFnd; 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? // Can we join two Nodes?
// We can return the 2nd position in pIdx. // We can return the 2nd position in pIdx.
int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const
{ {
const SwNodes& rNds = GetNodes(); const SwNodes& rNds = GetNodes();
sal_uInt8 nNdType = GetNodeType();
SwNodeIndex aIdx( *this, 1 ); SwNodeIndex aIdx( *this, 1 );
const SwNode* pNd = this; const SwNode* pNd = this;
...@@ -1638,16 +1652,11 @@ int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const ...@@ -1638,16 +1652,11 @@ int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const
( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() ))) ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
++aIdx; ++aIdx;
if( pNd->GetNodeType() != nNdType || rNds.Count()-1 == aIdx.GetIndex() ) if (rNds.Count()-1 == aIdx.GetIndex())
return sal_False; return sal_False;
if( IsTxtNode() ) if (!lcl_CheckMaxLength(*this, *pNd))
{ // Do not merge strings if the result exceeds the allowed string length {
const SwTxtNode* pTxtNd = static_cast<const SwTxtNode*>(this); return false;
sal_uInt64 nSum = pTxtNd->GetTxt().Len();
pTxtNd = static_cast<const SwTxtNode*>(pNd);
nSum += pTxtNd->GetTxt().Len();
if( nSum > STRING_LEN )
return sal_False;
} }
if( pIdx ) if( pIdx )
*pIdx = aIdx; *pIdx = aIdx;
...@@ -1658,7 +1667,6 @@ int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const ...@@ -1658,7 +1667,6 @@ int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const
// We can return the 2nd position in pIdx. // We can return the 2nd position in pIdx.
int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const
{ {
sal_uInt8 nNdType = GetNodeType();
SwNodeIndex aIdx( *this, -1 ); SwNodeIndex aIdx( *this, -1 );
const SwNode* pNd = this; const SwNode* pNd = this;
...@@ -1667,8 +1675,12 @@ int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const ...@@ -1667,8 +1675,12 @@ int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const
( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() ))) ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
aIdx--; aIdx--;
if( pNd->GetNodeType() != nNdType || 0 == aIdx.GetIndex() ) if (0 == aIdx.GetIndex())
return sal_False; return sal_False;
if (!lcl_CheckMaxLength(*pNd, *this))
{
return false;
}
if( pIdx ) if( pIdx )
*pIdx = aIdx; *pIdx = aIdx;
return sal_True; return sal_True;
......
...@@ -1712,7 +1712,11 @@ void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx, ...@@ -1712,7 +1712,11 @@ void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
xub_StrLen aPos = rIdx.GetIndex(); xub_StrLen aPos = rIdx.GetIndex();
xub_StrLen nLen = m_Text.Len() - aPos; 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; nLen = m_Text.Len() - aPos - nLen;
if ( !nLen ) return; if ( !nLen ) return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment