From b369dc6021e83e70b95d04f886cfda4dfcf56c45 Mon Sep 17 00:00:00 2001
From: Oliver Eftevaag
Date: Wed, 15 Dec 2021 15:10:00 +0100
Subject: [PATCH] QTextHtmlParser: fix prefix lookahead and html comments
The hasPrefix() function would only use the second 'lookahead' parameter
to check if there was more unparsed text after the current character.
When it's obvious from the codebase that it should actually look ahead
of the current character being processed, and compare againt that future
character.
Html comments were also not handled quite right. Partially because of
the broken hasPrefix() function, but also because it would advance the
current index tracker by 3 instead of 2. Remember that the beginning of
an html comment is would not automatically close, because the current index tracker
would jump over the first 3 dashes when it begins a comment, and the
remaining unprocessed string would be ->
Also, because of the broken lookahead in hasPrefix(), a comment could
actually be started with just
Reviewed-by: Volker Hilsheimer
---
src/gui/text/qtexthtmlparser.cpp | 6 +--
src/gui/text/qtexthtmlparser_p.h | 4 +-
.../text/qtextdocument/tst_qtextdocument.cpp | 41 +++++++++++++++++++
3 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 85877bfe475..f97b8a672a3 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -785,8 +785,8 @@ void QTextHtmlParser::parseCloseTag()
void QTextHtmlParser::parseExclamationTag()
{
++pos;
- if (hasPrefix(QLatin1Char('-'),1) && hasPrefix(QLatin1Char('-'),2)) {
- pos += 3;
+ if (hasPrefix(QLatin1Char('-')) && hasPrefix(QLatin1Char('-'), 1)) {
+ pos += 2;
// eat comments
int end = txt.indexOf(QLatin1String("-->"), pos);
pos = (end >= 0 ? end + 3 : len);
@@ -882,7 +882,7 @@ QString QTextHtmlParser::parseWord()
while (pos < len) {
QChar c = txt.at(pos++);
if (c == QLatin1Char('>')
- || (c == QLatin1Char('/') && hasPrefix(QLatin1Char('>'), 1))
+ || (c == QLatin1Char('/') && hasPrefix(QLatin1Char('>')))
|| c == QLatin1Char('<')
|| c == QLatin1Char('=')
|| c.isSpace()) {
diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h
index 06bbc032a83..a96bf3244f7 100644
--- a/src/gui/text/qtexthtmlparser_p.h
+++ b/src/gui/text/qtexthtmlparser_p.h
@@ -333,7 +333,9 @@ protected:
void applyAttributes(const QStringList &attributes);
void eatSpace();
inline bool hasPrefix(QChar c, int lookahead = 0) const
- {return pos + lookahead < len && txt.at(pos) == c; }
+ {
+ return pos + lookahead < len && txt.at(pos + lookahead) == c;
+ }
int margin(int i, int mar) const;
bool nodeIsChildOf(int i, QTextHTMLElements id) const;
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
index a38defa6562..bb2f3750aa0 100644
--- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -202,6 +202,9 @@ private slots:
void contentsChangeIndices_data();
void contentsChangeIndices();
+ void insertHtmlWithComments_data();
+ void insertHtmlWithComments();
+
private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
void buildRegExpData();
@@ -3917,6 +3920,44 @@ void tst_QTextDocument::contentsChangeIndices()
QCOMPARE(changeAdded - changeRemoved, 1);
}
+void tst_QTextDocument::insertHtmlWithComments_data()
+{
+ QTest::addColumn("html");
+ QTest::addColumn("expectedBlocks");
+
+ QTest::newRow("commentless") << "first
second
third
"
+ << QStringList { "first", "second", "third" };
+ QTest::newRow("normal") << "first
third
"
+ << QStringList { "first", "third" };
+ QTest::newRow("nonClosing") << "first
second
third
"
+ << QStringList { "first", "second", "third" };
+ QTest::newRow("fake") << "first
second
third
"
+ << QStringList { "first", "second", "third" };
+ QTest::newRow("endingNonExistant") << "first
-->second
third
"
+ << QStringList { "first", "-->", "second", "third" };
+}
+
+void tst_QTextDocument::insertHtmlWithComments()
+{
+ QFETCH(QString, html);
+ QFETCH(QStringList, expectedBlocks);
+
+ QTextDocument doc;
+ doc.setHtml(html);
+
+ QCOMPARE(doc.blockCount(), expectedBlocks.count());
+
+ QStringList blockContent;
+ auto currentBlock = doc.begin();
+ while (currentBlock != doc.end()) {
+ blockContent.append(currentBlock.text());
+ currentBlock = currentBlock.next();
+ }
+
+ QCOMPARE(blockContent, expectedBlocks);
+}
QTEST_MAIN(tst_QTextDocument)
#include "tst_qtextdocument.moc"