Package: release.debian.org
Severity: normal
X-Debbugs-Cc: qt6-b...@packages.debian.org, delta...@debian.org
Control: affects -1 + src:qt6-base
User: release.debian....@packages.debian.org
Usertags: unblock

Dear Release Team, 

please unblock package qt6-base.

[ Reason ]
This patch fixes CVE-2025-5992.
Technically, it's 2 patches. The first one is not needed to fix the CVE itself,
but without it, the patch for fixing the CVE cannot be applied and would have
to be rewritten. As a small bonus, the first patch also fixes a bug by
correctly applying a formula.

[ Impact ]
Specifically crafted ICC profiles can cause a denial of service.

[ Tests ]
Both patches are taken directly from upstream where they have been part of
Qt's LTS branch. There they have gone through their usual upstream QA.
No specific tests in Debian have been done.

[ Risks ]
I deem the risks for these 2 patches to be low. They are fairly simple,
have been taken directly from upstream's LTS branch and gone through
their usual QA.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

unblock qt6-base/6.8.2+dfsg-9
diff -Nru qt6-base-6.8.2+dfsg/debian/changelog 
qt6-base-6.8.2+dfsg/debian/changelog
--- qt6-base-6.8.2+dfsg/debian/changelog        2025-06-29 23:52:49.000000000 
+0200
+++ qt6-base-6.8.2+dfsg/debian/changelog        2025-07-18 15:28:20.000000000 
+0200
@@ -1,3 +1,12 @@
+qt6-base (6.8.2+dfsg-9) unstable; urgency=medium
+
+  [ Patrick Franz ]
+  * Backport patch to fix the PQ EOTF formula for BT.2100. This patch is
+    needed to make the patch for CVE-2025-5992 applicable.
+  * Backport patch to fix CVE-2025-5992 (Closes: #1109299).
+
+ -- Patrick Franz <delta...@debian.org>  Fri, 18 Jul 2025 15:28:20 +0200
+
 qt6-base (6.8.2+dfsg-8) unstable; urgency=medium
 
   [ Patrick Franz ]
diff -Nru qt6-base-6.8.2+dfsg/debian/patches/series 
qt6-base-6.8.2+dfsg/debian/patches/series
--- qt6-base-6.8.2+dfsg/debian/patches/series   2025-06-29 23:47:49.000000000 
+0200
+++ qt6-base-6.8.2+dfsg/debian/patches/series   2025-07-18 15:26:54.000000000 
+0200
@@ -1,3 +1,7 @@
+# fixed in 6.8.4/6.9.2
+upstream_QColorTransferGeneric_fix_BT2100PQEOTF.patch
+upstream_cve-2025-5992_input_range_qcolortransformation.diff
+
 # fixed in 6.9.1
 upstream_prevent_recursion_in_qsortfilterproxymodel.diff
 
diff -Nru 
qt6-base-6.8.2+dfsg/debian/patches/upstream_cve-2025-5992_input_range_qcolortransformation.diff
 
qt6-base-6.8.2+dfsg/debian/patches/upstream_cve-2025-5992_input_range_qcolortransformation.diff
--- 
qt6-base-6.8.2+dfsg/debian/patches/upstream_cve-2025-5992_input_range_qcolortransformation.diff
     1970-01-01 01:00:00.000000000 +0100
+++ 
qt6-base-6.8.2+dfsg/debian/patches/upstream_cve-2025-5992_input_range_qcolortransformation.diff
     2025-07-18 15:26:02.000000000 +0200
@@ -0,0 +1,57 @@
+From f4822eec1855231f189e5348dffc29299f6edf93 Mon Sep 17 00:00:00 2001
+From: Samuel Gaist <samuel.ga...@idiap.ch>
+Date: Sat, 24 May 2025 21:07:37 +0200
+Subject: [PATCH] Add clamping to QColorTransferGenericFunction
+
+This ensures that the inputs are within range for the use of these
+function.
+
+Depending on the values passed, they can trigger FE_INVALID errors
+and thus NaN as return values.
+
+This can happen for example when feeding an invalid ICC profile to
+QColorSpace::fromIccProfile.
+
+Credit to OSS-Fuzz
+
+Fixes: QTBUG-137159
+
+Origin: upstream, 
https://download.qt.io/official_releases/qt/6.8/CVE-2025-5992-qtbase-6.8.patch
+---
+
+diff --git a/src/gui/painting/qcolortransfergeneric_p.h 
b/src/gui/painting/qcolortransfergeneric_p.h
+index f9052509df5d..6983651794d8 100644
+--- a/src/gui/painting/qcolortransfergeneric_p.h
++++ b/src/gui/painting/qcolortransfergeneric_p.h
+@@ -66,6 +66,7 @@ private:
+     // HLG from linear [0-12] -> [0-1]
+     static float hlgFromLinear(float x)
+     {
++        x = std::clamp(x, 0.f, 12.f);
+         if (x > 1.f)
+             return m_hlg_a * std::log(x - m_hlg_b) + m_hlg_c;
+         return std::sqrt(x * 0.25f);
+@@ -74,6 +75,7 @@ private:
+     // HLG to linear [0-1] -> [0-12]
+     static float hlgToLinear(float x)
+     {
++        x = std::clamp(x, 0.f, 1.f);
+         if (x < 0.5f)
+             return (x * x) * 4.f;
+         return std::exp((x - m_hlg_c) / m_hlg_a) + m_hlg_b;
+@@ -87,6 +89,7 @@ private:
+     // PQ to linear [0-1] -> [0-64]
+     static float pqToLinear(float e)
+     {
++        e = std::clamp(e, 0.f, 1.f);
+         // m2-th root of E'
+         const float eRoot = std::pow(e, 1.f / m_pq_m2);
+         // rational transform
+@@ -100,6 +103,7 @@ private:
+     // PQ from linear [0-64] -> [0-1]
+     static float pqFromLinear(float fd)
+     {
++        fd = std::clamp(fd, 0.f, 64.f);
+         // scale Fd to Y
+         const float y = fd * (1.f / m_pq_f);
+         // yRoot = Y^m1 -- "root" because m1 is <1
diff -Nru 
qt6-base-6.8.2+dfsg/debian/patches/upstream_QColorTransferGeneric_fix_BT2100PQEOTF.patch
 
qt6-base-6.8.2+dfsg/debian/patches/upstream_QColorTransferGeneric_fix_BT2100PQEOTF.patch
--- 
qt6-base-6.8.2+dfsg/debian/patches/upstream_QColorTransferGeneric_fix_BT2100PQEOTF.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
qt6-base-6.8.2+dfsg/debian/patches/upstream_QColorTransferGeneric_fix_BT2100PQEOTF.patch
    2025-07-18 15:22:53.000000000 +0200
@@ -0,0 +1,76 @@
+From 23e902a4ac81fef2d4f9add722254ad0e5b31347 Mon Sep 17 00:00:00 2001
+From: Giuseppe D'Angelo <giuseppe.dang...@kdab.com>
+Date: Thu, 6 Feb 2025 21:00:55 +0100
+Subject: [PATCH] QColorTransferGeneric: fix the BT.2100 PQ EOTF
+
+The PQ EOTF formula for BT.2100 [1][2] was incorrect. Fix it; while at
+it, rename the variables to match the symbols used in the original
+formula.
+
+The inverse EOTF was correct, but also rename the variables there (for
+the same reason).
+
+[1] https://www.itu.int/rec/R-REC-BT.2100-2-201807-I/en
+[2] https://en.wikipedia.org/wiki/Perceptual_quantizer#Technical_details
+
+Change-Id: I6ce3a609824bee82053a16b3ff3cfc7cb396ce8f
+Reviewed-by: Edward Welbourne <edward.welbou...@qt.io>
+Reviewed-by: Allan Sandfeld Jensen <allan.jen...@qt.io>
+(cherry picked from commit a7ff4679facb9a44dff8b63a7e461ababa6aedfb)
+Reviewed-by: Qt Cherry-pick Bot <cherrypick_...@qt-project.org>
+(cherry picked from commit 35c18eba64b6220e36ea14d32b911342e9d0921c)
+Reviewed-by: Volker Hilsheimer <volker.hilshei...@qt.io>
+---
+ src/gui/painting/qcolortransfergeneric_p.h | 26 +++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+diff --git a/src/gui/painting/qcolortransfergeneric_p.h 
b/src/gui/painting/qcolortransfergeneric_p.h
+index c46f00e9dcf2..f9052509df5d 100644
+--- a/src/gui/painting/qcolortransfergeneric_p.h
++++ b/src/gui/painting/qcolortransfergeneric_p.h
+@@ -17,6 +17,7 @@
+ 
+ #include <QtGui/private/qtguiglobal_p.h>
+ 
++#include <algorithm>
+ #include <cmath>
+ 
+ QT_BEGIN_NAMESPACE
+@@ -82,18 +83,31 @@ class QColorTransferGenericFunction
+     constexpr static float m_hlg_b = 1.f - (4.f * m_hlg_a);
+     constexpr static float m_hlg_c = 0.55991073f; // 0.5 - a * ln(4 * a)
+ 
++    // BT.2100-2 Reference PQ EOTF and inverse (see Table 4)
+     // PQ to linear [0-1] -> [0-64]
+-    static float pqToLinear(float x)
++    static float pqToLinear(float e)
+     {
+-        x = std::pow(x, 1.f / m_pq_m2);
+-        return std::pow((m_pq_c1 - x) / (m_pq_c3 * x - m_pq_c2), (1.f / 
m_pq_m1)) * m_pq_f;
++        // m2-th root of E'
++        const float eRoot = std::pow(e, 1.f / m_pq_m2);
++        // rational transform
++        const float yBase = (std::max)(eRoot - m_pq_c1, 0.0f) / (m_pq_c2 - 
m_pq_c3 * eRoot);
++        // calculate Y = yBase^(1/m1)
++        const float y = std::pow(yBase, 1.f / m_pq_m1);
++        // scale Y to Fd
++        return y * m_pq_f;
+     }
+ 
+     // PQ from linear [0-64] -> [0-1]
+-    static float pqFromLinear(float x)
++    static float pqFromLinear(float fd)
+     {
+-        x = std::pow(x * (1.f / m_pq_f), m_pq_m1);
+-        return std::pow((m_pq_c1 + m_pq_c2 * x) / (1.f + m_pq_c3 * x), 
m_pq_m2);
++        // scale Fd to Y
++        const float y = fd * (1.f / m_pq_f);
++        // yRoot = Y^m1 -- "root" because m1 is <1
++        const float yRoot = std::pow(y, m_pq_m1);
++        // rational transform
++        const float eBase = (m_pq_c1 + m_pq_c2 * yRoot) / (1.f + m_pq_c3 * 
yRoot);
++        // calculate E' = eBase^m2
++        return std::pow(eBase, m_pq_m2);
+     }
+ 
+     constexpr static float m_pq_c1 =  107.f / 128.f; // c3 - c2 + 1

Reply via email to