[Libreoffice-commits] core.git: sw/source

Caolán McNamara caolanm at redhat.com
Fri May 29 07:28:31 PDT 2015


 sw/source/core/inc/frame.hxx     |    2 +-
 sw/source/core/inc/tabfrm.hxx    |    2 +-
 sw/source/core/inc/txtfrm.hxx    |    5 ++++-
 sw/source/core/layout/tabfrm.cxx |    3 ++-
 sw/source/core/layout/wsfrm.cxx  |    3 ++-
 sw/source/core/text/txtfrm.cxx   |   38 ++++++++++++++++++++++++++------------
 6 files changed, 36 insertions(+), 17 deletions(-)

New commits:
commit f703201d35f6e77940f68a21b339f67335b99441
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri May 29 15:25:27 2015 +0100

    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

diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx
index 0a23c88..8d283f5 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 3b418cf..c78872b 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 034b2be..7bfa692 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 477053a..c2f63c1 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 6ab254e..73ca1dd 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 bebe456..07e45f9 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;
 }
 
 /**


More information about the Libreoffice-commits mailing list