summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Ehrlicher <[email protected]>2024-11-12 19:49:37 +0100
committerChristian Ehrlicher <[email protected]>2025-03-04 06:10:31 +0100
commit254fc6a9782b29180cd545e18c34bcaf4cc03a7a (patch)
tree863272fa4b3c30dc06cd9f4b654fe49f86dacef5
parent49f462b7f873ecba6bb205697338a4f1eef6d307 (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.cpp7
-rw-r--r--tests/auto/gui/text/qcssparser/tst_qcssparser.cpp116
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; }");