sw/source/core/table/swnewtable.cxx | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
New commits: commit ac8717e861608031e50230015c90e64282a10ad0 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Oct 7 16:21:27 2022 +0200 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Fri Oct 7 17:45:08 2022 +0200 tdf#151375 sw: ODF import: delete any layout frames before ... ... converting subtables. This avoids use-after-free by the frames or a11y code on deleted cells. For file open, there is no layout at this point, but when inserting a file the crash happens. (regression from commit e366c928819c44b5c253c45dca6dae40b71c9808) Change-Id: Ia2cbe548fd5cdce7ae2479bfc3dc993ebb3ce830 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141080 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/sw/source/core/table/swnewtable.cxx b/sw/source/core/table/swnewtable.cxx index 8d6bcf023d2c..a0c420b1876c 100644 --- a/sw/source/core/table/swnewtable.cxx +++ b/sw/source/core/table/swnewtable.cxx @@ -2382,6 +2382,8 @@ bool SwTable::CanConvertSubtables() const void SwTable::ConvertSubtables() { + FndBox_ all(nullptr, nullptr); + all.DelFrames(*this); // tdf#151375 avoid UAF by frames on deleted cells for (size_t i = 0; i < GetTabLines().size(); ++i) { SwTableLine *const pLine(GetTabLines()[i]); @@ -2397,6 +2399,7 @@ void SwTable::ConvertSubtables() } GCLines(); m_bNewModel = true; + all.MakeFrames(*this); #if 0 // note: outline nodes (and ordinary lists) are sorted by MoveNodes() itself // (this could change order inside table of contents, but that's a commit 4757dfc2a520f63fba0b27cc161fe732231dbd0e Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Oct 7 16:13:05 2022 +0200 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Fri Oct 7 17:44:54 2022 +0200 tdf#145871 sw: ODF import: don't convert subtables if outer row ... ... has fixed or min height. The code had 2 obvious problems: the fixed height on the outer row wasn't cleared if the inner row didn't have a fixed height, and the code to set lastSize on the last row erroneously set the first row's height as well due to sharing the row format. But it turns out that this doesn't work anyway in case any of the inner rows are variable sized, because without layout it's not possible to determine the height of these rows, and so the lastSize is going to be too large in many cases. (regression from commit e366c928819c44b5c253c45dca6dae40b71c9808) Change-Id: I42ac7c14236562f9cae228efc0e98dc2fa8c2a23 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141079 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/sw/source/core/table/swnewtable.cxx b/sw/source/core/table/swnewtable.cxx index d87c039185c0..8d6bcf023d2c 100644 --- a/sw/source/core/table/swnewtable.cxx +++ b/sw/source/core/table/swnewtable.cxx @@ -2133,6 +2133,11 @@ void SwTable::ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox) assert(!pSubTableBox->GetTabLines().empty()); // are relative (%) heights possible? apparently not SwFormatFrameSize const outerSize(pSourceLine->GetFrameFormat()->GetFrameSize()); + if (outerSize.GetHeightSizeType() != SwFrameSize::Variable) + { // tdf#145871 clear fixed size in first row + pSourceLine->ClaimFrameFormat(); + pSourceLine->GetFrameFormat()->ResetFormatAttr(RES_FRM_SIZE); + } tools::Long minHeights(0); { SwFrameFormat const& rSubLineFormat(*pSubTableBox->GetTabLines()[0]->GetFrameFormat()); @@ -2171,12 +2176,14 @@ void SwTable::ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox) && outerSize.GetHeightSizeType() != SwFrameSize::Variable && minHeights < outerSize.GetHeight()) { + assert(false); // this should be impossible currently, such subtable isn't converted because layout is needed to determine how much space is taken up by variable height rows SwFormatFrameSize lastSize(pNewLine->GetFrameFormat()->GetFrameSize()); lastSize.SetHeight(lastSize.GetHeight() + outerSize.GetHeight() - minHeights); if (lastSize.GetHeightSizeType() == SwFrameSize::Variable) { lastSize.SetHeightSizeType(SwFrameSize::Minimum); } + pNewLine->ClaimFrameFormat(); pNewLine->GetFrameFormat()->SetFormatAttr(lastSize); } SfxPoolItem const* pRowBrush(nullptr); @@ -2295,6 +2302,7 @@ bool SwTable::CanConvertSubtables() const return false; } haveSubtable = true; + bool haveNonFixedInnerLine(false); for (SwTableLine const*const pInnerLine : pBox->GetTabLines()) { // bitmap row background will look different @@ -2311,6 +2319,13 @@ bool SwTable::CanConvertSubtables() const return false; } } + if (SwFormatFrameSize const* pSize = rRowFormat.GetItemIfSet(RES_FRM_SIZE)) + { + if (pSize->GetHeightSizeType() != SwFrameSize::Fixed) + { + haveNonFixedInnerLine = true; + } + } for (SwTableBox const*const pInnerBox : pInnerLine->GetTabBoxes()) { if (!pInnerBox->GetTabLines().empty()) @@ -2319,6 +2334,17 @@ bool SwTable::CanConvertSubtables() const } } } + if (haveNonFixedInnerLine) + { + if (SwFormatFrameSize const* pSize = pLine->GetFrameFormat()->GetItemIfSet(RES_FRM_SIZE)) + { + if (pSize->GetHeightSizeType() != SwFrameSize::Variable) + { + // not possible to distribute fixed outer row height on rows without layout + return false; + } + } + } } } }