Related: tdf#167713 sw: keep a replayed shape out of the row buffer

Converting a document whose header holds a table with a shape in a cell
aborted the RTF import in a Debug CODA build:

    C:\PROGRA~1\MICROS~1\18\COMMUN~1\VC\Tools\MSVC\1451~1.362\Include\deque(1128) : Assertion failed: back() called on empty deque

reached, as crashtesting found it, with

    COConvert.exe rtf fdo35334-3.odt
    COConvert.exe pdf fdo35334-3.rtf

on https://bugs.documentfoundation.org/attachment.cgi?id=57398.

The row buffer is replayed while the states still point at it, so the shape
insertion was buffered again, behind the cell being replayed, and dropped
with the buffer; the EndShape next to it then closed a shape that was never
opened, taking the table manager that the next substream needed.

Regression from 6c7c171d1468765f7e2a1872d7243f6bf809e37e (tdf#167713 sw:
keep an RTF pict shape in its cell, 2026-08-06).

Signed-off-by: Mike Kaganski <mike.kaganski@collabora.com>
Change-Id: Ib4fe247910cf67a8b60d448da75510bcf2251885
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/10084
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
(cherry picked from commit b2a7dd57076573ddac7141b99f9c33a68fbe799d)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/210363
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
Mike Kaganski
2026-09-02 01:02:54 +02:00
committed by Xisco Fauli
parent 64a367ebf1
commit cd1536dfd8
3 changed files with 58 additions and 0 deletions
@@ -0,0 +1,33 @@
{\rtf1\ansi\ansicpg1252\deff0
{\fonttbl{\f0\froman\fcharset0 Liberation Serif;}}
\paperw11906\paperh16838\margl1440\margr1440\margt1440\margb1440
\sectd \ltrsect
{\header \trowd \irow0\irowband0\lastrow \ltrrow\trgaph108\trleft0\trwWidth9026\trftsWidth3\trautofit0\trpaddl108\trpaddr108\trpaddfl3\trpaddfr3\tblind0\tblindtype3
\clvertalt\clwWidth3009\clftsWidth3 \cellx3009
\clvertalt\clwWidth3008\clftsWidth3 \cellx6017
\clvertalt\clwWidth3009\clftsWidth3 \cellx9026
\pard\plain \ltrpar\ql \li0\ri0\intbl\f0\fs22 {A1}{\cell }
\pard\plain \ltrpar\ql \li0\ri0\intbl\f0\fs22 {\shp{\*\shpinst\shpleft0\shptop0\shpright1000\shpbottom500\shpbxcolumn\shpbxignore\shpbypara\shpbyignore\shpwr2\shpz0{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fLine}{\sv 0}}{\shptxt \pard\plain \ltrpar\ql \f0\fs22 {in the header}\par}}}{\cell }
\pard\plain \ltrpar\ql \li0\ri0\intbl\f0\fs22 {C1}{\cell }
\trowd \irow0\irowband0\lastrow \ltrrow\trgaph108\trleft0\trwWidth9026\trftsWidth3\trautofit0\trpaddl108\trpaddr108\trpaddfl3\trpaddfr3\tblind0\tblindtype3
\clvertalt\clwWidth3009\clftsWidth3 \cellx3009
\clvertalt\clwWidth3008\clftsWidth3 \cellx6017
\clvertalt\clwWidth3009\clftsWidth3 \cellx9026\row
\pard\plain \ltrpar\ql \f0\fs22
\par}
{\footer \trowd \irow0\irowband0\lastrow \ltrrow\trgaph108\trleft0\trwWidth9026\trftsWidth3\trautofit0\trpaddl108\trpaddr108\trpaddfl3\trpaddfr3\tblind0\tblindtype3
\clvertalt\clwWidth3009\clftsWidth3 \cellx3009
\clvertalt\clwWidth3008\clftsWidth3 \cellx6017
\clvertalt\clwWidth3009\clftsWidth3 \cellx9026
\pard\plain \ltrpar\ql \li0\ri0\intbl\f0\fs22 {A1}{\cell }
\pard\plain \ltrpar\ql \li0\ri0\intbl\f0\fs22 {B1}{\cell }
\pard\plain \ltrpar\ql \li0\ri0\intbl\f0\fs22 {\shp{\*\shpinst\shpleft0\shptop0\shpright1000\shpbottom500\shpbxcolumn\shpbxignore\shpbypara\shpbyignore\shpwr2\shpz0{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fLine}{\sv 0}}{\shptxt \pard\plain \ltrpar\ql \f0\fs22 {in the footer}\par}}}{\cell }
\trowd \irow0\irowband0\lastrow \ltrrow\trgaph108\trleft0\trwWidth9026\trftsWidth3\trautofit0\trpaddl108\trpaddr108\trpaddfl3\trpaddfr3\tblind0\tblindtype3
\clvertalt\clwWidth3009\clftsWidth3 \cellx3009
\clvertalt\clwWidth3008\clftsWidth3 \cellx6017
\clvertalt\clwWidth3009\clftsWidth3 \cellx9026\row
\pard\plain \ltrpar\ql \f0\fs22
\par}
\pard\plain \ltrpar\ql \li0\ri0\f0\fs22 {Body}
\par
}
+19
View File
@@ -1042,6 +1042,25 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf167713)
getProperty<OUString>(xImage2->getAnchor()->getText(), u"CellName"_ustr));
}
CPPUNIT_TEST_FIXTURE(Test, testTdf167713ShapeText)
{
// Importing this used to abort in DomainMapper_Impl::substream(), asserting on an empty table
// manager stack: a shape with text in a buffered row was closed without ever being opened, and
// took the manager that the next substream needed.
createSwDoc("tdf167713-shapetext.rtf");
// Each shape stayed in the cell it was written in: the footer's, which the draw page hands out
// first, in C1, and the header's in B1.
CPPUNIT_ASSERT_EQUAL(2, getShapes());
auto xShape1 = getShape(1).queryThrow<text::XTextContent>();
CPPUNIT_ASSERT_EQUAL(u"C1"_ustr,
getProperty<OUString>(xShape1->getAnchor()->getText(), u"CellName"_ustr));
auto xShape2 = getShape(2).queryThrow<text::XTextContent>();
CPPUNIT_ASSERT_EQUAL(u"B1"_ustr,
getProperty<OUString>(xShape2->getAnchor()->getText(), u"CellName"_ustr));
}
// tests should only be added to rtfIMPORT *if* they fail round-tripping in rtfEXPORT
} // end of anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
@@ -1983,7 +1983,13 @@ void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer, RTFSprms* const pSprms,
else if (std::get<0>(aTuple) == RTFBufferTypes::PAR)
parBreak();
else if (std::get<0>(aTuple) == RTFBufferTypes::StartShape)
{
// The shape belongs where the replay stands, not in the buffer being replayed.
RTFBuffer_t* pCurrentBuffer = m_aStates.top().getCurrentBuffer();
m_aStates.top().setCurrentBuffer(nullptr);
m_pSdrImport->resolve(std::get<1>(aTuple)->getShape(), false, RTFSdrImport::SHAPE);
m_aStates.top().setCurrentBuffer(pCurrentBuffer);
}
else if (std::get<0>(aTuple) == RTFBufferTypes::ResolveShape)
{
// Make sure there is no current buffer while replaying the shape,