From 6be6802547ce5753e34c2b60d2ad5a4ef7a98b5a Mon Sep 17 00:00:00 2001
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Date: Fri, 31 Oct 2025 09:08:51 +0100
Subject: [PATCH] Rich text: Limit size of text object

When we draw a text object, we need to store this in RAM
since the QTextObjectInterface is QPainter-based. This
could lead to over-allocation if the text object size
was set to be very large. We use the existing image IO
infrastructure for making sure allocations are within
reasonable (and configurable) limits.

Pick-to: 6.5 5.15
Task-number: QTBUG-141515
Change-Id: Ieae06a9e92a7bd078d22ab2314889201c2049122
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
(cherry picked from commit 144ce34e846b3f732bdb003f99b1f9455425416f)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit c3a07c99f9d2328cee4aa48a51d261d243b50d85)
---

diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index 634e234..af73e62 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -11,6 +11,7 @@
 #include <QtGui/qtextobject.h>
 #include <QtGui/qtexttable.h>
 #include <QtGui/qtextlist.h>
+#include <QtGui/qimageiohandler.h>
 
 #include <private/qquicktext_p.h>
 #include <private/qtextdocumentlayout_p.h>
@@ -435,11 +436,14 @@
         }
 
         if (image.isNull()) {
-            image = QImage(size.toSize(), QImage::Format_ARGB32_Premultiplied);
-            image.fill(Qt::transparent);
-            {
-                QPainter painter(&image);
-                handler->drawObject(&painter, image.rect(), textDocument, pos, format);
+            if (QImageIOHandler::allocateImage(size.toSize(),
+                                               QImage::Format_ARGB32_Premultiplied,
+                                               &image)) {
+                image.fill(Qt::transparent);
+                {
+                    QPainter painter(&image);
+                    handler->drawObject(&painter, QRectF({}, size), textDocument, pos, format);
+                }
             }
         }
 
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index a67345e..2b203cf 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -123,6 +123,8 @@
     void imgTagsElide();
     void imgTagsUpdates();
     void imgTagsError();
+    void imgSize_data();
+    void imgSize();
     void fontSizeMode_data();
     void fontSizeMode();
     void fontSizeModeMultiline_data();
@@ -3447,6 +3449,85 @@
     QVERIFY(textObject != nullptr);
 }
 
+void tst_qquicktext::imgSize_data()
+{
+    QTest::addColumn<QString>("url");
+    QTest::addColumn<qint64>("width");
+    QTest::addColumn<qint64>("height");
+    QTest::addColumn<QQuickText::TextFormat>("format");
+
+    QTest::newRow("negative (styled text)") << QStringLiteral("images/starfish_2.png")
+                                         << qint64(-0x7FFFFF)
+                                         << qint64(-0x7FFFFF)
+                                         << QQuickText::StyledText;
+    QTest::newRow("negative (rich text)") << QStringLiteral("images/starfish_2.png")
+                                         << qint64(-0x7FFFFF)
+                                         << qint64(-0x7FFFFF)
+                                         << QQuickText::RichText;
+    QTest::newRow("large (styled text)") << QStringLiteral("images/starfish_2.png")
+                                         << qint64(0x7FFFFF)
+                                         << qint64(0x7FFFFF)
+                                         << QQuickText::StyledText;
+    QTest::newRow("large (right text)") << QStringLiteral("images/starfish_2.png")
+                                        << qint64(0x7FFFFF)
+                                        << qint64(0x7FFFFF)
+                                        << QQuickText::RichText;
+    QTest::newRow("medium (styled text)") << QStringLiteral("images/starfish_2.png")
+                                         << qint64(0x10000)
+                                         << qint64(0x10000)
+                                         << QQuickText::StyledText;
+    QTest::newRow("medium (right text)") << QStringLiteral("images/starfish_2.png")
+                                        << qint64(0x10000)
+                                        << qint64(0x10000)
+                                        << QQuickText::RichText;
+    QTest::newRow("large non-existent (styled text)") << QStringLiteral("a")
+                                                 << qint64(0x7FFFFF)
+                                                 << qint64(0x7FFFFF)
+                                                 << QQuickText::StyledText;
+    QTest::newRow("medium non-existent (styled text)") << QStringLiteral("a")
+                                                 << qint64(0x10000)
+                                                 << qint64(0x10000)
+                                                 << QQuickText::StyledText;
+    QTest::newRow("out-of-bounds non-existent (styled text)") << QStringLiteral("a")
+                                                 << (qint64(INT_MAX) + 1)
+                                                 << (qint64(INT_MAX) + 1)
+                                                 << QQuickText::StyledText;
+    QTest::newRow("large non-existent (rich text)") << QStringLiteral("a")
+                                                 << qint64(0x7FFFFF)
+                                                 << qint64(0x7FFFFF)
+                                                 << QQuickText::RichText;
+    QTest::newRow("medium non-existent (rich text)") << QStringLiteral("a")
+                                                 << qint64(0x10000)
+                                                 << qint64(0x10000)
+                                                 << QQuickText::RichText;
+}
+
+void tst_qquicktext::imgSize()
+{
+    QFETCH(QString, url);
+    QFETCH(qint64, width);
+    QFETCH(qint64, height);
+    QFETCH(QQuickText::TextFormat, format);
+
+    // Reusing imgTagsUpdates.qml here, since it is just an empty Text component
+    QScopedPointer<QQuickView> window(createView(testFile("imgTagsUpdates.qml")));
+    window->show();
+    QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+    QScopedPointer<QQuickText> myText(window->rootObject()->findChild<QQuickText*>("myText"));
+    QVERIFY(myText);
+
+    myText->setTextFormat(format);
+
+    QString imgStr = QStringLiteral("<img src=\"%1\" width=\"%2\" height=\"%3\" />")
+            .arg(url)
+            .arg(width)
+            .arg(height);
+    myText->setText(imgStr);
+
+    QVERIFY(QQuickTest::qWaitForPolish(myText.data()));
+}
+
 void tst_qquicktext::fontSizeMode_data()
 {
     QTest::addColumn<QString>("text");
