From 907c7ceb7b27586039262567273efd5ec79e6202 Mon Sep 17 00:00:00 2001
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Date: Wed, 29 Oct 2025 09:43:40 +0100
Subject: [PATCH] Increase robustness of <img> tag in Text component

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
Pick-to: 6.8 6.5 5.15
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>
---

diff --git a/src/quick/items/qquicktextdocument.cpp b/src/quick/items/qquicktextdocument.cpp
index 2f32686..246807f 100644
--- a/src/quick/items/qquicktextdocument.cpp
+++ b/src/quick/items/qquicktextdocument.cpp
@@ -591,9 +591,9 @@
 {
     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 6880056..5095c1d 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 @@
             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 d6534e5..6f37a6a 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -3484,6 +3484,22 @@
                                         << 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)
