From 6be6802547ce5753e34c2b60d2ad5a4ef7a98b5a Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt 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 (cherry picked from commit 144ce34e846b3f732bdb003f99b1f9455425416f) Reviewed-by: Qt Cherry-pick Bot (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 #include #include +#include #include #include @@ -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("url"); + QTest::addColumn("width"); + QTest::addColumn("height"); + QTest::addColumn("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 window(createView(testFile("imgTagsUpdates.qml"))); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QScopedPointer myText(window->rootObject()->findChild("myText")); + QVERIFY(myText); + + myText->setTextFormat(format); + + QString imgStr = QStringLiteral("") + .arg(url) + .arg(width) + .arg(height); + myText->setText(imgStr); + + QVERIFY(QQuickTest::qWaitForPolish(myText.data())); +} + void tst_qquicktext::fontSizeMode_data() { QTest::addColumn("text");