Prechádzať zdrojové kódy

package/qt6/qt6base: backport fix for CVE-2023-32763

This commit backports some upstream commits to fix CVE-2023-32763.

To backport the CVE fix, we had to backport two other related patches
to make the backport reasonably clean/straightforward.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
Thomas Petazzoni 11 mesiacov pred
rodič
commit
862543eca0

+ 88 - 0
package/qt6/qt6base/0003-QTextLayout-fix-maximumWidth-for-a-text-containing-s.patch

@@ -0,0 +1,88 @@
+From ffa54deca4ee1e47c112b33ff37f296c4df6c559 Mon Sep 17 00:00:00 2001
+From: Vladimir Belyavsky <belyavskyv@gmail.com>
+Date: Mon, 26 Sep 2022 19:32:50 +0300
+Subject: [PATCH] QTextLayout: fix maximumWidth() for a text containing spaces
+
+When laying out a text and calculating maxWidth, we must _always_ take
+into account the accumulated width of spaces (lbh.spaceData.textWidth)
+regardless of wrapMode, other text content, spaces position, etc.
+
+Fixes: QTBUG-106947
+Change-Id: I2ac9af92ed7dd07c1e040bfcf83949a358d1c9c9
+Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
+Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
+
+Upstream: https://github.com/qt/qtbase/commit/4945fd93f13d2fc34adf260fd0e0325d0794f3f7
+[Thomas: Needed to backport fix for
+https://security-tracker.debian.org/tracker/CVE-2023-32763]
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+---
+ src/gui/text/qtextlayout.cpp                     |  6 +-----
+ .../gui/text/qtextlayout/tst_qtextlayout.cpp     | 16 ++++++++++++++--
+ 2 files changed, 15 insertions(+), 7 deletions(-)
+
+diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
+index e3c69db7e57..9ae6bee2de3 100644
+--- a/src/gui/text/qtextlayout.cpp
++++ b/src/gui/text/qtextlayout.cpp
+@@ -1919,7 +1919,6 @@ void QTextLine::layout_helper(int maxGlyphs)
+             }
+ 
+             if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) {
+-                lbh.spaceData.textWidth = line.width; // ignore spaces that fall out of the line.
+                 goto found;
+             }
+         } else {
+@@ -2105,12 +2104,9 @@ found:
+         eng->maxWidth = qMax(eng->maxWidth, line.textWidth);
+     } else {
+         eng->minWidth = qMax(eng->minWidth, lbh.minw);
+-        eng->maxWidth += line.textWidth;
++        eng->maxWidth += line.textWidth + lbh.spaceData.textWidth;
+     }
+ 
+-    if (line.textWidth > 0 && item < eng->layoutData->items.size())
+-        eng->maxWidth += lbh.spaceData.textWidth;
+-
+     line.textWidth += trailingSpace;
+     if (lbh.spaceData.length) {
+         line.trailingSpaces = lbh.spaceData.length;
+diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+index a8b42b88697..680c62e9825 100644
+--- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
++++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+@@ -124,6 +124,7 @@ private slots:
+     void tooManyDirectionalCharctersCrash_qtbug77819();
+     void softHyphens_data();
+     void softHyphens();
++    void min_maximumWidth_data();
+     void min_maximumWidth();
+ 
+ private:
+@@ -2662,10 +2663,21 @@ void tst_QTextLayout::softHyphens()
+     }
+ }
+ 
++void tst_QTextLayout::min_maximumWidth_data()
++{
++    QTest::addColumn<QString>("text");
++
++    QTest::newRow("long string") << QStringLiteral("lmong_long_crazy_87235982735_23857239682376923876923876-fuwhfhfw-names-AAAA-deeaois2019-03-03.and.more");
++    QTest::newRow("QTBUG-106947") << QStringLiteral("text                                text");
++    QTest::newRow("spaces") << QStringLiteral("                text                text                ");
++}
++
+ void tst_QTextLayout::min_maximumWidth()
+ {
+-    QString longString("lmong_long_crazy_87235982735_23857239682376923876923876-fuwhfhfw-names-AAAA-deeaois2019-03-03.and.more");
+-    QTextLayout layout(longString, testFont);
++    QFETCH(QString, text);
++
++    QTextLayout layout(text, testFont);
++    layout.setCacheEnabled(true);
+ 
+     for (int wrapMode = QTextOption::NoWrap; wrapMode <= QTextOption::WrapAtWordBoundaryOrAnywhere; ++wrapMode) {
+         QTextOption opt;
+-- 
+2.46.0
+

+ 168 - 0
package/qt6/qt6base/0004-QTextLayout-fix-maximumWidth-for-a-text-containing-l.patch

@@ -0,0 +1,168 @@
+From b58616bff6715a6c66bdc9019d008b7918d3ccc8 Mon Sep 17 00:00:00 2001
+From: Vladimir Belyavsky <belyavskyv@gmail.com>
+Date: Tue, 27 Sep 2022 16:57:08 +0300
+Subject: [PATCH] QTextLayout: fix maximumWidth() for a text containing line
+ separator
+
+This is improved version of previous fix
+013c346a8dcbd618febb07884c64c740daf9754d that was reverted because it
+broke some tests for Quick Text. The problem was that it did not work
+correctly in the case the text was wrapped to a fixed width.
+To deal with this we'll accumulate current line full width (as if it
+hadn't been wrapped) in layout data (layoutData->currentMaxWidth).
+Then when the next line is explicitly wrapped by line or paragraph
+separator, this accumulated width will be used to adjust layout's
+maximum width.
+
+Change-Id: Iad7119d9808e1db15fe1fbc5db049c3db928529f
+Fixes: QTBUG-89557
+Fixes: QTBUG-104986
+Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
+
+Upstream: https://github.com/qt/qtbase/commit/991c056438b311566bc4ea543af0f33dfd5dffbb
+[Thomas: Needed to backport fix for
+https://security-tracker.debian.org/tracker/CVE-2023-32763]
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+---
+ src/gui/text/qtextengine.cpp                     |  3 +++
+ src/gui/text/qtextengine_p.h                     |  1 +
+ src/gui/text/qtextlayout.cpp                     | 16 +++++++++++-----
+ .../gui/text/qtextlayout/tst_qtextlayout.cpp     | 16 +++++++++++++++-
+ 4 files changed, 30 insertions(+), 6 deletions(-)
+
+diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
+index ec528760e3b..ef3cdcbaaa7 100644
+--- a/src/gui/text/qtextengine.cpp
++++ b/src/gui/text/qtextengine.cpp
+@@ -2619,6 +2619,7 @@ QTextEngine::LayoutData::LayoutData()
+     haveCharAttributes = false;
+     logClustersPtr = nullptr;
+     available_glyphs = 0;
++    currentMaxWidth = 0;
+ }
+ 
+ QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int _allocated)
+@@ -2651,6 +2652,7 @@ QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int
+     hasBidi = false;
+     layoutState = LayoutEmpty;
+     haveCharAttributes = false;
++    currentMaxWidth = 0;
+ }
+ 
+ QTextEngine::LayoutData::~LayoutData()
+@@ -2736,6 +2738,7 @@ void QTextEngine::freeMemory()
+         layoutData->hasBidi = false;
+         layoutData->layoutState = LayoutEmpty;
+         layoutData->haveCharAttributes = false;
++        layoutData->currentMaxWidth = 0;
+         layoutData->items.clear();
+     }
+     if (specialData)
+diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
+index 925dafe04e2..59e332c64ae 100644
+--- a/src/gui/text/qtextengine_p.h
++++ b/src/gui/text/qtextengine_p.h
+@@ -385,6 +385,7 @@ public:
+         uint layoutState : 2;
+         uint memory_on_stack : 1;
+         uint haveCharAttributes : 1;
++        QFixed currentMaxWidth;
+         QString string;
+         bool reallocate(int totalGlyphs);
+     };
+diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
+index 9ae6bee2de3..2009dd3d0bb 100644
+--- a/src/gui/text/qtextlayout.cpp
++++ b/src/gui/text/qtextlayout.cpp
+@@ -1808,6 +1808,7 @@ void QTextLine::layout_helper(int maxGlyphs)
+     lbh.logClusters = eng->layoutData->logClustersPtr;
+     lbh.previousGlyph = 0;
+ 
++    bool manuallyWrapped = false;
+     bool hasInlineObject = false;
+     QFixed maxInlineObjectHeight = 0;
+ 
+@@ -1883,6 +1884,7 @@ void QTextLine::layout_helper(int maxGlyphs)
+                 lbh.calculateRightBearingForPreviousGlyph();
+             }
+             line += lbh.tmpData;
++            manuallyWrapped = true;
+             goto found;
+         } else if (current.analysis.flags == QScriptAnalysis::Object) {
+             lbh.whiteSpaceOrObject = true;
+@@ -1917,11 +1919,10 @@ void QTextLine::layout_helper(int maxGlyphs)
+                 addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount,
+                                current, lbh.logClusters, lbh.glyphs);
+             }
+-
+-            if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) {
+-                goto found;
+-            }
+         } else {
++            if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width)
++                goto found;
++
+             lbh.whiteSpaceOrObject = false;
+             bool sb_or_ws = false;
+             lbh.saveCurrentGlyph();
+@@ -2104,7 +2105,12 @@ found:
+         eng->maxWidth = qMax(eng->maxWidth, line.textWidth);
+     } else {
+         eng->minWidth = qMax(eng->minWidth, lbh.minw);
+-        eng->maxWidth += line.textWidth + lbh.spaceData.textWidth;
++        eng->layoutData->currentMaxWidth += line.textWidth;
++        if (!manuallyWrapped)
++            eng->layoutData->currentMaxWidth += lbh.spaceData.textWidth;
++        eng->maxWidth = qMax(eng->maxWidth, eng->layoutData->currentMaxWidth);
++        if (manuallyWrapped)
++            eng->layoutData->currentMaxWidth = 0;
+     }
+ 
+     line.textWidth += trailingSpace;
+diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+index 680c62e9825..5b14c4e1491 100644
+--- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
++++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+@@ -2670,17 +2670,28 @@ void tst_QTextLayout::min_maximumWidth_data()
+     QTest::newRow("long string") << QStringLiteral("lmong_long_crazy_87235982735_23857239682376923876923876-fuwhfhfw-names-AAAA-deeaois2019-03-03.and.more");
+     QTest::newRow("QTBUG-106947") << QStringLiteral("text                                text");
+     QTest::newRow("spaces") << QStringLiteral("                text                text                ");
++    QTest::newRow("QTBUG-104986") << QStringLiteral("text\ntext\ntext");
++    QTest::newRow("spaces + line breaks") << QStringLiteral("       \n         text\n                \ntext       \n         ");
+ }
+ 
+ void tst_QTextLayout::min_maximumWidth()
+ {
+     QFETCH(QString, text);
++    text.replace('\n', QChar::LineSeparator);
+ 
+     QTextLayout layout(text, testFont);
+     layout.setCacheEnabled(true);
+ 
++    QTextOption opt;
++    opt.setWrapMode(QTextOption::NoWrap);
++    layout.setTextOption(opt);
++    layout.beginLayout();
++    while (layout.createLine().isValid()) { }
++    layout.endLayout();
++
++    const qreal nonWrappedMaxWidth = layout.maximumWidth();
++
+     for (int wrapMode = QTextOption::NoWrap; wrapMode <= QTextOption::WrapAtWordBoundaryOrAnywhere; ++wrapMode) {
+-        QTextOption opt;
+         opt.setWrapMode((QTextOption::WrapMode)wrapMode);
+         layout.setTextOption(opt);
+         layout.beginLayout();
+@@ -2689,6 +2700,9 @@ void tst_QTextLayout::min_maximumWidth()
+         const qreal minWidth = layout.minimumWidth();
+         const qreal maxWidth = layout.maximumWidth();
+ 
++        QCOMPARE_LE(minWidth, maxWidth);
++        QCOMPARE_LE(maxWidth, nonWrappedMaxWidth); // maxWidth for wrapped text shouldn't exceed maxWidth for the text without wrapping.
++
+         // Try the layout from slightly wider than the widest (maxWidth)
+         // and narrow it down to slighly narrower than minWidth
+         // layout.maximumWidth() should return the same regardless
+-- 
+2.46.0
+

+ 79 - 0
package/qt6/qt6base/0005-Fix-specific-overflow-in-qtextlayout.patch

@@ -0,0 +1,79 @@
+From 693a617236d37e12798013c75d51fd02dd1e1963 Mon Sep 17 00:00:00 2001
+From: Allan Sandfeld Jensen <allan.jensen@qt.io>
+Date: Fri, 5 May 2023 09:51:32 +0200
+Subject: [PATCH] Fix specific overflow in qtextlayout
+
+Adds qAddOverflow and qMulOverflow definitions to QFixed
+
+Fixes: QTBUG-113337
+Pick-to: 6.5 6.5.1 6.2 5.15
+Change-Id: I13579306defceaccdc0fbb1ec0e9b77c6f8d1af9
+Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
+Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
+
+Fixes: https://security-tracker.debian.org/tracker/CVE-2023-32763
+Upstream: https://github.com/qt/qtbase/commit/7b7a01c266b507636eab51a36328c7c72d82d93c
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+---
+ src/gui/painting/qfixed_p.h  | 17 +++++++++++++++++
+ src/gui/text/qtextlayout.cpp |  9 ++++++---
+ 2 files changed, 23 insertions(+), 3 deletions(-)
+
+diff --git a/src/gui/painting/qfixed_p.h b/src/gui/painting/qfixed_p.h
+index f3718a097e5..c0a13d057f5 100644
+--- a/src/gui/painting/qfixed_p.h
++++ b/src/gui/painting/qfixed_p.h
+@@ -18,6 +18,7 @@
+ #include <QtGui/private/qtguiglobal_p.h>
+ #include "QtCore/qdebug.h"
+ #include "QtCore/qpoint.h"
++#include "QtCore/qnumeric.h"
+ #include "QtCore/qsize.h"
+ 
+ QT_BEGIN_NAMESPACE
+@@ -136,6 +137,22 @@ constexpr inline QFixed operator+(uint i, QFixed d) { return d+i; }
+ constexpr inline QFixed operator-(uint i, QFixed d) { return -(d-i); }
+ // constexpr inline QFixed operator*(qreal d, QFixed d2) { return d2*d; }
+ 
++inline bool qAddOverflow(QFixed v1, QFixed v2, QFixed *r)
++{
++    int val;
++    bool result = qAddOverflow(v1.value(), v2.value(), &val);
++    r->setValue(val);
++    return result;
++}
++
++inline bool qMulOverflow(QFixed v1, QFixed v2, QFixed *r)
++{
++    int val;
++    bool result = qMulOverflow(v1.value(), v2.value(), &val);
++    r->setValue(val);
++    return result;
++}
++
+ #ifndef QT_NO_DEBUG_STREAM
+ inline QDebug &operator<<(QDebug &dbg, QFixed f)
+ { return dbg << f.toReal(); }
+diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
+index 2009dd3d0bb..1844f777b4e 100644
+--- a/src/gui/text/qtextlayout.cpp
++++ b/src/gui/text/qtextlayout.cpp
+@@ -2105,9 +2105,12 @@ found:
+         eng->maxWidth = qMax(eng->maxWidth, line.textWidth);
+     } else {
+         eng->minWidth = qMax(eng->minWidth, lbh.minw);
+-        eng->layoutData->currentMaxWidth += line.textWidth;
+-        if (!manuallyWrapped)
+-            eng->layoutData->currentMaxWidth += lbh.spaceData.textWidth;
++        if (qAddOverflow(eng->layoutData->currentMaxWidth, line.textWidth, &eng->layoutData->currentMaxWidth))
++            eng->layoutData->currentMaxWidth = QFIXED_MAX;
++        if (!manuallyWrapped) {
++            if (qAddOverflow(eng->layoutData->currentMaxWidth, lbh.spaceData.textWidth, &eng->layoutData->currentMaxWidth))
++                eng->layoutData->currentMaxWidth = QFIXED_MAX;
++        }
+         eng->maxWidth = qMax(eng->maxWidth, eng->layoutData->currentMaxWidth);
+         if (manuallyWrapped)
+             eng->layoutData->currentMaxWidth = 0;
+-- 
+2.46.0
+

+ 2 - 0
package/qt6/qt6base/qt6base.mk

@@ -13,6 +13,8 @@ QT6BASE_CPE_ID_PRODUCT = qt
 QT6BASE_IGNORE_CVES += CVE-2023-33285
 # 0002-Hsts-match-header-names-case-insensitively.patch
 QT6BASE_IGNORE_CVES += CVE-2023-32762
+# 0005-Fix-specific-overflow-in-qtextlayout.patch
+QT6BASE_IGNORE_CVES += CVE-2023-32763
 
 QT6BASE_CMAKE_BACKEND = ninja