sw/qa/extras/ooxmlexport/data/testCrashWhileSave.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 8 + sw/source/filter/ww8/docxattributeoutput.cxx | 82 ++++++++++++------ sw/source/filter/ww8/docxattributeoutput.hxx | 30 +++++- sw/source/filter/ww8/docxexport.cxx | 6 - sw/source/filter/ww8/docxexport.hxx | 3 6 files changed, 98 insertions(+), 31 deletions(-)
New commits: commit 29c079f0480f63dd3f046f30c2b81023c2a5aebf Author: Rohit Deshmukh <rohit.deshm...@synerzip.com> Date: Thu Nov 21 11:17:40 2013 +0530 fdo#71594: Fix for LO crash while saving of file. 1] Libreoffice gets crashed while saving. 2] This caused: "testCrashWhileSave.docx" file crashes on save Tested on Libreoffice 4.2 Implementation: 1] It crashes when we are trying to access cell number 2 from cells vector which contains only single cell. So put check for cell number which we are accessing and Number of cells in single row. 2] As we are exporting Header and footer in between when we are exporting document.xml. In this case we are facing issue in table export for header and footer. Because flags for table is getting shared in both export. So we are switching between flags in between exporting "document.xml" and Header & footer export. After fix: 1] No crash on save for "testCrashWhileSave.docx" and opens successfully on MS Office 2010 Added Unit test case in export. Conflicts: sw/qa/extras/ooxmlexport/ooxmlexport.cxx Reviewed on: https://gerrit.libreoffice.org/6676 Change-Id: Iefbf565f7b512d76ac68e9353e225edca425ef06 diff --git a/sw/qa/extras/ooxmlexport/data/testCrashWhileSave.docx b/sw/qa/extras/ooxmlexport/data/testCrashWhileSave.docx new file mode 100644 index 0000000..2059951 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/testCrashWhileSave.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index d594627..7428200 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -2128,6 +2128,14 @@ DECLARE_OOXMLEXPORT_TEST(testFdo71785, "fdo71785.docx") // crashtest } +DECLARE_OOXMLEXPORT_TEST(testCrashWhileSave, "testCrashWhileSave.docx") +{ + xmlDocPtr pXmlDoc = parseExport("word/footer1.xml"); + if (!pXmlDoc) + return; + CPPUNIT_ASSERT(getXPath(pXmlDoc, "/w:ftr/w:tbl/w:tr/w:tc[1]/w:p[1]/w:pPr/w:pStyle", "val").match("Normal")); +} + #endif CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 6896717..2d938b5 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -237,9 +237,9 @@ void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pText sal_uInt32 nCell = pTextNodeInfo->getCell(); // New cell/row? - if ( m_nTableDepth > 0 && !m_bTableCellOpen ) + if ( m_tableReference->m_nTableDepth > 0 && !m_tableReference->m_bTableCellOpen ) { - ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_nTableDepth ) ); + ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_tableReference->m_nTableDepth ) ); if ( pDeepInner->getCell() == 0 ) StartTableRow( pDeepInner ); @@ -253,10 +253,10 @@ void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pText // continue the table cell] sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth(); - if ( nCurrentDepth > m_nTableDepth ) + if ( nCurrentDepth > m_tableReference->m_nTableDepth ) { // Start all the tables that begin here - for ( sal_uInt32 nDepth = m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth ) + for ( sal_uInt32 nDepth = m_tableReference->m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth ) { ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) ); @@ -265,7 +265,7 @@ void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pText StartTableCell( pInner ); } - m_nTableDepth = nCurrentDepth; + m_tableReference->m_nTableDepth = nCurrentDepth; } } } @@ -2014,13 +2014,18 @@ void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Point // Horizontal spans const SwWriteTableRows& aRows = m_pTableWrt->GetRows( ); SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ]; - const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ]; + sal_uInt32 nCell = pTableTextNodeInfoInner->getCell(); + const SwWriteTableCells *tableCells = &pRow->GetCells(); + if (nCell < tableCells->size() ) + { + const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ]; - sal_uInt16 nColSpan = pCell->GetColSpan(); - if ( nColSpan > 1 ) - m_pSerializer->singleElementNS( XML_w, XML_gridSpan, - FSNS( XML_w, XML_val ), OString::number( nColSpan ).getStr(), - FSEND ); + sal_uInt16 nColSpan = pCell->GetColSpan(); + if ( nColSpan > 1 ) + m_pSerializer->singleElementNS( XML_w, XML_gridSpan, + FSNS( XML_w, XML_val ), OString::number( nColSpan ).getStr(), + FSEND ); + } // Vertical merges long vSpan = pTblBox->getRowSpan( ); @@ -2076,6 +2081,32 @@ void DocxAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t (sal_uInt16)nTblSz, false); } +/** + * As we are exporting Header and footer in between when we are exporting document.xml. + * In this case we are facing issue in table export for header and footer. Because + * flags for table is getting shared in both export. + * So we are switching between flags in between exporting "document.xml" and Header & footer + * export. + */ +void DocxAttributeOutput::switchHeaderFooter(bool isHeaderFooter, sal_Int32 index) +{ + if( isHeaderFooter && index == 1) + { + m_oldTableReference->m_bTableCellOpen = m_tableReference->m_bTableCellOpen; + m_oldTableReference->m_nTableDepth = m_tableReference->m_nTableDepth; + m_tableReference->m_bTableCellOpen = false; + m_tableReference->m_nTableDepth = 0; + } + else if( index == -1) + { + m_tableReference = m_oldTableReference; + } + else + { + m_tableReference->m_bTableCellOpen = false; + m_tableReference->m_nTableDepth = 0; + } +} void DocxAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner ) { m_pSerializer->startElementNS( XML_w, XML_tbl, FSEND ); @@ -2090,14 +2121,14 @@ void DocxAttributeOutput::EndTable() { m_pSerializer->endElementNS( XML_w, XML_tbl ); - if ( m_nTableDepth > 0 ) - --m_nTableDepth; + if ( m_tableReference->m_nTableDepth > 0 ) + --m_tableReference->m_nTableDepth; tableFirstCells.pop_back(); // We closed the table; if it is a nested table, the cell that contains it // still continues - m_bTableCellOpen = true; + m_tableReference->m_bTableCellOpen = true; // Cleans the table helper delete m_pTableWrt, m_pTableWrt = NULL; @@ -2138,7 +2169,7 @@ void DocxAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t // Write the cell properties here TableCellProperties( pTableTextNodeInfoInner ); - m_bTableCellOpen = true; + m_tableReference->m_bTableCellOpen = true; } void DocxAttributeOutput::EndTableCell( ) @@ -2146,7 +2177,7 @@ void DocxAttributeOutput::EndTableCell( ) m_pSerializer->endElementNS( XML_w, XML_tc ); m_bBtLr = false; - m_bTableCellOpen = false; + m_tableReference->m_bTableCellOpen = false; } void DocxAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ ) @@ -2235,7 +2266,7 @@ void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t // If nested, tblInd is added to parent table's left spacing and defines left edge position // If not nested, text position of left-most cell must be at absolute X = tblInd // so, table_spacing + table_spacing_to_content = tblInd - if (m_nTableDepth == 0) + if (m_tableReference->m_nTableDepth == 0) { const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox(); const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt(); @@ -2410,19 +2441,24 @@ void DocxAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer const SwWriteTableRows& aRows = m_pTableWrt->GetRows( ); SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ]; - const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ]; - switch( pCell->GetVertOri()) + sal_uInt32 nCell = pTableTextNodeInfoInner->getCell(); + const SwWriteTableCells *tableCells = &pRow->GetCells(); + if (nCell < tableCells->size() ) { + const SwWriteTableCell *pCell = &pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ]; + switch( pCell->GetVertOri()) + { case text::VertOrientation::TOP: break; case text::VertOrientation::CENTER: m_pSerializer->singleElementNS( XML_w, XML_vAlign, - FSNS( XML_w, XML_val ), "center", FSEND ); + FSNS( XML_w, XML_val ), "center", FSEND ); break; case text::VertOrientation::BOTTOM: m_pSerializer->singleElementNS( XML_w, XML_vAlign, - FSNS( XML_w, XML_val ), "bottom", FSEND ); + FSNS( XML_w, XML_val ), "bottom", FSEND ); break; + } } } @@ -6570,8 +6606,6 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri m_bPostitStart(false), m_bPostitEnd(false), m_pTableWrt( NULL ), - m_bTableCellOpen( false ), - m_nTableDepth( 0 ), m_bParagraphOpened( false ), m_nColBreakStatus( COLBRK_NONE ), m_bTextFrameSyntax( false ), @@ -6589,6 +6623,8 @@ DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSeri m_postitFieldsMaxId( 0 ), m_anchorId( 1 ), m_nextFontId( 1 ), + m_tableReference(new TableReference()), + m_oldTableReference(new TableReference()), m_bBtLr(false), m_bFrameBtLr(false), m_pTableStyleExport(new DocxTableStyleExport(rExport.pDoc, pSerializer)), diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx index 958300d..3ef815a 100644 --- a/sw/source/filter/ww8/docxattributeoutput.hxx +++ b/sw/source/filter/ww8/docxattributeoutput.hxx @@ -100,6 +100,24 @@ struct PageMargins PageMargins() : nPageMarginLeft(0), nPageMarginRight(0), nPageMarginTop(0), nPageMarginBottom(0) {} }; +/** + * A structure that holds flags for the table export. + */ +struct TableReference +{ + /// Remember if we are in an open cell, or not. + bool m_bTableCellOpen; + + /// Remember the current table depth. + sal_uInt32 m_nTableDepth; + + TableReference() + : m_bTableCellOpen(false), + m_nTableDepth(0) + { + } +}; + /// The class that has handlers for various resource types when exporting as DOCX. class DocxAttributeOutput : public AttributeOutputBase, public oox::vml::VMLTextExport, public oox::drawingml::DMLTextExport { @@ -721,12 +739,6 @@ private: /// The current table helper SwWriteTable *m_pTableWrt; - /// Remember if we are in an open cell, or not. - bool m_bTableCellOpen; - - /// Remember the current table depth. - sal_uInt32 m_nTableDepth; - bool m_bParagraphOpened; // Remember that a column break has to be opened at the @@ -781,6 +793,11 @@ private: OString relId; OString fontKey; }; + + + TableReference *m_tableReference; + TableReference *m_oldTableReference; + std::map< OUString, EmbeddedFontRef > fontFilesMap; // font file url to data // Remember first cell (used for for default borders/margins) of each table @@ -836,6 +853,7 @@ public: /// VMLTextExport virtual void WriteOutliner(const OutlinerParaObject& rParaObj); virtual oox::drawingml::DrawingML& GetDrawingML(); + virtual void switchHeaderFooter(bool isHeaderFooter, sal_Int32 index); void BulletDefinition(int nId, const Graphic& rGraphic, Size aSize) SAL_OVERRIDE; diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 2edcf56..2409e42 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -201,6 +201,7 @@ bool DocxExport::DisallowInheritingOutlineNumbering( const SwFmt& rFmt ) void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 /*nBreakCode*/ ) { + m_nHeadersFootersInSection = 1; // Turn ON flag for 'Writing Headers \ Footers' m_pAttrOutput->SetWritingHeaderFooter( true ); @@ -229,7 +230,7 @@ void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, // Turn OFF flag for 'Writing Headers \ Footers' m_pAttrOutput->SetWritingHeaderFooter( false ); - + m_pAttrOutput->switchHeaderFooter(false, -1); #if OSL_DEBUG_LEVEL > 1 fprintf( stderr, "DocxExport::WriteHeadersFooters() - nBreakCode introduced, but ignored\n" ); #endif @@ -628,7 +629,7 @@ void DocxExport::WriteHeaderFooter( const SwFmt& rFmt, bool bHeader, const char* // switch the serializer to redirect the output to word/styles.xml m_pAttrOutput->SetSerializer( pFS ); m_pVMLExport->SetFS( pFS ); - + m_pAttrOutput->switchHeaderFooter(true, m_nHeadersFootersInSection++); // do the work WriteHeaderFooterText( rFmt, bHeader ); @@ -1199,6 +1200,7 @@ DocxExport::DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCur m_pSections( NULL ), m_nHeaders( 0 ), m_nFooters( 0 ), + m_nHeadersFootersInSection(0), m_pVMLExport( NULL ) { // Write the document properies diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index cac754e..5dd9e04 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -83,6 +83,9 @@ class DocxExport : public MSWordExportBase /// Footer counter. sal_Int32 m_nFooters; + ///Footer and Header counter in Section properties + sal_Int32 m_nHeadersFootersInSection; + /// Exporter of the VML shapes. oox::vml::VMLExport *m_pVMLExport; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits