diff options
author | Caolán McNamara <caolanm@redhat.com> | 2015-05-29 15:25:27 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2015-05-29 15:25:27 +0100 |
commit | f703201d35f6e77940f68a21b339f67335b99441 (patch) | |
tree | 4938156f7665ea71be69f15a5b915263b67f3a42 | |
parent | e9bb7c9e69999467a8dd5aa1683563228c619edc (diff) |
fix Invalid Read on conversion of ooo95991-1.odt to pdf
"Prepare" can delete the Portion belonging to the SwTxtFrm
and replace it. Prepare knows this and re-fetches it if
that happens. But Prepare can call itself and the outermost
Prepare doesn't know that the innermost Prepare replaced
the SwTxtFrm (and re-fetched it for the remainer of the
innermost Prepare).
So bubble out that it was re-fetched so the outer most
one re-fetches too
Invalid read of size 1
SwParaPortion::SetPrep(bool) (porlay.hxx:299)
SwTextFrm::Prepare(PrepareHint, void const*, bool) (txtfrm.cxx:1805)
SwContentFrm::MakeAll() (calcmove.cxx:1317)
SwFrm::PrepareMake() (calcmove.cxx:340)
SwFrm::Calc() const (frame.hxx:1004)
CalcContent(SwLayoutFrm*, bool, bool) (fly.cxx:1465)
SwLayoutFrm::FormatWidthCols(SwBorderAttrs const&, long, long) (wsfrm.cxx:3306)
Address 0x2137c850 is 832 bytes inside a block of size 840 free'd
free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
rtl_freeMemory_SYSTEM(void*) (alloc_global.cxx:277)
rtl_freeMemory (alloc_global.cxx:347)
rtl_cache_free (alloc_cache.cxx:1222)
FixedMemPool::Free(void*) (mempool.cxx:48)
SwParaPortion::operator delete(void*, unsigned long) (in /home/caolan/LibreOffice/core/instdir/program/libswlo.so)
SwParaPortion::~SwParaPortion() (porlay.cxx:1967)
SwTextFrm::ClearPara() (txtcache.cxx:106)
SwTextFrm::Init() (txtfrm.cxx:339)
SwTextFrm::CalcLineSpace() (txtfrm.cxx:792)
SwTextFrm::Prepare(PrepareHint, void const*, bool) (txtfrm.cxx:1724)
SwTextFrm::Prepare(PrepareHint, void const*, bool) (txtfrm.cxx:1706)
SwContentFrm::MakeAll() (calcmove.cxx:1317)
SwFrm::PrepareMake() (calcmove.cxx:340)
SwFrm::Calc() const (frame.hxx:1004)
CalcContent(SwLayoutFrm*, bool, bool) (fly.cxx:1465)
SwLayoutFrm::FormatWidthCols(SwBorderAttrs const&, long, long) (wsfrm.cxx:3306)
Change-Id: I1fdade2846e3cbd2e73be1f58d2597e9358fa0ea
-rw-r--r-- | sw/source/core/inc/frame.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/inc/tabfrm.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/inc/txtfrm.hxx | 5 | ||||
-rw-r--r-- | sw/source/core/layout/tabfrm.cxx | 3 | ||||
-rw-r--r-- | sw/source/core/layout/wsfrm.cxx | 3 | ||||
-rw-r--r-- | sw/source/core/text/txtfrm.cxx | 38 |
6 files changed, 36 insertions, 17 deletions
diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx index 0a23c88acc24..8d283f59e23a 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -770,7 +770,7 @@ public: // HACK: shortcut between frame and formatting // It's your own fault if you cast void* incorrectly! In any case check // the void* for 0. - virtual void Prepare( const PrepareHint ePrep = PREP_CLEAR, + virtual bool Prepare( const PrepareHint ePrep = PREP_CLEAR, const void *pVoid = 0, bool bNotify = true ); // true if it is the correct class, false otherwise diff --git a/sw/source/core/inc/tabfrm.hxx b/sw/source/core/inc/tabfrm.hxx index 3b418cf7f18b..c78872bc553a 100644 --- a/sw/source/core/inc/tabfrm.hxx +++ b/sw/source/core/inc/tabfrm.hxx @@ -133,7 +133,7 @@ public: virtual void Cut() SAL_OVERRIDE; virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 ) SAL_OVERRIDE; - virtual void Prepare( const PrepareHint ePrep = PREP_CLEAR, + virtual bool Prepare( const PrepareHint ePrep = PREP_CLEAR, const void *pVoid = 0, bool bNotify = true ) SAL_OVERRIDE; SwContentFrm *FindLastContent(); diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx index 034b2bee5361..7bfa6920dd8d 100644 --- a/sw/source/core/inc/txtfrm.hxx +++ b/sw/source/core/inc/txtfrm.hxx @@ -342,8 +342,11 @@ public: * SwContentFrm: the shortcut for the Frames * If the void* casts wrongly, it's its own fault! * The void* must be checked for 0 in any case! + * + * return true if the Portion associated with this SwTxtFrm was + * potentially destroyed and replaced by Prepare */ - virtual void Prepare( const PrepareHint ePrep = PREP_CLEAR, + virtual bool Prepare( const PrepareHint ePrep = PREP_CLEAR, const void *pVoid = 0, bool bNotify = true ) SAL_OVERRIDE; /** diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index 477053a9c9e2..c2f63c184c95 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -3490,10 +3490,11 @@ void SwTabFrm::Paste( SwFrm* pParent, SwFrm* pSibling ) } } -void SwTabFrm::Prepare( const PrepareHint eHint, const void *, bool ) +bool SwTabFrm::Prepare( const PrepareHint eHint, const void *, bool ) { if( PREP_BOSS_CHGD == eHint ) CheckDirChange(); + return false; } SwRowFrm::SwRowFrm(const SwTableLine &rLine, SwFrm* pSib, bool bInsertContent) diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index 6ab254e6b9aa..73ca1dd29ed8 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -332,9 +332,10 @@ void SwFrm::_UpdateAttrFrm( const SfxPoolItem *pOld, const SfxPoolItem *pNew, } } -void SwFrm::Prepare( const PrepareHint, const void *, bool ) +bool SwFrm::Prepare( const PrepareHint, const void *, bool ) { /* Do nothing */ + return false; } /** diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index bebe4564c54d..07e45f91c601 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -1441,9 +1441,11 @@ static bool lcl_ErgoVadis( SwTextFrm* pFrm, sal_Int32 &rPos, const PrepareHint e return true; } -void SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, +bool SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, bool bNotify ) { + bool bParaPossiblyInvalid = false; + SwFrmSwapper aSwapper( this, false ); #if OSL_DEBUG_LEVEL > 1 @@ -1459,7 +1461,7 @@ void SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, SetInvalidVert( true ); // Test case PREP_WIDOWS_ORPHANS: case PREP_WIDOWS: - case PREP_FTN_GONE : return; + case PREP_FTN_GONE : return bParaPossiblyInvalid; case PREP_POS_CHGD : { @@ -1491,7 +1493,7 @@ void SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, if ( GetDrawObjs() ) break; - return; + return bParaPossiblyInvalid; } default: break; @@ -1506,7 +1508,7 @@ void SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, InvalidateSize(); else _InvalidateSize(); - return; + return bParaPossiblyInvalid; } // Get object from cache while locking @@ -1537,7 +1539,7 @@ void SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, case PREP_WIDOWS : // MustFit is stronger than anything else if( pPara->IsPrepMustFit() ) - return; + return bParaPossiblyInvalid; // see comment in WidowsAndOrphans::FindOrphans and CalcPreps() PrepWidows( *static_cast<const sal_uInt16 *>(pVoid), bNotify ); break; @@ -1703,17 +1705,23 @@ void SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, else { if( GetTextNode()->GetSwAttrSet().GetRegister().GetValue() ) - Prepare( PREP_REGISTER, 0, bNotify ); - + bParaPossiblyInvalid = Prepare( PREP_REGISTER, 0, bNotify ); // The Frames need to be readjusted, which caused by changes // in position else if( HasFootnote() ) { - Prepare( PREP_ADJUST_FRM, 0, bNotify ); + bParaPossiblyInvalid = Prepare( PREP_ADJUST_FRM, 0, bNotify ); _InvalidateSize(); } else - return; // So that there's no SetPrep() + return bParaPossiblyInvalid; // So that there's no SetPrep() + + if (bParaPossiblyInvalid) + { + // It's possible that pPara was deleted above; retrieve it again + pPara = aAccess.GetPara(); + } + } break; } @@ -1724,7 +1732,9 @@ void SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, CalcLineSpace(); // It's possible that pPara was deleted above; retrieve it again + bParaPossiblyInvalid = true; pPara = aAccess.GetPara(); + InvalidateSize(); _InvalidatePrt(); SwFrm* pNxt; @@ -1750,7 +1760,7 @@ void SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, if( nPos ) --nPos; // The char preceding our Follow InvalidateRange( SwCharRange( nPos, 1 ), 0 ); - return; + return bParaPossiblyInvalid; } case PREP_ERGOSUM: case PREP_QUOVADIS: @@ -1767,7 +1777,7 @@ void SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, sal_Int32 nWhere = CalcFlyPos( const_cast<SwFrameFormat *>(static_cast<SwFrameFormat const *>(pVoid)) ); OSL_ENSURE( COMPLETE_STRING != nWhere, "Prepare: Why me?" ); InvalidateRange( SwCharRange( nWhere, 1 ) ); - return; + return bParaPossiblyInvalid; } // else: continue with default case block } @@ -1796,11 +1806,15 @@ void SwTextFrm::Prepare( const PrepareHint ePrep, const void* pVoid, else _InvalidateSize(); } - return; // no SetPrep() happened + return bParaPossiblyInvalid; // no SetPrep() happened } } if( pPara ) + { pPara->SetPrep(); + } + + return bParaPossiblyInvalid; } /** |