aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2025-10-29 09:43:40 +0100
committerJani Heikkinen <jani.heikkinen@qt.io>2025-11-20 07:12:11 +0000
commit855f02c96d3c089ea7c0010ebbe4b29fab9cc1ba (patch)
treed12dcbbbb547b63ebd368e6475eba0c5ae5392ff
parent5a263603c34387d3b93dd03985490dd3d1131644 (diff)
Increase robustness of <img> tag in Text component6.9
For Text.StyledText, there was no protection against <img> tags with very large widths or heights. This could cause an application to spend a very long time processing a layout and sometimes crash if the size was too large. We reuse the internal coord limit in QPainter as our maximum size here, similar to what we do in Qt Svg for instance. For Text.RichText, there were no issues in release builds, but in debug builds, you could trigger an overflow assert when rounding the number if it exceeded INT_MAX. For this, we simply cap the width and height at INT_MAX. Fixes: QTBUG-141515 Change-Id: I4bcba16158f5f495a0de38963316effc4c46aae1 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io> (cherry picked from commit 4aaf9bf21f7cc69d73066785e254b664fcc82025) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 907c7ceb7b27586039262567273efd5ec79e6202) Reviewed-by: Antti Kokko <antti.kokko@qt.io>
-rw-r--r--src/quick/items/qquicktextdocument.cpp4
-rw-r--r--src/quick/util/qquickstyledtext.cpp19
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp16
3 files changed, 35 insertions, 4 deletions
diff --git a/src/quick/items/qquicktextdocument.cpp b/src/quick/items/qquicktextdocument.cpp
index d11bae5919..798b0d0599 100644
--- a/src/quick/items/qquicktextdocument.cpp
+++ b/src/quick/items/qquicktextdocument.cpp
@@ -590,9 +590,9 @@ QSizeF QQuickTextImageHandler::intrinsicSize(
{
if (format.isImageFormat()) {
QTextImageFormat imageFormat = format.toImageFormat();
- int width = qRound(imageFormat.width());
+ int width = qRound(qBound(qreal(INT_MIN), imageFormat.width(), qreal(INT_MAX)));
const bool hasWidth = imageFormat.hasProperty(QTextFormat::ImageWidth) && width > 0;
- const int height = qRound(imageFormat.height());
+ const int height = qRound(qBound(qreal(INT_MIN), imageFormat.height(), qreal(INT_MAX)));
const bool hasHeight = imageFormat.hasProperty(QTextFormat::ImageHeight) && height > 0;
const auto maxWidth = imageFormat.maximumWidth();
const bool hasMaxWidth = imageFormat.hasProperty(QTextFormat::ImageMaxWidth) && maxWidth.type() != QTextLength::VariableLength;
diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp
index bb003c19a6..7d21c8999f 100644
--- a/src/quick/util/qquickstyledtext.cpp
+++ b/src/quick/util/qquickstyledtext.cpp
@@ -11,6 +11,11 @@
#include "qquickstyledtext_p.h"
#include <QQmlContext>
#include <QtGui/private/qtexthtmlparser_p.h>
+#include <QtGui/private/qoutlinemapper_p.h>
+
+#ifndef QQUICKSTYLEDPARSER_COORD_LIMIT
+# define QQUICKSTYLEDPARSER_COORD_LIMIT QT_RASTER_COORD_LIMIT
+#endif
Q_STATIC_LOGGING_CATEGORY(lcStyledText, "qt.quick.styledtext")
@@ -660,9 +665,19 @@ void QQuickStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QStri
if (is_equal_ignoring_case(attr.first, QLatin1String("src"))) {
image->url = QUrl(attr.second.toString());
} else if (is_equal_ignoring_case(attr.first, QLatin1String("width"))) {
- image->size.setWidth(attr.second.toString().toInt());
+ bool ok;
+ int v = attr.second.toString().toInt(&ok);
+ if (ok && v <= QQUICKSTYLEDPARSER_COORD_LIMIT)
+ image->size.setWidth(v);
+ else
+ qCWarning(lcStyledText) << "Invalid width provided for <img>";
} else if (is_equal_ignoring_case(attr.first, QLatin1String("height"))) {
- image->size.setHeight(attr.second.toString().toInt());
+ bool ok;
+ int v = attr.second.toString().toInt(&ok);
+ if (ok && v <= QQUICKSTYLEDPARSER_COORD_LIMIT)
+ image->size.setHeight(v);
+ else
+ qCWarning(lcStyledText) << "Invalid height provided for <img>";
} else if (is_equal_ignoring_case(attr.first, QLatin1String("align"))) {
if (is_equal_ignoring_case(attr.second, QLatin1String("top"))) {
image->align = QQuickStyledTextImgTag::Top;
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index d6534e504c..6f37a6a01f 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -3484,6 +3484,22 @@ void tst_qquicktext::imgSize_data()
<< qint64(0x10000)
<< qint64(0x10000)
<< QQuickText::RichText;
+ QTest::newRow("out-of-bounds (styled text)") << QStringLiteral("images/starfish_2.png")
+ << (qint64(INT_MAX) + 1)
+ << (qint64(INT_MAX) + 1)
+ << QQuickText::StyledText;
+ QTest::newRow("out-of-bounds (rich text)") << QStringLiteral("images/starfish_2.png")
+ << (qint64(INT_MAX) + 1)
+ << (qint64(INT_MAX) + 1)
+ << QQuickText::RichText;
+ QTest::newRow("negative out-of-bounds (styled text)") << QStringLiteral("images/starfish_2.png")
+ << (qint64(INT_MIN) - 1)
+ << (qint64(INT_MIN) - 1)
+ << QQuickText::StyledText;
+ QTest::newRow("negative out-of-bounds (rich text)") << QStringLiteral("images/starfish_2.png")
+ << (qint64(INT_MIN) - 1)
+ << (qint64(INT_MIN) - 1)
+ << QQuickText::RichText;
QTest::newRow("large non-existent (styled text)") << QStringLiteral("a")
<< qint64(0x7FFFFF)
<< qint64(0x7FFFFF)