summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2023-10-05 08:14:41 +0200
committerXisco Fauli <xiscofauli@libreoffice.org>2023-10-05 11:25:40 +0200
commit840606ffb872e280228cd5144bf22541d1f94214 (patch)
tree7a92d55406dcd5e88e1c838c3a8f4928ede9f52d
parentmacOS /w Xcode 15: force the old linker when targeting macOS 11 or lower (diff)
downloadcore-840606ffb872e280228cd5144bf22541d1f94214.tar.gz
core-840606ffb872e280228cd5144bf22541d1f94214.zip
sw floattable, crashtesting: fix PDF export of fdo56210-3.docx
The bugdoc crashed on PDF export: heap-use-after-free on address 0x614000205148 at pc 0x7fb757347d7a bp 0x7fffeff17170 sp 0x7fffeff17168 READ of size 8 at 0x614000205148 thread T0 #2 0x7fb75785959b in SwFrame::GetDrawObjs() sw/source/core/inc/frame.hxx:569:66 #3 0x7fb75a802a60 in SwObjectFormatterTextFrame::InvalidatePrevObjs(SwAnchoredObject&) sw/source/core/layout/objectformattertxtfrm.cxx:494:50 #4 0x7fb75a7fe371 in SwObjectFormatterTextFrame::DoFormatObj(SwAnchoredObject&, bool) sw/source/core/layout/objectformattertxtfrm.cxx:155:13 #5 0x7fb75a7ee2c3 in SwObjectFormatter::FormatObjsAtFrame_(SwTextFrame*) sw/source/core/layout/objectformatter.cxx:413:19 #6 0x7fb75a807bff in SwObjectFormatterTextFrame::DoFormatObjs() sw/source/core/layout/objectformattertxtfrm.cxx:337:20 freed by thread T0 here: #1 0x7fb75b7a0b06 in SwTextFrame::~SwTextFrame() sw/source/core/text/txtfrm.cxx:988:1 #2 0x7fb75ab070e3 in SwFrame::DestroyFrame(SwFrame*) sw/source/core/layout/ssfrm.cxx:397:9 #3 0x7fb75b1925be in SwTextFrame::JoinFrame() sw/source/core/text/frmform.cxx:763:5 #4 0x7fb75a4dcd9e in SwFlyAtContentFrame::DelEmpty() sw/source/core/layout/flycnt.cxx:1748:26 #5 0x7fb75a3e3764 in SwFlowFrame::MoveSubTree(SwLayoutFrame*, SwFrame*) sw/source/core/layout/flowfrm.cxx:713:28 #6 0x7fb75a418138 in SwFlowFrame::MoveFwd(bool, bool, bool) sw/source/core/layout/flowfrm.cxx:2149:13 #7 0x7fb75ab63f19 in SwTabFrame::MakeAll(OutputDevice*) sw/source/core/layout/tabfrm.cxx:2886:23 #8 0x7fb75a2fc227 in SwFrame::PrepareMake(OutputDevice*) sw/source/core/layout/calcmove.cxx:388:5 #9 0x7fb75abf7383 in SwFrame::Calc(OutputDevice*) const sw/source/core/layout/trvlfrm.cxx:1803:37 #10 0x7fb75a7e9bd0 in SwObjectFormatter::FormatLayout_(SwLayoutFrame&) sw/source/core/layout/objectformatter.cxx:207:19 #11 0x7fb75a7e9f7d in SwObjectFormatter::FormatLayout_(SwLayoutFrame&) sw/source/core/layout/objectformatter.cxx:214:13 #12 0x7fb75a7eb550 in SwObjectFormatter::FormatObj_(SwAnchoredObject&) sw/source/core/layout/objectformatter.cxx:296:17 #13 0x7fb75a7fd88d in SwObjectFormatterTextFrame::DoFormatObj(SwAnchoredObject&, bool) sw/source/core/layout/objectformattertxtfrm.cxx:133:9 #14 0x7fb75a7ee2c3 in SwObjectFormatter::FormatObjsAtFrame_(SwTextFrame*) sw/source/core/layout/objectformatter.cxx:413:19 #15 0x7fb75a807bff in SwObjectFormatterTextFrame::DoFormatObjs() sw/source/core/layout/objectformattertxtfrm.cxx:337:20 I.e. the trouble is that SwObjectFormatter::FormatObjsAtFrame_() calls first calls DoFormatObj(), which joins a follow text frame, but then the same SwObjectFormatter::FormatObjsAtFrame_() calls DoFormatObj() again, and that still refers to the now deleted text frame. SwFlyAtContentFrame::DelEmpty() calling SwTextFrame::JoinFrame() was added recently, in commit cfe9c68a7a19dd77d1fcbde3a7dd75730634becc (tdf#157119 sw floattable: fix moving master of split fly to next page, 2023-09-21). Fix the problem by dropping the 2nd fix from the above commit (and leave the other 3 unchanged): that is no longer necessary for the old use-case, probably because in the meantime commit 695390b08799af34b393c81c834d615bea330d89 (tdf#126449 sw floattable: fix too small height of non-last anchors, 2023-10-03) started to add some real height for some of the split fly anchor frames, so less manual joins are needed. Note that the crash only happens with this bugdoc in case MALLOC_PERTURB_ is set to something non-empty or when using sanitizers. Change-Id: I4b810bd77a01a251dd1225426c50a7d7f100ece2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157577 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins (cherry picked from commit 2d6f48d53674ee85179ec8cee8648830207200a2) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157548 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
-rw-r--r--sw/qa/core/layout/data/floattable-del-empty.docxbin0 -> 36317 bytes
-rw-r--r--sw/qa/core/layout/flycnt.cxx12
-rw-r--r--sw/source/core/layout/flycnt.cxx11
3 files changed, 12 insertions, 11 deletions
diff --git a/sw/qa/core/layout/data/floattable-del-empty.docx b/sw/qa/core/layout/data/floattable-del-empty.docx
new file mode 100644
index 000000000000..340d06b6222b
--- /dev/null
+++ b/sw/qa/core/layout/data/floattable-del-empty.docx
Binary files differ
diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index f5f5fb094a37..37b255945d9e 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -1145,6 +1145,18 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyMoveMaster)
CPPUNIT_ASSERT(pPage4);
CPPUNIT_ASSERT(!pPage4->GetSortedObjs());
}
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyDelEmpty)
+{
+ // Given a document with multiple floating tables and 7 pages:
+ // When loading that document:
+ // Without the accompanying fix in place, this test would have crashed due to a
+ // heap-use-after-free problem (visible with e.g. MALLOC_PERTURB_=153).
+ createSwDoc("floattable-del-empty.docx");
+
+ // Then make sure that the page count matches Word:
+ CPPUNIT_ASSERT_EQUAL(7, getPages());
+}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx
index b23e8a46e868..faf991ddd9d2 100644
--- a/sw/source/core/layout/flycnt.cxx
+++ b/sw/source/core/layout/flycnt.cxx
@@ -1737,17 +1737,6 @@ void SwFlyAtContentFrame::DelEmpty()
// The anchor has a precede: invalidate it so that JoinFrame() is called on it.
pAnchorPrecede->GetFrame().InvalidateSize();
}
- else if (SwTextFrame* pAnchorFollow = pAnchor->GetFollow())
- {
- // No precede, but has a follow. Then move the master just before the follow and join.
- // This way the anchor chain and the fly chain will match even after clearing this
- // frame's follow pointer.
- if (pAnchorFollow != pAnchor->GetNext())
- {
- pAnchor->MoveSubTree(pAnchorFollow->GetUpper(), pAnchorFollow);
- pAnchor->JoinFrame();
- }
- }
}
SwFlyAtContentFrame* pMaster = IsFollow() ? GetPrecede() : nullptr;