QTextMarkdownImporter: fix use after free; add fuzz-generated tests
It was possible to end up with a dangling pointer in m_listStack.
This is now avoided by using QPointer and doing nullptr checks before
accessing any QTextList pointer stored there.
We have 2 specimens of garbage that caused crashes before; now they don't.
But only fuzz20450 triggered the dangling pointer in the list stack.
The crash caused by fuzz20580 was fixed by updating md4c from upstream:
4b0fc03077
Change-Id: I8e1eca23b281256a03aea0f55e9ae20f1bdd2a38
Reviewed-by: Robert Loehning <robert.loehning@qt.io>
This commit is contained in:
parent
eaf7f572bf
commit
7447e2b337
@ -577,7 +577,10 @@ void QTextMarkdownImporter::insertBlock()
|
||||
QTextBlockFormat blockFormat;
|
||||
if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) {
|
||||
QTextList *list = m_listStack.top();
|
||||
if (list)
|
||||
blockFormat = list->item(list->count() - 1).blockFormat();
|
||||
else
|
||||
qWarning() << "attempted to insert into a list that no longer exists";
|
||||
}
|
||||
if (m_blockQuoteDepth) {
|
||||
blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth);
|
||||
@ -607,7 +610,7 @@ void QTextMarkdownImporter::insertBlock()
|
||||
}
|
||||
if (m_needsInsertList) {
|
||||
m_listStack.push(m_cursor->createList(m_listFormat));
|
||||
} else if (!m_listStack.isEmpty() && m_listItem) {
|
||||
} else if (!m_listStack.isEmpty() && m_listItem && m_listStack.top()) {
|
||||
m_listStack.top()->add(m_cursor->block());
|
||||
}
|
||||
m_needsInsertList = false;
|
||||
|
@ -113,7 +113,7 @@ private:
|
||||
#endif
|
||||
QString m_blockCodeLanguage;
|
||||
QVector<int> m_nonEmptyTableCells; // in the current row
|
||||
QStack<QTextList *> m_listStack;
|
||||
QStack<QPointer<QTextList>> m_listStack;
|
||||
QStack<QTextCharFormat> m_spanFormatStack;
|
||||
QFont m_monoFont;
|
||||
QPalette m_palette;
|
||||
|
@ -0,0 +1,5 @@
|
||||
<t><EFBFBD>
|
||||
* <20>
|
||||
|
||||
<09>
|
||||
* <20>
|
@ -0,0 +1 @@
|
||||
|
--:|
<?`?><?|`
|
@ -5,5 +5,7 @@ SOURCES += tst_qtextmarkdownimporter.cpp
|
||||
TESTDATA += \
|
||||
data/thematicBreaks.md \
|
||||
data/headingBulletsContinuations.md \
|
||||
data/fuzz20450.md \
|
||||
data/fuzz20580.md \
|
||||
|
||||
DEFINES += SRCDIR=\\\"$$PWD\\\"
|
||||
|
@ -57,6 +57,8 @@ private slots:
|
||||
void lists();
|
||||
void avoidBlankLineAtBeginning_data();
|
||||
void avoidBlankLineAtBeginning();
|
||||
void pathological_data();
|
||||
void pathological();
|
||||
};
|
||||
|
||||
void tst_QTextMarkdownImporter::headingBulletsContinuations()
|
||||
@ -256,5 +258,27 @@ void tst_QTextMarkdownImporter::avoidBlankLineAtBeginning() // QTBUG-81060
|
||||
QCOMPARE(i, expectedNumberOfParagraphs);
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownImporter::pathological_data()
|
||||
{
|
||||
QTest::addColumn<QString>("warning");
|
||||
QTest::newRow("fuzz20450") << "attempted to insert into a list that no longer exists";
|
||||
QTest::newRow("fuzz20580") << "";
|
||||
}
|
||||
|
||||
void tst_QTextMarkdownImporter::pathological() // avoid crashing on crazy input
|
||||
{
|
||||
QFETCH(QString, warning);
|
||||
QString filename = QLatin1String("data/") + QTest::currentDataTag() + QLatin1String(".md");
|
||||
QFile f(QFINDTESTDATA(filename));
|
||||
QVERIFY(f.open(QFile::ReadOnly));
|
||||
#ifdef QT_NO_DEBUG
|
||||
Q_UNUSED(warning)
|
||||
#else
|
||||
if (!warning.isEmpty())
|
||||
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
|
||||
#endif
|
||||
QTextDocument().setMarkdown(f.readAll());
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QTextMarkdownImporter)
|
||||
#include "tst_qtextmarkdownimporter.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user