commit:     8ef76cdf289e87e625a0e04f8dcbb474473d13ac
Author:     Sam James <sam <AT> gentoo <DOT> org>
AuthorDate: Tue Sep 16 19:56:52 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Tue Sep 16 19:57:06 2025 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=8ef76cdf

dev-libs/qgpgme: backport UB fix and other post-release patches

Closes: https://bugs.gentoo.org/962891
Signed-off-by: Sam James <sam <AT> gentoo.org>

 dev-libs/qgpgme/files/qgpgme-2.0.0-cmake.patch     |  45 ++++++
 dev-libs/qgpgme/files/qgpgme-2.0.0-typo.patch      | 162 +++++++++++++++++++++
 .../qgpgme/files/qgpgme-2.0.0-ub-followup.patch    |  42 ++++++
 dev-libs/qgpgme/files/qgpgme-2.0.0-ub.patch        |  51 +++++++
 dev-libs/qgpgme/qgpgme-2.0.0-r2.ebuild             |  49 +++++++
 5 files changed, 349 insertions(+)

diff --git a/dev-libs/qgpgme/files/qgpgme-2.0.0-cmake.patch 
b/dev-libs/qgpgme/files/qgpgme-2.0.0-cmake.patch
new file mode 100644
index 000000000000..6af755140487
--- /dev/null
+++ b/dev-libs/qgpgme/files/qgpgme-2.0.0-cmake.patch
@@ -0,0 +1,45 @@
+https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gpgmeqt.git;a=patch;h=71f68de65b902cd9e9d7cf051f1be3f307b1a713
+
+From 71f68de65b902cd9e9d7cf051f1be3f307b1a713 Mon Sep 17 00:00:00 2001
+From: =?utf8?q?Ingo=20Kl=C3=B6cker?= <[email protected]>
+Date: Tue, 3 Jun 2025 17:58:33 +0200
+Subject: [PATCH] build: Fix logic for CONFIGURE_FOR_DISTRIBUTION
+
+* CMakeLists.txt: Set Qt5/Qt6 as required if CONFIGURE_FOR_DISTRIBUTION
+is not set. Also set Qt5Core, Qt6Core, and Qt6CoreTools as required.
+--
+
+Fixes-commit: e598181d462a73f3e0d33fd16a5224880b56d3f6
+---
+ CMakeLists.txt | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index ea7f9b6..90f1372 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -131,8 +131,9 @@ g10_configure_git_hooks()
+ if(BUILD_WITH_QT5)
+     set(QT_MAJOR_VERSION 5)
+     find_package(Qt5 ${QT5_REQUIRED_VERSION} COMPONENTS Core)
+-    if (CONFIGURE_FOR_DISTRIBUTION)
++    if (NOT CONFIGURE_FOR_DISTRIBUTION)
+         set_package_properties(Qt5 PROPERTIES TYPE REQUIRED)
++        set_package_properties(Qt5Core PROPERTIES TYPE REQUIRED)
+     endif()
+     if (LibGpgError_FOUND AND Gpgme_FOUND AND Gpgmepp_FOUND AND Qt5_FOUND)
+         add_subdirectory(src 5/src)
+@@ -145,8 +146,10 @@ endif()
+ if(BUILD_WITH_QT6)
+     set(QT_MAJOR_VERSION 6)
+     find_package(Qt6 ${QT6_REQUIRED_VERSION} CONFIG COMPONENTS Core CoreTools)
+-    if (CONFIGURE_FOR_DISTRIBUTION)
++    if (NOT CONFIGURE_FOR_DISTRIBUTION)
+         set_package_properties(Qt6 PROPERTIES TYPE REQUIRED)
++        set_package_properties(Qt6Core PROPERTIES TYPE REQUIRED)
++        set_package_properties(Qt6CoreTools PROPERTIES TYPE REQUIRED)
+     endif()
+     if (LibGpgError_FOUND AND Gpgme_FOUND AND Gpgmepp_FOUND AND Qt6_FOUND)
+         add_subdirectory(src 6/src)
+-- 
+2.30.2

diff --git a/dev-libs/qgpgme/files/qgpgme-2.0.0-typo.patch 
b/dev-libs/qgpgme/files/qgpgme-2.0.0-typo.patch
new file mode 100644
index 000000000000..9863aa1dfcc9
--- /dev/null
+++ b/dev-libs/qgpgme/files/qgpgme-2.0.0-typo.patch
@@ -0,0 +1,162 @@
+https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gpgmeqt.git;a=commit;h=dcec6832e81b7b972cf7fd85dc7c2efd5464908e
+
+From dcec6832e81b7b972cf7fd85dc7c2efd5464908e Mon Sep 17 00:00:00 2001
+From: Carl Schwan <[email protected]>
+Date: Fri, 13 Jun 2025 10:01:07 +0200
+Subject: [PATCH] Fix typo in outputIsBase64Encoded
+
+--
+* src/{qgpgmesignjob.cpp,qgpgmesignencryptjob.cpp,qgpgmeencryptjob.cpp}:
+  Replace bsse with base in outputIsBase64Encoded
+---
+ src/qgpgmeencryptjob.cpp     | 10 +++++-----
+ src/qgpgmesignencryptjob.cpp | 10 +++++-----
+ src/qgpgmesignjob.cpp        | 10 +++++-----
+ 3 files changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/src/qgpgmeencryptjob.cpp b/src/qgpgmeencryptjob.cpp
+index 7e15eea..041edda 100644
+--- a/src/qgpgmeencryptjob.cpp
++++ b/src/qgpgmeencryptjob.cpp
+@@ -99,7 +99,7 @@ static QGpgMEEncryptJob::result_type encrypt(Context *ctx, 
QThread *thread,
+         const std::weak_ptr<QIODevice> &plainText_,
+         const std::weak_ptr<QIODevice> &cipherText_,
+         const Context::EncryptionFlags eflags,
+-        bool outputIsBsse64Encoded,
++        bool outputIsBase64Encoded,
+         Data::Encoding inputEncoding,
+         const QString &fileName)
+ {
+@@ -127,7 +127,7 @@ static QGpgMEEncryptJob::result_type encrypt(Context *ctx, 
QThread *thread,
+         QGpgME::QByteArrayDataProvider out;
+         Data outdata(&out);
+ 
+-        if (outputIsBsse64Encoded) {
++        if (outputIsBase64Encoded) {
+             outdata.setEncoding(Data::Base64Encoding);
+         }
+ 
+@@ -139,7 +139,7 @@ static QGpgMEEncryptJob::result_type encrypt(Context *ctx, 
QThread *thread,
+         QGpgME::QIODeviceDataProvider out(cipherText);
+         Data outdata(&out);
+ 
+-        if (outputIsBsse64Encoded) {
++        if (outputIsBase64Encoded) {
+             outdata.setEncoding(Data::Base64Encoding);
+         }
+ 
+@@ -151,14 +151,14 @@ static QGpgMEEncryptJob::result_type encrypt(Context 
*ctx, QThread *thread,
+ 
+ }
+ 
+-static QGpgMEEncryptJob::result_type encrypt_qba(Context *ctx, const 
std::vector<Key> &recipients, const QByteArray &plainText, const 
Context::EncryptionFlags eflags, bool outputIsBsse64Encoded, Data::Encoding 
inputEncoding, const QString &fileName)
++static QGpgMEEncryptJob::result_type encrypt_qba(Context *ctx, const 
std::vector<Key> &recipients, const QByteArray &plainText, const 
Context::EncryptionFlags eflags, bool outputIsBase64Encoded, Data::Encoding 
inputEncoding, const QString &fileName)
+ {
+     const std::shared_ptr<QBuffer> buffer(new QBuffer);
+     buffer->setData(plainText);
+     if (!buffer->open(QIODevice::ReadOnly)) {
+         assert(!"This should never happen: QBuffer::open() failed");
+     }
+-    return encrypt(ctx, nullptr, recipients, buffer, 
std::shared_ptr<QIODevice>(), eflags, outputIsBsse64Encoded, inputEncoding, 
fileName);
++    return encrypt(ctx, nullptr, recipients, buffer, 
std::shared_ptr<QIODevice>(), eflags, outputIsBase64Encoded, inputEncoding, 
fileName);
+ }
+ 
+ static QGpgMEEncryptJob::result_type encrypt_to_filename(Context *ctx,
+diff --git a/src/qgpgmesignencryptjob.cpp b/src/qgpgmesignencryptjob.cpp
+index 769a078..65159f0 100644
+--- a/src/qgpgmesignencryptjob.cpp
++++ b/src/qgpgmesignencryptjob.cpp
+@@ -97,7 +97,7 @@ void QGpgMESignEncryptJob::setOutputIsBase64Encoded(bool on)
+ 
+ static QGpgMESignEncryptJob::result_type sign_encrypt(Context *ctx, QThread 
*thread, const std::vector<Key> &signers,
+                                                       const std::vector<Key> 
&recipients, const std::weak_ptr<QIODevice> &plainText_,
+-                                                      const 
std::weak_ptr<QIODevice> &cipherText_, const Context::EncryptionFlags eflags, 
bool outputIsBsse64Encoded, const QString &fileName)
++                                                      const 
std::weak_ptr<QIODevice> &cipherText_, const Context::EncryptionFlags eflags, 
bool outputIsBase64Encoded, const QString &fileName)
+ {
+     const std::shared_ptr<QIODevice> &plainText = plainText_.lock();
+     const std::shared_ptr<QIODevice> &cipherText = cipherText_.lock();
+@@ -129,7 +129,7 @@ static QGpgMESignEncryptJob::result_type 
sign_encrypt(Context *ctx, QThread *thr
+         QGpgME::QByteArrayDataProvider out;
+         Data outdata(&out);
+ 
+-        if (outputIsBsse64Encoded) {
++        if (outputIsBase64Encoded) {
+             outdata.setEncoding(Data::Base64Encoding);
+         }
+ 
+@@ -141,7 +141,7 @@ static QGpgMESignEncryptJob::result_type 
sign_encrypt(Context *ctx, QThread *thr
+         QGpgME::QIODeviceDataProvider out(cipherText);
+         Data outdata(&out);
+ 
+-        if (outputIsBsse64Encoded) {
++        if (outputIsBase64Encoded) {
+             outdata.setEncoding(Data::Base64Encoding);
+         }
+ 
+@@ -154,14 +154,14 @@ static QGpgMESignEncryptJob::result_type 
sign_encrypt(Context *ctx, QThread *thr
+ }
+ 
+ static QGpgMESignEncryptJob::result_type sign_encrypt_qba(Context *ctx, const 
std::vector<Key> &signers,
+-                                                          const 
std::vector<Key> &recipients, const QByteArray &plainText, const 
Context::EncryptionFlags eflags, bool outputIsBsse64Encoded, const QString 
&fileName)
++                                                          const 
std::vector<Key> &recipients, const QByteArray &plainText, const 
Context::EncryptionFlags eflags, bool outputIsBase64Encoded, const QString 
&fileName)
+ {
+     const std::shared_ptr<QBuffer> buffer(new QBuffer);
+     buffer->setData(plainText);
+     if (!buffer->open(QIODevice::ReadOnly)) {
+         assert(!"This should never happen: QBuffer::open() failed");
+     }
+-    return sign_encrypt(ctx, nullptr, signers, recipients, buffer, 
std::shared_ptr<QIODevice>(), eflags, outputIsBsse64Encoded, fileName);
++    return sign_encrypt(ctx, nullptr, signers, recipients, buffer, 
std::shared_ptr<QIODevice>(), eflags, outputIsBase64Encoded, fileName);
+ }
+ 
+ static QGpgMESignEncryptJob::result_type sign_encrypt_to_filename(Context 
*ctx,
+diff --git a/src/qgpgmesignjob.cpp b/src/qgpgmesignjob.cpp
+index f94044b..29ff35f 100644
+--- a/src/qgpgmesignjob.cpp
++++ b/src/qgpgmesignjob.cpp
+@@ -97,7 +97,7 @@ static QGpgMESignJob::result_type sign(Context *ctx, QThread 
*thread,
+                                        const std::weak_ptr<QIODevice> 
&plainText_,
+                                        const std::weak_ptr<QIODevice> 
&signature_,
+                                        SignatureMode mode,
+-                                       bool outputIsBsse64Encoded)
++                                       bool outputIsBase64Encoded)
+ {
+ 
+     const std::shared_ptr<QIODevice> plainText = plainText_.lock();
+@@ -125,7 +125,7 @@ static QGpgMESignJob::result_type sign(Context *ctx, 
QThread *thread,
+         QGpgME::QByteArrayDataProvider out;
+         Data outdata(&out);
+ 
+-        if (outputIsBsse64Encoded) {
++        if (outputIsBase64Encoded) {
+             outdata.setEncoding(Data::Base64Encoding);
+         }
+ 
+@@ -137,7 +137,7 @@ static QGpgMESignJob::result_type sign(Context *ctx, 
QThread *thread,
+         QGpgME::QIODeviceDataProvider out(signature);
+         Data outdata(&out);
+ 
+-        if (outputIsBsse64Encoded) {
++        if (outputIsBase64Encoded) {
+             outdata.setEncoding(Data::Base64Encoding);
+         }
+ 
+@@ -153,14 +153,14 @@ static QGpgMESignJob::result_type sign_qba(Context *ctx,
+         const std::vector<Key> &signers,
+         const QByteArray &plainText,
+         SignatureMode mode,
+-        bool outputIsBsse64Encoded)
++        bool outputIsBase64Encoded)
+ {
+     const std::shared_ptr<QBuffer> buffer(new QBuffer);
+     buffer->setData(plainText);
+     if (!buffer->open(QIODevice::ReadOnly)) {
+         assert(!"This should never happen: QBuffer::open() failed");
+     }
+-    return sign(ctx, nullptr, signers, buffer, std::shared_ptr<QIODevice>(), 
mode, outputIsBsse64Encoded);
++    return sign(ctx, nullptr, signers, buffer, std::shared_ptr<QIODevice>(), 
mode, outputIsBase64Encoded);
+ }
+ 
+ static QGpgMESignJob::result_type sign_to_filename(Context *ctx,
+-- 
+2.30.2

diff --git a/dev-libs/qgpgme/files/qgpgme-2.0.0-ub-followup.patch 
b/dev-libs/qgpgme/files/qgpgme-2.0.0-ub-followup.patch
new file mode 100644
index 000000000000..4b166535ff27
--- /dev/null
+++ b/dev-libs/qgpgme/files/qgpgme-2.0.0-ub-followup.patch
@@ -0,0 +1,42 @@
+https://bugs.gentoo.org/962891
+https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gpgmeqt.git;a=commit;h=86d58c452e0028ea3b59a6ceac7060ece99b4fd2
+
+From 86d58c452e0028ea3b59a6ceac7060ece99b4fd2 Mon Sep 17 00:00:00 2001
+From: =?utf8?q?Ingo=20Kl=C3=B6cker?= <[email protected]>
+Date: Mon, 14 Jul 2025 12:24:09 +0200
+Subject: [PATCH] Improve the fix for the DN parser
+
+* src/dn.cpp (parse_dn_part): Set end of hex string to size of string if
+no non-hex characters were found. Remove special-casing of remove_prefix
+call.
+--
+---
+ src/dn.cpp | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/src/dn.cpp b/src/dn.cpp
+index 90632cc..fb64c6e 100644
+--- a/src/dn.cpp
++++ b/src/dn.cpp
+@@ -215,15 +215,14 @@ static std::pair<std::optional<std::string_view>, 
std::pair<std::string, std::st
+         /* hexstring */
+         stringv.remove_prefix(1);
+         auto endHex = stringv.find_first_not_of("1234567890abcdefABCDEF"sv);
++        if (endHex == std::string_view::npos) {
++            endHex = stringv.size();
++        }
+         auto value = parseHexString(stringv.substr(0, endHex));
+         if (!value.has_value()) {
+             return {};
+         }
+-        if (endHex == std::string_view::npos) {
+-            stringv = {};
+-        } else {
+-            stringv.remove_prefix(endHex);
+-        }
++        stringv.remove_prefix(endHex);
+         dnPair.second = value.value();
+     } else if (stringv.front() == '"') {
+         stringv.remove_prefix(1);
+-- 
+2.30.2

diff --git a/dev-libs/qgpgme/files/qgpgme-2.0.0-ub.patch 
b/dev-libs/qgpgme/files/qgpgme-2.0.0-ub.patch
new file mode 100644
index 000000000000..97e19b9b8792
--- /dev/null
+++ b/dev-libs/qgpgme/files/qgpgme-2.0.0-ub.patch
@@ -0,0 +1,51 @@
+https://bugs.gentoo.org/962891
+https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gpgmeqt.git;a=commit;h=150b23c105f3ea7034e6f106e60686aea4e4a13e
+
+From 150b23c105f3ea7034e6f106e60686aea4e4a13e Mon Sep 17 00:00:00 2001
+From: =?utf8?q?Ingo=20Kl=C3=B6cker?= <[email protected]>
+Date: Sat, 12 Jul 2025 23:10:10 +0200
+Subject: [PATCH] Fix parsing DNs that end with a hex string
+
+* src/dn.cpp (parse_dn_part): Handle case that stringv ends with hex
+string.
+* tests/t-dn.cpp (TestDistinguishedNameParser::testParser_data): Add
+test with DN ending with hex string.
+--
+
+Calling remove_prefix with n > size() (e.g. n == npos) is UB.
+---
+ src/dn.cpp     | 6 +++++-
+ tests/t-dn.cpp | 1 +
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/dn.cpp b/src/dn.cpp
+index 0a407c9..90632cc 100644
+--- a/src/dn.cpp
++++ b/src/dn.cpp
+@@ -219,7 +219,11 @@ static std::pair<std::optional<std::string_view>, 
std::pair<std::string, std::st
+         if (!value.has_value()) {
+             return {};
+         }
+-        stringv.remove_prefix(endHex);
++        if (endHex == std::string_view::npos) {
++            stringv = {};
++        } else {
++            stringv.remove_prefix(endHex);
++        }
+         dnPair.second = value.value();
+     } else if (stringv.front() == '"') {
+         stringv.remove_prefix(1);
+diff --git a/tests/t-dn.cpp b/tests/t-dn.cpp
+index 17f418a..a1b617d 100644
+--- a/tests/t-dn.cpp
++++ b/tests/t-dn.cpp
+@@ -108,6 +108,7 @@ void TestDistinguishedNameParser::testParser_data()
+     QTest::newRow("frompdf2") << u"2.5.4.5=#34,CN=Koch\\, 
Werner,2.5.4.42=#5765726E6572,2.5.4.4=#4B6F6368,C=DE"_s << 
QGpgME::DN::AttributeList {QGpgME::DN::Attribute{u"SerialNumber"_s, u"4"_s}, 
QGpgME::DN::Attribute{u"CN"_s, u"Koch, Werner"_s}, 
QGpgME::DN::Attribute{u"GN"_s, u"Werner"_s}, QGpgME::DN::Attribute{u"SN"_s, 
u"Koch"_s}, QGpgME::DN::Attribute{u"C"_s, u"DE"_s}};
+     QTest::newRow("frompdf2a") << u"2.5.4.5=#34,CN=Koch\\, 
Werner,oid.2.5.4.42=#5765726E6572,OID.2.5.4.4=#4B6F6368,C=DE"_s
+                                << QGpgME::DN::AttributeList 
{QGpgME::DN::Attribute{u"SerialNumber"_s, u"4"_s}, 
QGpgME::DN::Attribute{u"CN"_s, u"Koch, Werner"_s}, 
QGpgME::DN::Attribute{u"GN"_s, u"Werner"_s}, QGpgME::DN::Attribute{u"SN"_s, 
u"Koch"_s}, QGpgME::DN::Attribute{u"C"_s, u"DE"_s}};
++    QTest::newRow("ends with hex string") << u"2.5.4.5=#34"_s << 
QGpgME::DN::AttributeList {QGpgME::DN::Attribute{u"SerialNumber"_s, u"4"_s}};
+ 
+     // weird spacing
+     QTest::newRow("CN =Simple") << u"CN =Simple"_s << 
QGpgME::DN::AttributeList {QGpgME::DN::Attribute{u"CN"_s, u"Simple"_s}};
+-- 
+2.30.2

diff --git a/dev-libs/qgpgme/qgpgme-2.0.0-r2.ebuild 
b/dev-libs/qgpgme/qgpgme-2.0.0-r2.ebuild
new file mode 100644
index 000000000000..60f21b6ceabb
--- /dev/null
+++ b/dev-libs/qgpgme/qgpgme-2.0.0-r2.ebuild
@@ -0,0 +1,49 @@
+# Copyright 1999-2025 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/openpgp-keys/gnupg.asc
+inherit cmake verify-sig
+
+DESCRIPTION="GnuPG Made Easy is a library for making GnuPG easier to use (Qt 
bindings)"
+HOMEPAGE="https://www.gnupg.org/related_software/gpgme";
+SRC_URI="
+       mirror://gnupg/${PN}/${P}.tar.xz
+       verify-sig? ( mirror://gnupg/${PN}/${P}.tar.xz.sig )
+"
+
+LICENSE="GPL-2+ test? ( GPL-2 )"
+SLOT="0/7"
+KEYWORDS="~amd64 ~arm ~arm64 ~hppa ~loong ~ppc ~ppc64 ~riscv ~x86 ~amd64-linux 
~x86-linux ~arm64-macos ~ppc-macos ~x64-macos ~x64-solaris"
+IUSE="test"
+RESTRICT="!test? ( test )"
+
+DEPEND="
+       >=app-crypt/gpgme-${PV%.*}:=
+       >=dev-cpp/gpgmepp-${PV%.*}:=
+       >=dev-libs/libgpg-error-1.47:=
+       >=dev-qt/qtbase-6.5.0:6
+"
+RDEPEND="${DEPEND}
+       !<app-crypt/gpgme-2[qt6(-)]
+       !dev-libs/qgpgme:1
+"
+BDEPEND="verify-sig? ( sec-keys/openpgp-keys-gnupg )"
+
+PATCHES=(
+       "${FILESDIR}"/${P}-cmake.patch
+       "${FILESDIR}"/${P}-typo.patch
+       "${FILESDIR}"/${P}-ub.patch
+       "${FILESDIR}"/${P}-ub-followup.patch
+)
+
+src_configure() {
+       local mycmakeargs=(
+               -DBUILD_WITH_QT5=OFF
+               -DBUILD_WITH_QT6=ON
+               -DBUILD_TESTING=$(usex test)
+       )
+
+       cmake_src_configure
+}

Reply via email to