diff options
author | Christian Ehrlicher <[email protected]> | 2024-11-12 19:49:37 +0100 |
---|---|---|
committer | Christian Ehrlicher <[email protected]> | 2025-03-04 06:10:31 +0100 |
commit | 254fc6a9782b29180cd545e18c34bcaf4cc03a7a (patch) | |
tree | 863272fa4b3c30dc06cd9f4b654fe49f86dacef5 | |
parent | 49f462b7f873ecba6bb205697338a4f1eef6d307 (diff) |
QCssParser: don't allow negative values for cuts in border-image
The spec does not allow this and qDrawBorderPixmap can not handle it.
Pick-to: 6.9 6.8 6.5
Fixes: QTBUG-107904
Change-Id: I5873dec2312865fb96ccccd3cc2292c6b9e1d4f0
Reviewed-by: Oliver Wolff <[email protected]>
Reviewed-by: Volker Hilsheimer <[email protected]>
-rw-r--r-- | src/gui/text/qcssparser.cpp | 7 | ||||
-rw-r--r-- | tests/auto/gui/text/qcssparser/tst_qcssparser.cpp | 116 |
2 files changed, 123 insertions, 0 deletions
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index b58c17bcf79..794e400c34b 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -1821,6 +1821,13 @@ void Declaration::borderImageValue(QString *image, int *cuts, if (v.type != Value::Number) break; cuts[i] = v.variant.toString().toInt(); + if (cuts[i] < 0) { + qWarning("Declaration::borderImageValue: Invalid cut value %d at position %d", + cuts[i], i); + cuts[0] = cuts[1] = cuts[2] = cuts[3] = -1; + i = 4; + break; + } } if (i == 0) cuts[0] = cuts[1] = cuts[2] = cuts[3] = 0; else if (i == 1) cuts[3] = cuts[2] = cuts[1] = cuts[0]; diff --git a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp index fe681b7b2d0..c90cba5b4fc 100644 --- a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp +++ b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp @@ -55,6 +55,10 @@ private slots: void extractFontSize(); void extractBorder_data(); void extractBorder(); + void extractBorderImage_data(); + void extractBorderImage(); + void extractBorderImageCuts_data(); + void extractBorderImageCuts(); void noTextDecoration(); void quotedAndUnquotedIdentifiers(); void whitespaceValues_data(); @@ -1812,6 +1816,118 @@ void tst_QCssParser::extractBorder() QCOMPARE(colors[QCss::TopEdge].color(), expectedTopColor); } +void tst_QCssParser::extractBorderImage_data() +{ + QTest::addColumn<QString>("css"); + QTest::addColumn<QString>("imgUrl"); + QTest::addColumn<QCss::TileMode>("tileMode1"); + QTest::addColumn<QCss::TileMode>("tileMode2"); + + QTest::newRow("no valid url, 1 stretch") + << "border-image: stretch" << QString() + << QCss::TileMode::TileMode_Stretch + << QCss::TileMode::TileMode_Stretch; + QTest::newRow("tilemode stretch") + << "border-image: url(:/image.png) 1 stretch" << ":/image.png" + << QCss::TileMode::TileMode_Stretch + << QCss::TileMode::TileMode_Stretch; + QTest::newRow("tilemode repeat") + << "border-image: url(:/image.png) 1 2 repeat" << ":/image.png" + << QCss::TileMode::TileMode_Repeat + << QCss::TileMode::TileMode_Repeat; + QTest::newRow("tilemode repeat and stretch") + << "border-image: url(:/image.png) 1 2 3 repeat stretch" << ":/image.png" + << QCss::TileMode::TileMode_Repeat + << QCss::TileMode::TileMode_Stretch; +} + +void tst_QCssParser::extractBorderImage() +{ + QFETCH(QString, css); + QFETCH(QString, imgUrl); + QFETCH(QCss::TileMode, tileMode1); + QFETCH(QCss::TileMode, tileMode2); + + css.prepend("dummy {"); + css.append(QLatin1Char('}')); + + QCss::Parser parser(css); + QCss::StyleSheet sheet; + QVERIFY(parser.parse(&sheet)); + + QCOMPARE(sheet.styleRules.size() + sheet.nameIndex.size(), 1); + QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ? + sheet.styleRules.at(0) : *sheet.nameIndex.begin(); + const QList<QCss::Declaration> decls = rule.declarations; + QVERIFY(!decls.isEmpty()); + + QString uri; + QCss::TileMode horizStretch, vertStretch; + int cuts[4]; + for (const auto& decl : decls) { + if (decl.d->propertyId == QCss::BorderImage) { + decl.borderImageValue(&uri, cuts, &horizStretch, &vertStretch); + QCOMPARE(uri, imgUrl); + QCOMPARE(horizStretch, tileMode1); + QCOMPARE(vertStretch, tileMode2); + } + } +} +void tst_QCssParser::extractBorderImageCuts_data() +{ + QTest::addColumn<QString>("css"); + QTest::addColumn<int>("expCut1"); + QTest::addColumn<int>("expCut2"); + QTest::addColumn<int>("expCut3"); + QTest::addColumn<int>("expCut4"); + + const QString url = "border-image: url(:/image.png)"; + QTest::newRow("no cuts") << url << -1 << -1 << -1 << -1; + QTest::newRow("1 cut, valid") << url + " 2" << 2 << 2 << 2 << 2; + QTest::newRow("1 cut, invalid") << url + " -42" << -1 << -1 << -1 << -1; + QTest::newRow("2 cuts, valid") << url + " 2 3" << 2 << 3 << 2 << 3; + QTest::newRow("2 cuts, invalid") << url + " 2 -3" << -1 << -1 << -1 << -1; + QTest::newRow("3 cuts, valid") << url + " 2 3 4" << 2 << 3 << 4 << 3; + QTest::newRow("3 cuts, invalid") << url + " 2 3 -4" << -1 << -1 << -1 << -1; + QTest::newRow("4 cuts, valid") << url + " 2 3 4 5" << 2 << 3 << 4 << 5; + QTest::newRow("4 cuts, invalid") << url + " 2 3 4 -5" << -1 << -1 << -1 << -1; +} + +void tst_QCssParser::extractBorderImageCuts() +{ + QFETCH(QString, css); + QFETCH(int, expCut1); + QFETCH(int, expCut2); + QFETCH(int, expCut3); + QFETCH(int, expCut4); + + css.prepend("dummy {"); + css.append(QLatin1Char('}')); + + QCss::Parser parser(css); + QCss::StyleSheet sheet; + QVERIFY(parser.parse(&sheet)); + + QCOMPARE(sheet.styleRules.size() + sheet.nameIndex.size(), 1); + QCss::StyleRule rule = (!sheet.styleRules.isEmpty()) ? + sheet.styleRules.at(0) : *sheet.nameIndex.begin(); + const QList<QCss::Declaration> decls = rule.declarations; + QVERIFY(!decls.isEmpty()); + + QString uri; + QCss::TileMode horizStretch, vertStretch; + int cuts[4]; + for (const auto& decl : decls) { + if (decl.d->propertyId == QCss::BorderImage) { + decl.borderImageValue(&uri, cuts, &horizStretch, &vertStretch); + QCOMPARE(cuts[0], expCut1); + QCOMPARE(cuts[1], expCut2); + QCOMPARE(cuts[2], expCut3); + QCOMPARE(cuts[3], expCut4); + } + } +} + void tst_QCssParser::noTextDecoration() { QCss::Parser parser("dummy { text-decoration: none; }"); |