From 9f79ab360fd8a504601d3c66a7773eeaa09bffde Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 3 Mar 2019 14:55:20 +0100 Subject: Fix assert in QTextDocument CSS parser on "border-width: 1pt" The code was assuming that if the parsing of the value worked, then it must be a list of 4 variants. But in this case it's just a single length. This came from using 4 values for border-width while other elements use a single value. But the storage is shared. So the fix is to use 4 values everywhere. When reading 4 and there's only one, it gets duplicated, so the caller can just use the first one in that case. Task-number: QTBUG-80496 Change-Id: I682244b6e3781c4d673a62d5e6511dac263c58e8 Reviewed-by: Nils Jeisecke Reviewed-by: Shawn Rutledge --- src/gui/text/qcssparser.cpp | 1 + src/gui/text/qcssparser_p.h | 4 +-- src/gui/text/qtexthtmlparser.cpp | 7 ++-- .../tst_qtextdocumentfragment.cpp | 38 ++++++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index ce7c7610c1..627b3ec8c0 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -443,6 +443,7 @@ void ValueExtractor::lengthValues(const Declaration &decl, int *m) { if (decl.d->parsed.isValid()) { QList v = decl.d->parsed.toList(); + Q_ASSERT(v.size() == 4); for (int i = 0; i < 4; i++) m[i] = lengthValueFromData(qvariant_cast(v.at(i)), f); return; diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h index ab85e76cf3..d91b095a76 100644 --- a/src/gui/text/qcssparser_p.h +++ b/src/gui/text/qcssparser_p.h @@ -856,13 +856,13 @@ struct Q_GUI_EXPORT ValueExtractor int extractStyleFeatures(); bool extractImage(QIcon *icon, Qt::Alignment *a, QSize *size); - int lengthValue(const Declaration &decl); + void lengthValues(const Declaration &decl, int *m); private: void extractFont(); void borderValue(const Declaration &decl, int *width, QCss::BorderStyle *style, QBrush *color); LengthData lengthValue(const Value& v); - void lengthValues(const Declaration &decl, int *m); + int lengthValue(const Declaration &decl); QSize sizeValue(const Declaration &decl); void sizeValues(const Declaration &decl, QSize *radii); diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index 5d37982a8b..b867f42480 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -1209,8 +1209,11 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector if (decl.styleValue() != QCss::BorderStyle_Unknown && decl.styleValue() != QCss::BorderStyle_Native) borderStyle = static_cast(decl.styleValue() - 1); break; - case QCss::BorderWidth: - tableBorder = extractor.lengthValue(decl); + case QCss::BorderWidth: { + int borders[4]; + extractor.lengthValues(decl, borders); + tableBorder = borders[0]; + } break; case QCss::BorderCollapse: borderCollapse = decl.borderCollapseValue(); diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp index b6917f1208..2f5936cf74 100644 --- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp +++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp @@ -182,6 +182,8 @@ private slots: void css_bodyBackground(); void css_tableCellBackground(); void css_tableCellBorder(); + void css_tableCellBorderWidthOneValue(); + void css_tableCellBorderWidthTwoValues(); void css_tableCellBorderShorthand(); void css_tableCellAllBordersShorthand(); void css_tableCellOverrideOneBorder(); @@ -1787,6 +1789,42 @@ void tst_QTextDocumentFragment::css_tableCellBorder() QCOMPARE(cellFormat.topBorderStyle(), QTextFrameFormat::BorderStyle_Groove); } +void tst_QTextDocumentFragment::css_tableCellBorderWidthOneValue() // QTBUG-80496 +{ + const char html[] = "
"; + doc->setHtml(html); + + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::NextBlock); + QTextTable *table = cursor.currentTable(); + QVERIFY(table); + + QTextTableCell cell = table->cellAt(0, 0); + QTextTableCellFormat cellFormat = cell.format().toTableCellFormat(); + QCOMPARE(cellFormat.leftBorder(), qreal(2)); + QCOMPARE(cellFormat.rightBorder(), qreal(2)); + QCOMPARE(cellFormat.bottomBorder(), qreal(2)); + QCOMPARE(cellFormat.topBorder(), qreal(2)); +} + +void tst_QTextDocumentFragment::css_tableCellBorderWidthTwoValues() // QTBUG-80496 +{ + const char html[] = "
"; + doc->setHtml(html); + + cursor.movePosition(QTextCursor::Start); + cursor.movePosition(QTextCursor::NextBlock); + QTextTable *table = cursor.currentTable(); + QVERIFY(table); + + QTextTableCell cell = table->cellAt(0, 0); + QTextTableCellFormat cellFormat = cell.format().toTableCellFormat(); + QCOMPARE(cellFormat.leftBorder(), qreal(3)); + QCOMPARE(cellFormat.rightBorder(), qreal(3)); + QCOMPARE(cellFormat.bottomBorder(), qreal(2)); + QCOMPARE(cellFormat.topBorder(), qreal(2)); +} + void tst_QTextDocumentFragment::css_tableCellBorderShorthand() { const char html[] = "
Foo
"; -- cgit v1.2.3