[neon/qt/qtbase/Neon/release] debian/patches: manually sync to debian patches
Carlos De Maine
null at kde.org
Fri Jul 14 01:59:26 BST 2023
Git commit d027d07b3374a0f446b4b4ef734f8ec78c98ceae by Carlos De Maine.
Committed on 14/07/2023 at 00:48.
Pushed by carlosdem into branch 'Neon/release'.
manually sync to debian patches
D +0 -38 debian/patches/CVE-2021-38593.diff
D +0 -92 debian/patches/CVE-2022-25255.diff
A +330 -0 debian/patches/CVE-2023-24607.diff
A +18 -0 debian/patches/CVE-2023-32762.diff
A +50 -0 debian/patches/CVE-2023-32763.diff
A +77 -0 debian/patches/CVE-2023-33285.diff
A +34 -0 debian/patches/CVE-2023-34410.diff
A +31 -0 debian/patches/a11y_root.diff
A +39 -0 debian/patches/dont_use_O_PATH.diff
A +80 -0 debian/patches/fix_alt_backtick.diff
A +32 -0 debian/patches/fix_qdbusmacros_h.diff
D +0 -58 debian/patches/fix_recursion_crash.diff
A +27 -0 debian/patches/fusion_checkable_qpushbutton.diff
A +25 -0 debian/patches/gnome_wayland.diff
A +66 -0 debian/patches/image_deletion_order.diff
D +0 -80 debian/patches/mysql_field_readonly.diff
A +79 -0 debian/patches/openssl_set_options.diff
A +60 -0 debian/patches/qmenu_set_transient_parent.diff
A +25 -0 debian/patches/qshapedpixmapwindow_no_tooltip.diff
A +44 -0 debian/patches/qxcbwindow_set_geometry.diff
D +0 -50 debian/patches/remove_limit_on_number_of_streams.diff
A +102 -0 debian/patches/revert_startBlocking_removal.diff
M +19 -9 debian/patches/series
A +32 -0 debian/patches/sql_odbc_fix_unicode_check.diff
A +35 -0 debian/patches/sql_odbc_more_unicode_checks.diff
D +0 -18 debian/patches/xdg_filechooser_portal_send_window_id_in_hex.diff
https://invent.kde.org/neon/qt/qtbase/-/commit/d027d07b3374a0f446b4b4ef734f8ec78c98ceae
diff --git a/debian/patches/CVE-2021-38593.diff b/debian/patches/CVE-2021-38593.diff
deleted file mode 100644
index c80e5c91..00000000
--- a/debian/patches/CVE-2021-38593.diff
+++ /dev/null
@@ -1,38 +0,0 @@
-Description: improve fix for avoiding huge number of tiny dashes
- Some pathological cases were not caught by the previous fix.
-Origin: upstream, commits:
- https://code.qt.io/cgit/qt/qtbase.git/commit/?id=6b400e3147dcfd8c
- https://code.qt.io/cgit/qt/qtbase.git/commit/?id=84aba80944a2e1c3
- https://code.qt.io/cgit/qt/qtbase.git/commit/?id=cca8ed0547405b1c
-Last-Update: 2022-06-20
-
---- a/src/gui/painting/qpaintengineex.cpp
-+++ b/src/gui/painting/qpaintengineex.cpp
-@@ -388,7 +388,7 @@ Q_GUI_EXPORT extern bool qt_scaleForTran
- void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen)
- {
- #ifdef QT_DEBUG_DRAW
-- qDebug() << "QPaintEngineEx::stroke()" << pen;
-+ qDebug() << "QPaintEngineEx::stroke()" << inPen;
- #endif
-
- Q_D(QPaintEngineEx);
-@@ -415,15 +415,15 @@ void QPaintEngineEx::stroke(const QVecto
- clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect));
- }
- // Check to avoid generating unwieldy amount of dashes that will not be visible anyway
-- QRectF extentRect = cpRect & clipRect;
-+ qreal pw = pen.widthF() ? pen.widthF() : 1;
-+ QRectF extentRect = cpRect.adjusted(-pw, -pw, pw, pw) & clipRect;
- qreal extent = qMax(extentRect.width(), extentRect.height());
- qreal patternLength = 0;
- const QVector<qreal> pattern = pen.dashPattern();
- const int patternSize = qMin(pattern.size(), 32);
- for (int i = 0; i < patternSize; i++)
- patternLength += qMax(pattern.at(i), qreal(0));
-- if (pen.widthF())
-- patternLength *= pen.widthF();
-+ patternLength *= pw;
- if (qFuzzyIsNull(patternLength)) {
- pen.setStyle(Qt::NoPen);
- } else if (extent / patternLength > 10000) {
diff --git a/debian/patches/CVE-2022-25255.diff b/debian/patches/CVE-2022-25255.diff
deleted file mode 100644
index c9687c09..00000000
--- a/debian/patches/CVE-2022-25255.diff
+++ /dev/null
@@ -1,92 +0,0 @@
-Description: QProcess: ensure we don't accidentally execute something from CWD
- Unless "." (or the empty string) is in $PATH, we're not supposed to find
- executables in the current directory. This is how the Unix shells behave
- and we match their behavior. It's also the behavior Qt had prior to 5.9
- (commit 28666d167aa8e602c0bea25ebc4d51b55005db13). On Windows, searching
- the current directory is the norm, so we keep that behavior.
- .
- This commit does not add an explicit check for an empty return from
- QStandardPaths::findExecutable(). Instead, we allow that empty string to
- go all the way to execve(2), which will fail with ENOENT. We could catch
- it early, before fork(2), but why add code for the error case?
- .
- See https://kde.org/info/security/advisory-20220131-1.txt
-Origin: upstream, https://download.qt.io/official_releases/qt/5.15/CVE-2022-25255-qprocess5-15.diff
-Last-Update: 2022-02-21
-
---- a/src/corelib/io/qprocess_unix.cpp
-+++ b/src/corelib/io/qprocess_unix.cpp
-@@ -1,7 +1,7 @@
- /****************************************************************************
- **
- ** Copyright (C) 2016 The Qt Company Ltd.
--** Copyright (C) 2016 Intel Corporation.
-+** Copyright (C) 2022 Intel Corporation.
- ** Contact: https://www.qt.io/licensing/
- **
- ** This file is part of the QtCore module of the Qt Toolkit.
-@@ -422,14 +422,15 @@ void QProcessPrivate::startProcess()
- // Add the program name to the argument list.
- argv[0] = nullptr;
- if (!program.contains(QLatin1Char('/'))) {
-+ // findExecutable() returns its argument if it's an absolute path,
-+ // otherwise it searches $PATH; returns empty if not found (we handle
-+ // that case much later)
- const QString &exeFilePath = QStandardPaths::findExecutable(program);
-- if (!exeFilePath.isEmpty()) {
-- const QByteArray &tmp = QFile::encodeName(exeFilePath);
-- argv[0] = ::strdup(tmp.constData());
-- }
-- }
-- if (!argv[0])
-+ const QByteArray &tmp = QFile::encodeName(exeFilePath);
-+ argv[0] = ::strdup(tmp.constData());
-+ } else {
- argv[0] = ::strdup(encodedProgramName.constData());
-+ }
-
- // Add every argument to the list
- for (int i = 0; i < arguments.count(); ++i)
-@@ -983,15 +984,16 @@ bool QProcessPrivate::startDetached(qint
- envp = _q_dupEnvironment(environment.d.constData()->vars, &envc);
- }
-
-- QByteArray tmp;
- if (!program.contains(QLatin1Char('/'))) {
-+ // findExecutable() returns its argument if it's an absolute path,
-+ // otherwise it searches $PATH; returns empty if not found (we handle
-+ // that case much later)
- const QString &exeFilePath = QStandardPaths::findExecutable(program);
-- if (!exeFilePath.isEmpty())
-- tmp = QFile::encodeName(exeFilePath);
-+ const QByteArray &tmp = QFile::encodeName(exeFilePath);
-+ argv[0] = ::strdup(tmp.constData());
-+ } else {
-+ argv[0] = ::strdup(QFile::encodeName(program));
- }
-- if (tmp.isEmpty())
-- tmp = QFile::encodeName(program);
-- argv[0] = tmp.data();
-
- if (envp)
- qt_safe_execve(argv[0], argv, envp);
---- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
-+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
-@@ -1498,7 +1498,7 @@ void tst_QApplication::desktopSettingsAw
- environment += QLatin1String("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM=1");
- testProcess.setEnvironment(environment);
- #endif
-- testProcess.start("desktopsettingsaware_helper");
-+ testProcess.start("./desktopsettingsaware_helper");
- QVERIFY2(testProcess.waitForStarted(),
- qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString())));
- QVERIFY(testProcess.waitForFinished(10000));
-@@ -2452,7 +2452,7 @@ void tst_QApplication::qtbug_12673()
- #if QT_CONFIG(process)
- QProcess testProcess;
- QStringList arguments;
-- testProcess.start("modal_helper", arguments);
-+ testProcess.start("./modal_helper", arguments);
- QVERIFY2(testProcess.waitForStarted(),
- qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString())));
- QVERIFY(testProcess.waitForFinished(20000));
diff --git a/debian/patches/CVE-2023-24607.diff b/debian/patches/CVE-2023-24607.diff
new file mode 100644
index 00000000..a7977dcb
--- /dev/null
+++ b/debian/patches/CVE-2023-24607.diff
@@ -0,0 +1,330 @@
+Description: Fix denial-of-service in Qt SQL ODBC driver plugin
+Origin: upstream, https://download.qt.io/official_releases/qt/5.15/CVE-2023-24607-qtbase-5.15.diff
+Last-Update: 2023-02-26
+
+--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
++++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+@@ -92,23 +92,39 @@ inline static QString fromSQLTCHAR(const
+ return result;
+ }
+
++template <size_t SizeOfChar = sizeof(SQLTCHAR)>
++void toSQLTCHARImpl(QVarLengthArray<SQLTCHAR> &result, const QString &input); // primary template undefined
++
++template <typename Container>
++void do_append(QVarLengthArray<SQLTCHAR> &result, const Container &c)
++{
++ result.append(reinterpret_cast<const SQLTCHAR *>(c.data()), c.size());
++}
++
++template <>
++void toSQLTCHARImpl<1>(QVarLengthArray<SQLTCHAR> &result, const QString &input)
++{
++ const auto u8 = input.toUtf8();
++ do_append(result, u8);
++}
++
++template <>
++void toSQLTCHARImpl<2>(QVarLengthArray<SQLTCHAR> &result, const QString &input)
++{
++ do_append(result, input);
++}
++
++template <>
++void toSQLTCHARImpl<4>(QVarLengthArray<SQLTCHAR> &result, const QString &input)
++{
++ const auto u32 = input.toUcs4();
++ do_append(result, u32);
++}
++
+ inline static QVarLengthArray<SQLTCHAR> toSQLTCHAR(const QString &input)
+ {
+ QVarLengthArray<SQLTCHAR> result;
+- result.resize(input.size());
+- switch(sizeof(SQLTCHAR)) {
+- case 1:
+- memcpy(result.data(), input.toUtf8().data(), input.size());
+- break;
+- case 2:
+- memcpy(result.data(), input.unicode(), input.size() * 2);
+- break;
+- case 4:
+- memcpy(result.data(), input.toUcs4().data(), input.size() * 4);
+- break;
+- default:
+- qCritical("sizeof(SQLTCHAR) is %d. Don't know how to handle this.", int(sizeof(SQLTCHAR)));
+- }
++ toSQLTCHARImpl(result, input);
+ result.append(0); // make sure it's null terminated, doesn't matter if it already is, it does if it isn't.
+ return result;
+ }
+@@ -763,6 +779,14 @@ QChar QODBCDriverPrivate::quoteChar()
+ return quote;
+ }
+
++static SQLRETURN qt_string_SQLSetConnectAttr(SQLHDBC handle, SQLINTEGER attr, const QString &val)
++{
++ auto encoded = toSQLTCHAR(val);
++ return SQLSetConnectAttr(handle, attr,
++ encoded.data(),
++ SQLINTEGER(encoded.size() * sizeof(SQLTCHAR))); // size in bytes
++}
++
+
+ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts)
+ {
+@@ -798,10 +822,7 @@ bool QODBCDriverPrivate::setConnectionOp
+ v = val.toUInt();
+ r = SQLSetConnectAttr(hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) size_t(v), 0);
+ } else if (opt.toUpper() == QLatin1String("SQL_ATTR_CURRENT_CATALOG")) {
+- val.utf16(); // 0 terminate
+- r = SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG,
+- toSQLTCHAR(val).data(),
+- val.length()*sizeof(SQLTCHAR));
++ r = qt_string_SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG, val);
+ } else if (opt.toUpper() == QLatin1String("SQL_ATTR_METADATA_ID")) {
+ if (val.toUpper() == QLatin1String("SQL_TRUE")) {
+ v = SQL_TRUE;
+@@ -816,10 +837,7 @@ bool QODBCDriverPrivate::setConnectionOp
+ v = val.toUInt();
+ r = SQLSetConnectAttr(hDbc, SQL_ATTR_PACKET_SIZE, (SQLPOINTER) size_t(v), 0);
+ } else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACEFILE")) {
+- val.utf16(); // 0 terminate
+- r = SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE,
+- toSQLTCHAR(val).data(),
+- val.length()*sizeof(SQLTCHAR));
++ r = qt_string_SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE, val);
+ } else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACE")) {
+ if (val.toUpper() == QLatin1String("SQL_OPT_TRACE_OFF")) {
+ v = SQL_OPT_TRACE_OFF;
+@@ -1022,9 +1040,12 @@ bool QODBCResult::reset (const QString&
+ return false;
+ }
+
+- r = SQLExecDirect(d->hStmt,
+- toSQLTCHAR(query).data(),
+- (SQLINTEGER) query.length());
++ {
++ auto encoded = toSQLTCHAR(query);
++ r = SQLExecDirect(d->hStmt,
++ encoded.data(),
++ SQLINTEGER(encoded.size()));
++ }
+ if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r!= SQL_NO_DATA) {
+ setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
+ "Unable to execute statement"), QSqlError::StatementError, d));
+@@ -1371,9 +1392,12 @@ bool QODBCResult::prepare(const QString&
+ return false;
+ }
+
+- r = SQLPrepare(d->hStmt,
+- toSQLTCHAR(query).data(),
+- (SQLINTEGER) query.length());
++ {
++ auto encoded = toSQLTCHAR(query);
++ r = SQLPrepare(d->hStmt,
++ encoded.data(),
++ SQLINTEGER(encoded.size()));
++ }
+
+ if (r != SQL_SUCCESS) {
+ setLastError(qMakeError(QCoreApplication::translate("QODBCResult",
+@@ -1401,7 +1425,7 @@ bool QODBCResult::exec()
+ SQLCloseCursor(d->hStmt);
+
+ QVector<QVariant>& values = boundValues();
+- QVector<QByteArray> tmpStorage(values.count(), QByteArray()); // holds temporary buffers
++ QVector<QByteArray> tmpStorage(values.count(), QByteArray()); // targets for SQLBindParameter()
+ QVarLengthArray<SQLLEN, 32> indicators(values.count());
+ memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN));
+
+@@ -1580,35 +1604,36 @@ bool QODBCResult::exec()
+ case QVariant::String:
+ if (d->unicode) {
+ QByteArray &ba = tmpStorage[i];
+- QString str = val.toString();
++ {
++ const auto encoded = toSQLTCHAR(val.toString());
++ ba = QByteArray(reinterpret_cast<const char *>(encoded.data()),
++ encoded.size() * sizeof(SQLTCHAR));
++ }
++
+ if (*ind != SQL_NULL_DATA)
+- *ind = str.length() * sizeof(SQLTCHAR);
+- int strSize = str.length() * sizeof(SQLTCHAR);
++ *ind = ba.size();
+
+ if (bindValueType(i) & QSql::Out) {
+- const QVarLengthArray<SQLTCHAR> a(toSQLTCHAR(str));
+- ba = QByteArray((const char *)a.constData(), a.size() * sizeof(SQLTCHAR));
+ r = SQLBindParameter(d->hStmt,
+ i + 1,
+ qParamType[bindValueType(i) & QSql::InOut],
+ SQL_C_TCHAR,
+- strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
++ ba.size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
+ 0, // god knows... don't change this!
+ 0,
+- ba.data(),
++ const_cast<char *>(ba.constData()), // don't detach
+ ba.size(),
+ ind);
+ break;
+ }
+- ba = QByteArray ((const char *)toSQLTCHAR(str).constData(), str.size()*sizeof(SQLTCHAR));
+ r = SQLBindParameter(d->hStmt,
+ i + 1,
+ qParamType[bindValueType(i) & QSql::InOut],
+ SQL_C_TCHAR,
+- strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
+- strSize,
++ ba.size() > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
++ ba.size(),
+ 0,
+- const_cast<char *>(ba.constData()),
++ const_cast<char *>(ba.constData()), // don't detach
+ ba.size(),
+ ind);
+ break;
+@@ -1716,10 +1741,11 @@ bool QODBCResult::exec()
+ case QVariant::String:
+ if (d->unicode) {
+ if (bindValueType(i) & QSql::Out) {
+- const QByteArray &first = tmpStorage.at(i);
+- QVarLengthArray<SQLTCHAR> array;
+- array.append((const SQLTCHAR *)first.constData(), first.size());
+- values[i] = fromSQLTCHAR(array, first.size()/sizeof(SQLTCHAR));
++ const QByteArray &bytes = tmpStorage.at(i);
++ const auto strSize = bytes.size() / int(sizeof(SQLTCHAR));
++ QVarLengthArray<SQLTCHAR> string(strSize);
++ memcpy(string.data(), bytes.data(), strSize * sizeof(SQLTCHAR));
++ values[i] = fromSQLTCHAR(string);
+ }
+ break;
+ }
+@@ -1966,14 +1992,16 @@ bool QODBCDriver::open(const QString & d
+ SQLSMALLINT cb;
+ QVarLengthArray<SQLTCHAR> connOut(1024);
+ memset(connOut.data(), 0, connOut.size() * sizeof(SQLTCHAR));
+- r = SQLDriverConnect(d->hDbc,
+- NULL,
+- toSQLTCHAR(connQStr).data(),
+- (SQLSMALLINT)connQStr.length(),
+- connOut.data(),
+- 1024,
+- &cb,
+- /*SQL_DRIVER_NOPROMPT*/0);
++ {
++ auto encoded = toSQLTCHAR(connQStr);
++ r = SQLDriverConnect(d->hDbc,
++ nullptr,
++ encoded.data(), SQLSMALLINT(encoded.size()),
++ connOut.data(),
++ 1024,
++ &cb,
++ /*SQL_DRIVER_NOPROMPT*/0);
++ }
+
+ if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) {
+ setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d));
+@@ -2352,17 +2380,15 @@ QStringList QODBCDriver::tables(QSql::Ta
+ if (tableType.isEmpty())
+ return tl;
+
+- QString joinedTableTypeString = tableType.join(QLatin1Char(','));
++ {
++ auto joinedTableTypeString = toSQLTCHAR(tableType.join(u','));
+
+- r = SQLTables(hStmt,
+- NULL,
+- 0,
+- NULL,
+- 0,
+- NULL,
+- 0,
+- toSQLTCHAR(joinedTableTypeString).data(),
+- joinedTableTypeString.length() /* characters, not bytes */);
++ r = SQLTables(hStmt,
++ nullptr, 0,
++ nullptr, 0,
++ nullptr, 0,
++ joinedTableTypeString.data(), joinedTableTypeString.size());
++ }
+
+ if (r != SQL_SUCCESS)
+ qSqlWarning(QLatin1String("QODBCDriver::tables Unable to execute table list"), d);
+@@ -2436,28 +2462,30 @@ QSqlIndex QODBCDriver::primaryIndex(cons
+ SQL_ATTR_CURSOR_TYPE,
+ (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
+ SQL_IS_UINTEGER);
+- r = SQLPrimaryKeys(hStmt,
+- catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(),
+- catalog.length(),
+- schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(),
+- schema.length(),
+- toSQLTCHAR(table).data(),
+- table.length() /* in characters, not in bytes */);
++ {
++ auto c = toSQLTCHAR(catalog);
++ auto s = toSQLTCHAR(schema);
++ auto t = toSQLTCHAR(table);
++ r = SQLPrimaryKeys(hStmt,
++ catalog.isEmpty() ? nullptr : c.data(), c.size(),
++ schema.isEmpty() ? nullptr : s.data(), s.size(),
++ t.data(), t.size());
++ }
+
+ // if the SQLPrimaryKeys() call does not succeed (e.g the driver
+ // does not support it) - try an alternative method to get hold of
+ // the primary index (e.g MS Access and FoxPro)
+ if (r != SQL_SUCCESS) {
+- r = SQLSpecialColumns(hStmt,
+- SQL_BEST_ROWID,
+- catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(),
+- catalog.length(),
+- schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(),
+- schema.length(),
+- toSQLTCHAR(table).data(),
+- table.length(),
+- SQL_SCOPE_CURROW,
+- SQL_NULLABLE);
++ auto c = toSQLTCHAR(catalog);
++ auto s = toSQLTCHAR(schema);
++ auto t = toSQLTCHAR(table);
++ r = SQLSpecialColumns(hStmt,
++ SQL_BEST_ROWID,
++ catalog.isEmpty() ? nullptr : c.data(), c.size(),
++ schema.isEmpty() ? nullptr : s.data(), s.size(),
++ t.data(), t.size(),
++ SQL_SCOPE_CURROW,
++ SQL_NULLABLE);
+
+ if (r != SQL_SUCCESS) {
+ qSqlWarning(QLatin1String("QODBCDriver::primaryIndex: Unable to execute primary key list"), d);
+@@ -2538,15 +2566,17 @@ QSqlRecord QODBCDriver::record(const QSt
+ SQL_ATTR_CURSOR_TYPE,
+ (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY,
+ SQL_IS_UINTEGER);
+- r = SQLColumns(hStmt,
+- catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(),
+- catalog.length(),
+- schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(),
+- schema.length(),
+- toSQLTCHAR(table).data(),
+- table.length(),
+- NULL,
+- 0);
++ {
++ auto c = toSQLTCHAR(catalog);
++ auto s = toSQLTCHAR(schema);
++ auto t = toSQLTCHAR(table);
++ r = SQLColumns(hStmt,
++ catalog.isEmpty() ? nullptr : c.data(), c.size(),
++ schema.isEmpty() ? nullptr : s.data(), s.size(),
++ t.data(), t.size(),
++ nullptr,
++ 0);
++ }
+ if (r != SQL_SUCCESS)
+ qSqlWarning(QLatin1String("QODBCDriver::record: Unable to execute column list"), d);
+
diff --git a/debian/patches/CVE-2023-32762.diff b/debian/patches/CVE-2023-32762.diff
new file mode 100644
index 00000000..ef4376da
--- /dev/null
+++ b/debian/patches/CVE-2023-32762.diff
@@ -0,0 +1,18 @@
+Description: hsts: match header names case insensitively
+ Header field names are always considered to be case-insensitive.
+Origin: upstream, https://download.qt.io/official_releases/qt/5.15/CVE-2023-32762-qtbase-5.15.diff
+Last-Update: 2023-05-22
+
+--- a/src/network/access/qhsts.cpp
++++ b/src/network/access/qhsts.cpp
+@@ -364,8 +364,8 @@ quoted-pair = "\" CHAR
+ bool QHstsHeaderParser::parse(const QList<QPair<QByteArray, QByteArray>> &headers)
+ {
+ for (const auto &h : headers) {
+- // We use '==' since header name was already 'trimmed' for us:
+- if (h.first == "Strict-Transport-Security") {
++ // We compare directly because header name was already 'trimmed' for us:
++ if (h.first.compare("Strict-Transport-Security", Qt::CaseInsensitive) == 0) {
+ header = h.second;
+ // RFC6797, 8.1:
+ //
diff --git a/debian/patches/CVE-2023-32763.diff b/debian/patches/CVE-2023-32763.diff
new file mode 100644
index 00000000..3de1b412
--- /dev/null
+++ b/debian/patches/CVE-2023-32763.diff
@@ -0,0 +1,50 @@
+Description: fix buffer overflow in Qt SVG
+ Adds qAddOverflow and qMulOverflow definitions to QFixed.
+Origin: upstream, https://download.qt.io/official_releases/qt/5.15/CVE-2023-32763-qtbase-5.15.diff
+Last-Update: 2023-05-22
+
+--- a/src/gui/painting/qfixed_p.h
++++ b/src/gui/painting/qfixed_p.h
+@@ -54,6 +54,7 @@
+ #include <QtGui/private/qtguiglobal_p.h>
+ #include "QtCore/qdebug.h"
+ #include "QtCore/qpoint.h"
++#include <QtCore/private/qnumeric_p.h>
+ #include "QtCore/qsize.h"
+
+ QT_BEGIN_NAMESPACE
+@@ -182,6 +183,14 @@ Q_DECL_CONSTEXPR inline bool operator<(i
+ Q_DECL_CONSTEXPR inline bool operator>(const QFixed &f, int i) { return f.value() > i * 64; }
+ Q_DECL_CONSTEXPR inline bool operator>(int i, const QFixed &f) { return i * 64 > f.value(); }
+
++inline bool qAddOverflow(QFixed v1, QFixed v2, QFixed *r)
++{
++ int val;
++ bool result = add_overflow(v1.value(), v2.value(), &val);
++ r->setValue(val);
++ return result;
++}
++
+ #ifndef QT_NO_DEBUG_STREAM
+ inline QDebug &operator<<(QDebug &dbg, const QFixed &f)
+ { return dbg << f.toReal(); }
+--- a/src/gui/text/qtextlayout.cpp
++++ b/src/gui/text/qtextlayout.cpp
+@@ -2150,11 +2150,14 @@ found:
+ eng->maxWidth = qMax(eng->maxWidth, line.textWidth);
+ } else {
+ eng->minWidth = qMax(eng->minWidth, lbh.minw);
+- eng->maxWidth += line.textWidth;
++ if (qAddOverflow(eng->maxWidth, line.textWidth, &eng->maxWidth))
++ eng->maxWidth = QFIXED_MAX;
+ }
+
+- if (line.textWidth > 0 && item < eng->layoutData->items.size())
+- eng->maxWidth += lbh.spaceData.textWidth;
++ if (line.textWidth > 0 && item < eng->layoutData->items.size()) {
++ if (qAddOverflow(eng->maxWidth, lbh.spaceData.textWidth, &eng->maxWidth))
++ eng->maxWidth = QFIXED_MAX;
++ }
+
+ line.textWidth += trailingSpace;
+ if (lbh.spaceData.length) {
diff --git a/debian/patches/CVE-2023-33285.diff b/debian/patches/CVE-2023-33285.diff
new file mode 100644
index 00000000..9eadaf64
--- /dev/null
+++ b/debian/patches/CVE-2023-33285.diff
@@ -0,0 +1,77 @@
+Description: QDnsLookup/Unix: make sure we don't overflow the buffer
+ The DNS Records are variable length and encode their size in 16 bits
+ before the Record Data (RDATA). Ensure that both the RDATA and the
+ Record header fields before it fall inside the buffer we have.
+ .
+ Additionally reject any replies containing more than one query records.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=7dba2c87619d558a
+Last-Update: 2023-05-25
+
+--- a/src/network/kernel/qdnslookup_unix.cpp
++++ b/src/network/kernel/qdnslookup_unix.cpp
+@@ -227,7 +227,6 @@ void QDnsLookupRunnable::query(const int
+ // responseLength in case of error, we still can extract the
+ // exact error code from the response.
+ HEADER *header = (HEADER*)response;
+- const int answerCount = ntohs(header->ancount);
+ switch (header->rcode) {
+ case NOERROR:
+ break;
+@@ -260,18 +259,31 @@ void QDnsLookupRunnable::query(const int
+ return;
+ }
+
+- // Skip the query host, type (2 bytes) and class (2 bytes).
+ char host[PACKETSZ], answer[PACKETSZ];
+ unsigned char *p = response + sizeof(HEADER);
+- int status = local_dn_expand(response, response + responseLength, p, host, sizeof(host));
+- if (status < 0) {
++ int status;
++
++ if (ntohs(header->qdcount) == 1) {
++ // Skip the query host, type (2 bytes) and class (2 bytes).
++ status = local_dn_expand(response, response + responseLength, p, host, sizeof(host));
++ if (status < 0) {
++ reply->error = QDnsLookup::InvalidReplyError;
++ reply->errorString = tr("Could not expand domain name");
++ return;
++ }
++ if ((p - response) + status + 4 >= responseLength)
++ header->qdcount = 0xffff; // invalid reply below
++ else
++ p += status + 4;
++ }
++ if (ntohs(header->qdcount) > 1) {
+ reply->error = QDnsLookup::InvalidReplyError;
+- reply->errorString = tr("Could not expand domain name");
++ reply->errorString = tr("Invalid reply received");
+ return;
+ }
+- p += status + 4;
+
+ // Extract results.
++ const int answerCount = ntohs(header->ancount);
+ int answerIndex = 0;
+ while ((p < response + responseLength) && (answerIndex < answerCount)) {
+ status = local_dn_expand(response, response + responseLength, p, host, sizeof(host));
+@@ -283,6 +295,11 @@ void QDnsLookupRunnable::query(const int
+ const QString name = QUrl::fromAce(host);
+
+ p += status;
++
++ if ((p - response) + 10 > responseLength) {
++ // probably just a truncated reply, return what we have
++ return;
++ }
+ const quint16 type = (p[0] << 8) | p[1];
+ p += 2; // RR type
+ p += 2; // RR class
+@@ -290,6 +307,8 @@ void QDnsLookupRunnable::query(const int
+ p += 4;
+ const quint16 size = (p[0] << 8) | p[1];
+ p += 2;
++ if ((p - response) + size > responseLength)
++ return; // truncated
+
+ if (type == QDnsLookup::A) {
+ if (size != 4) {
diff --git a/debian/patches/CVE-2023-34410.diff b/debian/patches/CVE-2023-34410.diff
new file mode 100644
index 00000000..bc5e30dd
--- /dev/null
+++ b/debian/patches/CVE-2023-34410.diff
@@ -0,0 +1,34 @@
+Description: Ssl: Copy the on-demand cert loading bool from default config
+ Otherwise individual sockets will still load system certificates when
+ a chain doesn't match against the configured CA certificates.
+ That's not intended behavior, since specifically setting the CA
+ certificates means you don't want the system certificates to be used.
+ .
+ This is potentially a breaking change because now, if you ever add a
+ CA to the default config, it will disable loading system certificates
+ on demand for all sockets. And the only way to re-enable it is to
+ create a null-QSslConfiguration and set it as the new default.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=57ba6260c0801055
+Last-Update: 2023-06-08
+
+--- a/src/network/ssl/qsslsocket.cpp
++++ b/src/network/ssl/qsslsocket.cpp
+@@ -2221,6 +2221,10 @@ QSslSocketPrivate::QSslSocketPrivate()
+ , flushTriggered(false)
+ {
+ QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration);
++ // If the global configuration doesn't allow root certificates to be loaded
++ // on demand then we have to disable it for this socket as well.
++ if (!configuration.allowRootCertOnDemandLoading)
++ allowRootCertOnDemandLoading = false;
+ }
+
+ /*!
+@@ -2470,6 +2474,7 @@ void QSslConfigurationPrivate::deepCopyD
+ ptr->sessionProtocol = global->sessionProtocol;
+ ptr->ciphers = global->ciphers;
+ ptr->caCertificates = global->caCertificates;
++ ptr->allowRootCertOnDemandLoading = global->allowRootCertOnDemandLoading;
+ ptr->protocol = global->protocol;
+ ptr->peerVerifyMode = global->peerVerifyMode;
+ ptr->peerVerifyDepth = global->peerVerifyDepth;
diff --git a/debian/patches/a11y_root.diff b/debian/patches/a11y_root.diff
new file mode 100644
index 00000000..0a770c95
--- /dev/null
+++ b/debian/patches/a11y_root.diff
@@ -0,0 +1,31 @@
+Description: fix accessibility on XCB when running as root
+ Accessibility actually works when running applications as root, but we
+ would never properly connect, since the enabledChanged signal would be
+ emitted from the constructor in this case. So after connecting the
+ signal, check the value by hand to make sure not to miss the
+ notification.
+ .
+ Only applications running as root would be affected, because all other
+ applications would go through the asynchronous pattern of getting the
+ bus address from dbus instead.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=db346e711c9af505
+Bug: https://bugs.debian.org/1033995
+Last-Update: 2023-04-15
+
+--- a/src/platformsupport/linuxaccessibility/bridge.cpp
++++ b/src/platformsupport/linuxaccessibility/bridge.cpp
+@@ -65,6 +65,14 @@ QSpiAccessibleBridge::QSpiAccessibleBrid
+ {
+ dbusConnection = new DBusConnection();
+ connect(dbusConnection, SIGNAL(enabledChanged(bool)), this, SLOT(enabledChanged(bool)));
++ // Now that we have connected the signal, make sure we didn't miss a change,
++ // e.g. when running as root or when AT_SPI_BUS_ADDRESS is set by hand.
++ // But do that only on next loop, once dbus is really settled.
++ QTimer::singleShot(
++ 0, this, [this]{
++ if (dbusConnection->isEnabled())
++ enabledChanged(true);
++ });
+ }
+
+ void QSpiAccessibleBridge::enabledChanged(bool enabled)
diff --git a/debian/patches/dont_use_O_PATH.diff b/debian/patches/dont_use_O_PATH.diff
new file mode 100644
index 00000000..2a2a8caf
--- /dev/null
+++ b/debian/patches/dont_use_O_PATH.diff
@@ -0,0 +1,39 @@
+Description: OpenFile portal: do not use O_PATH fds
+ Using O_PATH requires correctly specifying whether the fd is writable or
+ not. Stating that the fd is writable without it actually being writable
+ results into rejection on xdg-desktop-portal side. Other implementations
+ like xdg-open or gtk have also moved away from O_PATH fds so this will
+ make a matching implementation and avoid possible rejections from xdp.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=03cbcba7b2b0e42a
+Last-Update: 2023-05-13
+
+--- a/src/platformsupport/services/genericunix/qgenericunixservices.cpp
++++ b/src/platformsupport/services/genericunix/qgenericunixservices.cpp
+@@ -203,8 +203,7 @@ static inline QDBusMessage xdgDesktopPor
+ // handle_token (s) - A string that will be used as the last element of the @handle.
+ // writable (b) - Whether to allow the chosen application to write to the file.
+
+-#ifdef O_PATH
+- const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_PATH);
++ const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_RDONLY);
+ if (fd != -1) {
+ QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
+ QLatin1String("/org/freedesktop/portal/desktop"),
+@@ -214,16 +213,13 @@ static inline QDBusMessage xdgDesktopPor
+ QDBusUnixFileDescriptor descriptor;
+ descriptor.giveFileDescriptor(fd);
+
+- const QVariantMap options = {{QLatin1String("writable"), true}};
++ const QVariantMap options = {};
+
+ // FIXME parent_window_id
+ message << QString() << QVariant::fromValue(descriptor) << options;
+
+ return QDBusConnection::sessionBus().call(message);
+ }
+-#else
+- Q_UNUSED(url)
+-#endif
+
+ return QDBusMessage::createError(QDBusError::InternalError, qt_error_string());
+ }
diff --git a/debian/patches/fix_alt_backtick.diff b/debian/patches/fix_alt_backtick.diff
new file mode 100644
index 00000000..cd094c00
--- /dev/null
+++ b/debian/patches/fix_alt_backtick.diff
@@ -0,0 +1,80 @@
+Description: fix Alt+` shortcut on non-US layouts
+ Make it possible for non-letter-keys with Latin 1 symbols (`, !, @ etc.)
+ to participate in shortcuts also, when the keys generate national
+ symbols on non-Latin layout.
+ .
+ For example, in Russian layout, "`" key generates cyrillic "ё" letter of
+ national alphabet, so shortcuts with the key should still work
+ regardless of the actual layout.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit?id=62e697fd568f6acd
+Last-Update: 2022-12-03
+
+--- a/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
++++ b/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
+@@ -471,7 +471,7 @@ QVector<xkb_keysym_t> QXkbCommon::toKeys
+ } else if (event->modifiers() & Qt::KeypadModifier) {
+ if (qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9)
+ keysyms.append(XKB_KEY_KP_0 + (qtKey - Qt::Key_0));
+- } else if (isLatin(qtKey) && event->text().isUpper()) {
++ } else if (isLatin1(qtKey) && event->text().isUpper()) {
+ keysyms.append(qtKey);
+ }
+
+@@ -523,7 +523,7 @@ int QXkbCommon::keysymToQtKey(xkb_keysym
+ // With standard shortcuts we should prefer a latin character, this is
+ // for checks like "some qkeyevent == QKeySequence::Copy" to work even
+ // when using for example 'russian' keyboard layout.
+- if (!QXkbCommon::isLatin(keysym)) {
++ if (!QXkbCommon::isLatin1(keysym)) {
+ xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code);
+ if (latinKeysym != XKB_KEY_NoSymbol)
+ keysym = latinKeysym;
+@@ -546,7 +546,7 @@ static int keysymToQtKey_internal(xkb_ke
+ } else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) {
+ // numeric keypad keys
+ qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0);
+- } else if (QXkbCommon::isLatin(keysym)) {
++ } else if (QXkbCommon::isLatin1(keysym)) {
+ qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym);
+ } else {
+ // check if we have a direct mapping
+@@ -678,7 +678,7 @@ QList<int> QXkbCommon::possibleKeys(xkb_
+ Qt::KeyboardModifiers neededMods = ModsTbl[i];
+ if ((modifiers & neededMods) == neededMods) {
+ if (i == 8) {
+- if (isLatin(baseQtKey))
++ if (isLatin1(baseQtKey))
+ continue;
+ // add a latin key as a fall back key
+ sym = lookupLatinKeysym(state, keycode);
+@@ -733,7 +733,7 @@ void QXkbCommon::verifyHasLatinLayout(xk
+ for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
+ for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
+ xkb_keymap_key_get_syms_by_level(keymap, code, layout, 0, &keysyms);
+- if (keysyms && isLatin(keysyms[0]))
++ if (keysyms && isLatin1(keysyms[0]))
+ nrLatinKeys++;
+ if (nrLatinKeys > 10) // arbitrarily chosen threshold
+ return;
+@@ -766,7 +766,7 @@ xkb_keysym_t QXkbCommon::lookupLatinKeys
+ xkb_level_index_t level = xkb_state_key_get_level(state, keycode, layout);
+ if (xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms) != 1)
+ continue;
+- if (isLatin(syms[0])) {
++ if (isLatin1(syms[0])) {
+ sym = syms[0];
+ break;
+ }
+--- a/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
++++ b/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
+@@ -94,8 +94,8 @@ public:
+ static void verifyHasLatinLayout(xkb_keymap *keymap);
+ static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode);
+
+- static bool isLatin(xkb_keysym_t sym) {
+- return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z'));
++ static bool isLatin1(xkb_keysym_t sym) {
++ return sym <= 0xff;
+ }
+ static bool isKeypad(xkb_keysym_t sym) {
+ return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9;
diff --git a/debian/patches/fix_qdbusmacros_h.diff b/debian/patches/fix_qdbusmacros_h.diff
new file mode 100644
index 00000000..563df7f2
--- /dev/null
+++ b/debian/patches/fix_qdbusmacros_h.diff
@@ -0,0 +1,32 @@
+Description: fix capitalization error in auto-generated qdbusmacros.h include
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=dca0304c26012a57
+Last-Update: 2023-05-13
+
+--- a/include/QtDBus/qdbusmacros.h
++++ b/include/QtDBus/qdbusmacros.h
+@@ -1,11 +1,11 @@
+ #ifndef DEPRECATED_HEADER_QtDBus_qdbusmacros_h
+ #define DEPRECATED_HEADER_QtDBus_qdbusmacros_h
+ #if defined(__GNUC__)
+-# warning Header <QtDBus/qdbusmacros.h> is deprecated. Please include <QtDbus/qtdbusglobal.h> instead.
++# warning Header <QtDBus/qdbusmacros.h> is deprecated. Please include <QtDBus/qtdbusglobal.h> instead.
+ #elif defined(_MSC_VER)
+-# pragma message ("Header <QtDBus/qdbusmacros.h> is deprecated. Please include <QtDbus/qtdbusglobal.h> instead.")
++# pragma message ("Header <QtDBus/qdbusmacros.h> is deprecated. Please include <QtDBus/qtdbusglobal.h> instead.")
+ #endif
+-#include <QtDbus/qtdbusglobal.h>
++#include <QtDBus/qtdbusglobal.h>
+ #if 0
+ #pragma qt_no_master_include
+ #endif
+--- a/sync.profile
++++ b/sync.profile
+@@ -77,7 +77,7 @@
+ "qsql.h" => "QtSql/qtsqlglobal.h"
+ },
+ "QtDBus" => {
+- "qdbusmacros.h" => "QtDbus/qtdbusglobal.h"
++ "qdbusmacros.h" => "QtDBus/qtdbusglobal.h"
+ },
+ "QtTest" => {
+ "qtest_global.h" => "QtTest/qttestglobal.h"
diff --git a/debian/patches/fix_recursion_crash.diff b/debian/patches/fix_recursion_crash.diff
deleted file mode 100644
index 91176014..00000000
--- a/debian/patches/fix_recursion_crash.diff
+++ /dev/null
@@ -1,58 +0,0 @@
-Description: fix recursion crash when calling setStyleSheet with qproperty-styleSheet
- When calling setStyleSheet with property qproperty-styleSheet,
- QStyleSheetStyle::polish will call QStyleSheetStyle::setProperties,
- and then QStyleSheetStyle::setProperties goes on to call setProperty.
- Because there is property qproperty-styleSheet, it will update
- stylesheet by calling QStyleSheetStyle::polish.
- This causes the recursive call to crash.
-Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=e9cdcc7cb314586a
-Last-Update: 2021-11-13
-
---- a/src/widgets/styles/qstylesheetstyle.cpp
-+++ b/src/widgets/styles/qstylesheetstyle.cpp
-@@ -2649,6 +2649,9 @@ void QStyleSheetStyle::setProperties(QWi
- default: v = decl.d->values.at(0).variant; break;
- }
-
-+ if (propertyL1 == QByteArray("styleSheet") && value == v)
-+ continue;
-+
- w->setProperty(propertyL1, v);
- }
- }
-Index: qtbase/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
-===================================================================
---- qtbase.orig/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
-+++ qtbase/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
-@@ -94,6 +94,7 @@ private slots:
- void layoutSpacing();
- #endif
- void qproperty();
-+ void qproperty_styleSheet();
- void palettePropagation_data();
- void palettePropagation();
- void fontPropagation_data();
-@@ -678,6 +679,23 @@ void tst_QStyleSheetStyle::qproperty()
- QCOMPARE(pb.isChecked(), false);
- }
-
-+void tst_QStyleSheetStyle::qproperty_styleSheet()
-+{
-+ QWidget w;
-+ auto checkBox = new QCheckBox("check", &w);
-+ QString sheet = R"(QCheckBox { qproperty-styleSheet: "QCheckBox { qproperty-text: foobar; }"; })";
-+
-+ QVERIFY(w.property("styleSheet").toString().isEmpty());
-+
-+ w.setStyleSheet(sheet);
-+ QCOMPARE(checkBox->text(), "check");
-+
-+ //recursion crash
-+ w.ensurePolished();
-+ QCOMPARE(w.property("styleSheet").toString(), sheet);
-+ QCOMPARE(checkBox->text(), "foobar");
-+}
-+
- namespace ns {
- class PushButton1 : public QPushButton {
- Q_OBJECT
diff --git a/debian/patches/fusion_checkable_qpushbutton.diff b/debian/patches/fusion_checkable_qpushbutton.diff
new file mode 100644
index 00000000..239cc386
--- /dev/null
+++ b/debian/patches/fusion_checkable_qpushbutton.diff
@@ -0,0 +1,27 @@
+Description: QPushButton/fusion style: don't ignore QIcon::On icon
+ The fusion style did ignore the QIcon::On icon because it reset
+ State_On to avoid the visual shift of a pressed button.
+ But it's not needed to reset this flag - the shift does not happen
+ because the fusion style does return 0 as offset for
+ PM_ButtonShiftHorizontal/PM_ButtonShiftVertical so no shifting will
+ happen.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=e9ccdf4d84157173
+Last-Update: 2021-08-10
+
+--- a/src/widgets/styles/qfusionstyle.cpp
++++ b/src/widgets/styles/qfusionstyle.cpp
+@@ -1772,14 +1772,6 @@ void QFusionStyle::drawControl(ControlEl
+ proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget);
+ }
+ break;
+- case CE_PushButtonLabel:
+- if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
+- QStyleOptionButton b(*button);
+- // no PM_ButtonShiftHorizontal and PM_ButtonShiftVertical for fusion style
+- b.state &= ~(State_On | State_Sunken);
+- QCommonStyle::drawControl(element, &b, painter, widget);
+- }
+- break;
+ case CE_MenuBarEmptyArea:
+ painter->save();
+ {
diff --git a/debian/patches/gnome_wayland.diff b/debian/patches/gnome_wayland.diff
new file mode 100644
index 00000000..9f7375c7
--- /dev/null
+++ b/debian/patches/gnome_wayland.diff
@@ -0,0 +1,25 @@
+Description: use wayland platform plugin on GNOME wayland sessions by default
+ Qt wayland platform plugin has improved quite a lot and it is now pretty
+ much usable on Gnome. It also improves user experience a lot on HiDPI
+ displays.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=dda7dab8274991e4
+Last-Update: 2022-10-16
+
+--- a/src/gui/kernel/qguiapplication.cpp
++++ b/src/gui/kernel/qguiapplication.cpp
+@@ -1412,14 +1412,7 @@ void QGuiApplicationPrivate::createPlatf
+ if (sessionType == QByteArrayLiteral("x11") && !platformName.contains(QByteArrayLiteral("xcb"))) {
+ platformName = QByteArrayLiteral("xcb");
+ } else if (sessionType == QByteArrayLiteral("wayland") && !platformName.contains(QByteArrayLiteral("wayland"))) {
+- QByteArray currentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toLower();
+- QByteArray sessionDesktop = qgetenv("XDG_SESSION_DESKTOP").toLower();
+- if (currentDesktop.contains("gnome") || sessionDesktop.contains("gnome")) {
+- qInfo() << "Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome."
+- << "Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.";
+- } else {
+- platformName = QByteArrayLiteral("wayland");
+- }
++ platformName = QByteArrayLiteral("wayland");
+ }
+ }
+ #ifdef QT_QPA_DEFAULT_PLATFORM_NAME
diff --git a/debian/patches/image_deletion_order.diff b/debian/patches/image_deletion_order.diff
new file mode 100644
index 00000000..b20f5cb0
--- /dev/null
+++ b/debian/patches/image_deletion_order.diff
@@ -0,0 +1,66 @@
+Description: fix deletion order in QImageReader/Writer destructors
+ The device would be deleted before the image format handler, and hence
+ be a dangling pointer that could easily cause a crash if the handler
+ or codec would access it on destruction, e.g. for cleanup.
+Origin: upstream, commits
+ https://code.qt.io/cgit/qt/qtbase.git/commit/?id=f091026be1deb4b4
+ https://code.qt.io/cgit/qt/qtbase.git/commit/?id=5633cb69f68ca3d3
+Last-Update: 2023-02-26
+
+--- a/src/gui/image/qimagereader.cpp
++++ b/src/gui/image/qimagereader.cpp
+@@ -515,9 +515,9 @@ QImageReaderPrivate::QImageReaderPrivate
+ */
+ QImageReaderPrivate::~QImageReaderPrivate()
+ {
++ delete handler;
+ if (deleteDevice)
+ delete device;
+- delete handler;
+ }
+
+ /*!
+@@ -774,12 +774,12 @@ bool QImageReader::decideFormatFromConte
+ */
+ void QImageReader::setDevice(QIODevice *device)
+ {
++ delete d->handler;
++ d->handler = nullptr;
+ if (d->device && d->deleteDevice)
+ delete d->device;
+ d->device = device;
+ d->deleteDevice = false;
+- delete d->handler;
+- d->handler = nullptr;
+ d->text.clear();
+ }
+
+--- a/src/gui/image/qimagewriter.cpp
++++ b/src/gui/image/qimagewriter.cpp
+@@ -349,9 +349,9 @@ QImageWriter::QImageWriter(const QString
+ */
+ QImageWriter::~QImageWriter()
+ {
++ delete d->handler;
+ if (d->deleteDevice)
+ delete d->device;
+- delete d->handler;
+ delete d;
+ }
+
+@@ -396,13 +396,13 @@ QByteArray QImageWriter::format() const
+ */
+ void QImageWriter::setDevice(QIODevice *device)
+ {
++ delete d->handler;
++ d->handler = nullptr;
+ if (d->device && d->deleteDevice)
+ delete d->device;
+
+ d->device = device;
+ d->deleteDevice = false;
+- delete d->handler;
+- d->handler = nullptr;
+ }
+
+ /*!
diff --git a/debian/patches/mysql_field_readonly.diff b/debian/patches/mysql_field_readonly.diff
deleted file mode 100644
index c33b7524..00000000
--- a/debian/patches/mysql_field_readonly.diff
+++ /dev/null
@@ -1,80 +0,0 @@
-Description: treat the MYSQL_FIELD as read-only
- The MariaDB-connector-c version 3.2 and MariaDB server version 10.6
- cooperate to avoid re-transferring the query metadata, so the fact that
- we were modifying it was causing it to improperly decode the DATETIME
- data types into string, as we had asked. We ended up with a 7-byte
- string that was actually the date binary-encoded.
-Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=549ee216fd5bf2b3
-Last-Update: 2021-11-13
-
---- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
-+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
-@@ -223,7 +223,7 @@ public:
- struct QMyField
- {
- char *outField = nullptr;
-- MYSQL_FIELD *myField = nullptr;
-+ const MYSQL_FIELD *myField = nullptr;
- QMetaType::Type type = QMetaType::UnknownType;
- my_bool nullIndicator = false;
- ulong bufLength = 0ul;
-@@ -361,11 +361,10 @@ static bool qIsInteger(int t)
- void QMYSQLResultPrivate::bindBlobs()
- {
- int i;
-- MYSQL_FIELD *fieldInfo;
- MYSQL_BIND *bind;
-
- for(i = 0; i < fields.count(); ++i) {
-- fieldInfo = fields.at(i).myField;
-+ const MYSQL_FIELD *fieldInfo = fields.at(i).myField;
- if (qIsBlob(inBinds[i].buffer_type) && meta && fieldInfo) {
- bind = &inBinds[i];
- bind->buffer_length = fieldInfo->max_length;
-@@ -392,35 +391,34 @@ bool QMYSQLResultPrivate::bindInValues()
- inBinds = new MYSQL_BIND[fields.size()];
- memset(inBinds, 0, fields.size() * sizeof(MYSQL_BIND));
-
-- MYSQL_FIELD *fieldInfo;
-+ const MYSQL_FIELD *fieldInfo;
-
- while((fieldInfo = mysql_fetch_field(meta))) {
-+ MYSQL_BIND *bind = &inBinds[i];
-+
- QMyField &f = fields[i];
- f.myField = fieldInfo;
--
-+ bind->buffer_length = f.bufLength = fieldInfo->length + 1;
-+ bind->buffer_type = fieldInfo->type;
- f.type = qDecodeMYSQLType(fieldInfo->type, fieldInfo->flags);
- if (qIsBlob(fieldInfo->type)) {
- // the size of a blob-field is available as soon as we call
- // mysql_stmt_store_result()
- // after mysql_stmt_exec() in QMYSQLResult::exec()
-- fieldInfo->length = 0;
-+ bind->buffer_length = f.bufLength = 0;
- hasBlobs = true;
- } else if (qIsInteger(f.type)) {
-- fieldInfo->length = 8;
-+ bind->buffer_length = f.bufLength = 8;
- } else {
-- fieldInfo->type = MYSQL_TYPE_STRING;
-+ bind->buffer_type = MYSQL_TYPE_STRING;
- }
-- bind = &inBinds[i];
-- field = new char[fieldInfo->length + 1];
-- memset(field, 0, fieldInfo->length + 1);
-
-- bind->buffer_type = fieldInfo->type;
-- bind->buffer = field;
-- bind->buffer_length = f.bufLength = fieldInfo->length + 1;
- bind->is_null = &f.nullIndicator;
- bind->length = &f.bufLength;
- bind->is_unsigned = fieldInfo->flags & UNSIGNED_FLAG ? 1 : 0;
-- f.outField=field;
-+
-+ char *field = new char[bind->buffer_length + 1]{};
-+ bind->buffer = f.outField = field;
-
- ++i;
- }
diff --git a/debian/patches/openssl_set_options.diff b/debian/patches/openssl_set_options.diff
new file mode 100644
index 00000000..62947914
--- /dev/null
+++ b/debian/patches/openssl_set_options.diff
@@ -0,0 +1,79 @@
+Description: update function argument of SSL_CTX_set_options
+ openssl3 uses uint64_t for the options argument in SSL_CTX_set_options,
+ older ones used long.
+ sizeof(long) is not the same on any platform as sizeof(uint64_t)
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=e995bfc0ea783c15
+ Backported for 5.15 by the patch author, Michael Saxl.
+Last-Update: 2022-08-07
+
+--- a/src/network/ssl/qsslcontext_openssl.cpp
++++ b/src/network/ssl/qsslcontext_openssl.cpp
+@@ -455,7 +455,7 @@ init_context:
+ }
+
+ // Enable bug workarounds.
+- long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
++ qssloptions options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
+ q_SSL_CTX_set_options(sslContext->ctx, options);
+
+ // Tell OpenSSL to release memory early
+--- a/src/network/ssl/qsslsocket_openssl.cpp
++++ b/src/network/ssl/qsslsocket_openssl.cpp
+@@ -550,9 +550,9 @@ static void q_loadCiphersForConnection(S
+ // Defined in qsslsocket.cpp
+ void q_setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers);
+
+-long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
++qssloptions QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
+ {
+- long options;
++ qssloptions options;
+ if (protocol == QSsl::TlsV1SslV3)
+ options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
+ else if (protocol == QSsl::SecureProtocols)
+--- a/src/network/ssl/qsslsocket_openssl_p.h
++++ b/src/network/ssl/qsslsocket_openssl_p.h
+@@ -107,6 +107,12 @@
+
+ QT_BEGIN_NAMESPACE
+
++#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
++typedef uint64_t qssloptions;
++#else
++typedef unsigned long qssloptions;
++#endif
++
+ struct QSslErrorEntry {
+ int code;
+ int depth;
+@@ -171,7 +177,7 @@ public:
+ QVector<QSslError> ocspErrors;
+ QByteArray ocspResponseDer;
+
+- Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
++ Q_AUTOTEST_EXPORT static qssloptions setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
+ static QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher);
+ static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
+ static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain, const QString &hostName);
+--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
++++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
+@@ -157,7 +157,7 @@ DEFINEFUNC2(void, OPENSSL_sk_push, OPENS
+ DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG)
+ DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return)
+ DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return)
+-DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return)
++DEFINEFUNC2(qssloptions, SSL_CTX_set_options, SSL_CTX *ctx, ctx, qssloptions op, op, return 0, return)
+ DEFINEFUNC(int, SSL_CTX_get_security_level, const SSL_CTX *ctx, ctx, return -1, return)
+ DEFINEFUNC2(void, SSL_CTX_set_security_level, SSL_CTX *ctx, ctx, int level, level, return, return)
+ #ifdef TLS1_3_VERSION
+--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
++++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
+@@ -245,7 +245,7 @@ Q_AUTOTEST_EXPORT void q_OPENSSL_sk_push
+ Q_AUTOTEST_EXPORT void q_OPENSSL_sk_free(OPENSSL_STACK *a);
+ Q_AUTOTEST_EXPORT void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
+ int q_SSL_session_reused(SSL *a);
+-unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
++qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions op);
+ int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
+ size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen);
+ size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen);
diff --git a/debian/patches/qmenu_set_transient_parent.diff b/debian/patches/qmenu_set_transient_parent.diff
new file mode 100644
index 00000000..a2afbb28
--- /dev/null
+++ b/debian/patches/qmenu_set_transient_parent.diff
@@ -0,0 +1,60 @@
+Description: widgets: setTransientParent() when a QMenu is a window
+ On some platforms, such as X11 and Wayland with some compositors,
+ QMenu could be a popup window, which should be set a transient parent
+ to get relative position, which is requested by Wayland.
+ .
+ Added transientParentWindow() for QMenuPrivate like QDialogPrivate.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=493a85a9e4688744
+Last-Update: 2022-10-16
+
+--- a/src/widgets/widgets/qmenu.cpp
++++ b/src/widgets/widgets/qmenu.cpp
+@@ -624,6 +624,29 @@ void QMenuPrivate::hideMenu(QMenu *menu)
+ menu->d_func()->causedPopup.widget = nullptr;
+ }
+
++QWindow *QMenuPrivate::transientParentWindow() const
++{
++ Q_Q(const QMenu);
++ if (const QWidget *parent = q->nativeParentWidget()) {
++ if (parent->windowHandle())
++ return parent->windowHandle();
++ }
++
++ if (const QWindow *w = q->windowHandle()) {
++ if (w->transientParent())
++ return w->transientParent();
++ }
++
++ if (causedPopup.widget) {
++ if (const QWidget *w = causedPopup.widget.data()) {
++ if (const QWidget *ww = w->window())
++ return ww->windowHandle();
++ }
++ }
++
++ return nullptr;
++}
++
+ void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst)
+ {
+ Q_Q(QMenu);
+@@ -3060,6 +3083,8 @@ QMenu::event(QEvent *e)
+ d->sloppyState.reset();
+ if (d->currentAction)
+ d->popupAction(d->currentAction, 0, false);
++ if (isWindow() && window() && window()->windowHandle() && !window()->windowHandle()->transientParent())
++ window()->windowHandle()->setTransientParent(d->transientParentWindow());
+ break;
+ #ifndef QT_NO_TOOLTIP
+ case QEvent::ToolTip:
+--- a/src/widgets/widgets/qmenu_p.h
++++ b/src/widgets/widgets/qmenu_p.h
+@@ -440,6 +440,7 @@ public:
+ QMenuCaused causedPopup;
+ void hideUpToMenuBar();
+ void hideMenu(QMenu *menu);
++ QWindow *transientParentWindow() const;
+
+ //index mappings
+ inline QAction *actionAt(int i) const { return q_func()->actions().at(i); }
diff --git a/debian/patches/qshapedpixmapwindow_no_tooltip.diff b/debian/patches/qshapedpixmapwindow_no_tooltip.diff
new file mode 100644
index 00000000..7e4dabfb
--- /dev/null
+++ b/debian/patches/qshapedpixmapwindow_no_tooltip.diff
@@ -0,0 +1,25 @@
+Description: do not set Qt::ToolTip flag for QShapedPixmapWindow
+ This hint is not really needed in the first place and only causes
+ problems in some environments.
+ .
+ For example in KDE, the compositor animates changes in position and size
+ for all ToolTip windows. However, this is not wanted here because we use
+ this window as a thumbnail for a drag-and-drop operation.
+ Before this patch the dragged element would lag significantly behind the
+ cursor. Now it works as expected, i.e. the dragged element follows the
+ cursor immediately.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=180b496b537089b8
+Bug: https://bugreports.qt.io/browse/QTBUG-98048
+Last-Update: 2023-05-20
+
+--- a/src/gui/kernel/qshapedpixmapdndwindow.cpp
++++ b/src/gui/kernel/qshapedpixmapdndwindow.cpp
+@@ -56,7 +56,7 @@ QShapedPixmapWindow::QShapedPixmapWindow
+ QSurfaceFormat format;
+ format.setAlphaBufferSize(8);
+ setFormat(format);
+- setFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint
++ setFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint
+ | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus);
+ }
+
diff --git a/debian/patches/qxcbwindow_set_geometry.diff b/debian/patches/qxcbwindow_set_geometry.diff
new file mode 100644
index 00000000..76ac96a9
--- /dev/null
+++ b/debian/patches/qxcbwindow_set_geometry.diff
@@ -0,0 +1,44 @@
+Description: set geometry property in QXcbWindow after checking minimum size
+ QXcbWindow::create() bound the window's size to windowMinimumSize(),
+ after its size had been inherited from parent().
+ QPlatformWindow::setGeometry() was called before that sanity check.
+ .
+ When a fullscreen window is re-mapped from a deactivated screen to the
+ remaining screen, the call to QPlatformWindow::setGeometry() assigns
+ an invalid QRect to QPlatformWindowPrivate::rect
+ The negative int values x2 and/or y2 cause
+ QXcbBackingStoreImage::flushPixmap to address unmapped memory and
+ crash.
+ .
+ This patch moves the call to QPlatformWindow::setGeometry() from
+ before to after bounding to a minimum value. That assures a valid
+ rectangle to be assigned in all cases.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=6a3627b6c5aa5109
+Last-Update: 2023-01-04
+
+--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
++++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
+@@ -299,11 +299,6 @@ void QXcbWindow::create()
+ return;
+ }
+
+- QPlatformWindow::setGeometry(rect);
+-
+- if (platformScreen != currentScreen)
+- QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
+-
+ const QSize minimumSize = windowMinimumSize();
+ if (rect.width() > 0 || rect.height() > 0) {
+ rect.setWidth(qBound(1, rect.width(), XCOORD_MAX));
+@@ -315,6 +310,11 @@ void QXcbWindow::create()
+ rect.setHeight(QHighDpi::toNativePixels(int(defaultWindowHeight), platformScreen->QPlatformScreen::screen()));
+ }
+
++ QPlatformWindow::setGeometry(rect);
++
++ if (platformScreen != currentScreen)
++ QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
++
+ xcb_window_t xcb_parent_id = platformScreen->root();
+ if (parent()) {
+ xcb_parent_id = static_cast<QXcbWindow *>(parent())->xcb_window();
diff --git a/debian/patches/remove_limit_on_number_of_streams.diff b/debian/patches/remove_limit_on_number_of_streams.diff
deleted file mode 100644
index 0d71c56a..00000000
--- a/debian/patches/remove_limit_on_number_of_streams.diff
+++ /dev/null
@@ -1,50 +0,0 @@
-Description: H2: remove a rather useless limit on the number of streams
- SETTINGS for max concurrect number of streams is 'one direction' - this
- is how our peer conveys the possible number of streams _we_ can open,
- not _them_. If they choose to have it unlimited - let it be so.
- .
- It's possible to send 0 as maximum number, also, it's possible to
- reduce the maximum compared to initial at some point - then I have
- to avoid integer overflows.
-Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=46940ca73791e87e
-Last-Update: 2022-06-20
-
---- a/src/network/access/http2/http2protocol_p.h
-+++ b/src/network/access/http2/http2protocol_p.h
-@@ -133,9 +133,6 @@ enum Http2PredefinedParameters
- maxPayloadSize = (1 << 24) - 1, // HTTP/2 6.5.2
-
- defaultSessionWindowSize = 65535, // HTTP/2 6.5.2
-- // Using 1000 (rather arbitrarily), just to
-- // impose *some* upper limit:
-- maxPeerConcurrentStreams = 1000,
- maxConcurrentStreams = 100 // HTTP/2, 6.5.2
- };
-
---- a/src/network/access/qhttp2protocolhandler.cpp
-+++ b/src/network/access/qhttp2protocolhandler.cpp
-@@ -393,7 +393,8 @@ bool QHttp2ProtocolHandler::sendRequest(
- initReplyFromPushPromise(message, key);
- }
-
-- const auto streamsToUse = std::min<quint32>(maxConcurrentStreams - activeStreams.size(),
-+ const auto streamsToUse = std::min<quint32>(maxConcurrentStreams > activeStreams.size()
-+ ? maxConcurrentStreams - activeStreams.size() : 0,
- requests.size());
- auto it = requests.begin();
- for (quint32 i = 0; i < streamsToUse; ++i) {
-@@ -1084,13 +1085,8 @@ bool QHttp2ProtocolHandler::acceptSettin
- QMetaObject::invokeMethod(this, "resumeSuspendedStreams", Qt::QueuedConnection);
- }
-
-- if (identifier == Settings::MAX_CONCURRENT_STREAMS_ID) {
-- if (newValue > maxPeerConcurrentStreams) {
-- connectionError(PROTOCOL_ERROR, "SETTINGS invalid number of concurrent streams");
-- return false;
-- }
-+ if (identifier == Settings::MAX_CONCURRENT_STREAMS_ID)
- maxConcurrentStreams = newValue;
-- }
-
- if (identifier == Settings::MAX_FRAME_SIZE_ID) {
- if (newValue < Http2::minPayloadLimit || newValue > Http2::maxPayloadSize) {
diff --git a/debian/patches/revert_startBlocking_removal.diff b/debian/patches/revert_startBlocking_removal.diff
new file mode 100644
index 00000000..3537b759
--- /dev/null
+++ b/debian/patches/revert_startBlocking_removal.diff
@@ -0,0 +1,102 @@
+Description: revert "Remove the dead code for blocking methods from QtConcurrent"
+ It's a binary incompatible change.
+Origin: KDE, https://invent.kde.org/qt/qt/qtbase/-/commit/eeadc036d77b75be
+ Also submitted to upstream 5.15 branch according to
+ https://lists.qt-project.org/pipermail/development/2022-September/042951.html.
+Last-Update: 2022-09-10
+
+--- a/src/concurrent/qtconcurrentthreadengine.cpp
++++ b/src/concurrent/qtconcurrentthreadengine.cpp
+@@ -176,6 +176,39 @@ void ThreadEngineBase::startSingleThread
+ finish();
+ }
+
++void ThreadEngineBase::startBlocking()
++{
++ start();
++ barrier.acquire();
++ startThreads();
++
++ bool throttled = false;
++#ifndef QT_NO_EXCEPTIONS
++ try {
++#endif
++ while (threadFunction() == ThrottleThread) {
++ if (threadThrottleExit()) {
++ throttled = true;
++ break;
++ }
++ }
++#ifndef QT_NO_EXCEPTIONS
++ } catch (QException &e) {
++ handleException(e);
++ } catch (...) {
++ handleException(QUnhandledException());
++ }
++#endif
++
++ if (throttled == false) {
++ barrier.release();
++ }
++
++ barrier.wait();
++ finish();
++ exceptionStore.throwPossibleException();
++}
++
+ void ThreadEngineBase::startThread()
+ {
+ startThreadInternal();
+--- a/src/concurrent/qtconcurrentthreadengine.h
++++ b/src/concurrent/qtconcurrentthreadengine.h
+@@ -91,6 +91,7 @@ public:
+ ThreadEngineBase();
+ virtual ~ThreadEngineBase();
+ void startSingleThreaded();
++ void startBlocking();
+ void startThread();
+ bool isCanceled();
+ void waitForResume();
+@@ -144,6 +145,15 @@ public:
+ }
+
+ // Runs the user algorithm using multiple threads.
++ // This function blocks until the algorithm is finished,
++ // and then returns the result.
++ T *startBlocking()
++ {
++ ThreadEngineBase::startBlocking();
++ return result();
++ }
++
++ // Runs the user algorithm using multiple threads.
+ // Does not block, returns a future.
+ QFuture<T> startAsynchronously()
+ {
+@@ -223,6 +233,13 @@ class ThreadEngineStarter : public Threa
+ public:
+ ThreadEngineStarter(TypedThreadEngine *eng)
+ : Base(eng) { }
++
++ T startBlocking()
++ {
++ T t = *this->threadEngine->startBlocking();
++ delete this->threadEngine;
++ return t;
++ }
+ };
+
+ // Full template specialization where T is void.
+@@ -232,6 +249,12 @@ class ThreadEngineStarter<void> : public
+ public:
+ ThreadEngineStarter(ThreadEngine<void> *_threadEngine)
+ : ThreadEngineStarterBase<void>(_threadEngine) {}
++
++ void startBlocking()
++ {
++ this->threadEngine->startBlocking();
++ delete this->threadEngine;
++ }
+ };
+
+ //! [qtconcurrentthreadengine-1]
diff --git a/debian/patches/series b/debian/patches/series
index 095a51a2..d4981851 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,15 +1,25 @@
# Backported from upstream.
#mime_globs.diff
-#fix-misplacement-of-placeholder-text-in-QLineEdit.diff
-#fix-placement-of-placeholder-text-in-QLineEdits-with-action-icons.diff
-#full_width_selection_rtl.diff
-#fix_recursion_crash.diff
-#mysql_field_readonly.diff
-#CVE-2021-38593.diff
+#fusion_checkable_qpushbutton.diff
#openssl3.diff
-#CVE-2022-25255.diff
-#moc_handle_include.diff
-#remove_limit_on_number_of_streams.diff
+#openssl_set_options.diff
+qmenu_set_transient_parent.diff
+gnome_wayland.diff
+#fix_alt_backtick.diff
+#image_deletion_order.diff
+#qxcbwindow_set_geometry.diff
+#CVE-2023-24607.diff
+#qshapedpixmapwindow_no_tooltip.diff
+#CVE-2023-32763.diff
+#CVE-2023-32762.diff
+#CVE-2023-33285.diff
+#CVE-2023-34410.diff
+sql_odbc_more_unicode_checks.diff
+sql_odbc_fix_unicode_check.diff
+a11y_root.diff
+dont_use_O_PATH.diff
+#fix_qdbusmacros_h.diff
+
# Debian specific.
gnukfreebsd.diff
diff --git a/debian/patches/sql_odbc_fix_unicode_check.diff b/debian/patches/sql_odbc_fix_unicode_check.diff
new file mode 100644
index 00000000..dd27b32e
--- /dev/null
+++ b/debian/patches/sql_odbc_fix_unicode_check.diff
@@ -0,0 +1,32 @@
+Description: QSQL/ODBC: fix regression (trailing NUL)
+ When we fixed the callers of toSQLTCHAR() to use the result's size()
+ instead of the input's (which differ, if sizeof(SQLTCHAR) != 2), we
+ exposed callers to the append(0), which changes the size() of the
+ result QVLA. Callers that don't rely on NUL-termination (all?) now saw
+ an additional training NUL.
+ .
+ Fix by not NUL-terminating, and changing the only user of SQL_NTS to
+ use an explicit length.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=9020034b3b6a3a81
+Last-Update: 2023-06-30
+
+--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
++++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+@@ -125,7 +125,6 @@ inline static QVarLengthArray<SQLTCHAR>
+ {
+ QVarLengthArray<SQLTCHAR> result;
+ toSQLTCHARImpl(result, input);
+- result.append(0); // make sure it's null terminated, doesn't matter if it already is, it does if it isn't.
+ return result;
+ }
+
+@@ -2119,7 +2118,8 @@ void QODBCDriverPrivate::checkUnicode()
+ QLatin1String("select 'test' from dual"),
+ };
+ for (const auto &statement : statements) {
+- r = SQLExecDirect(hStmt, toSQLTCHAR(statement).data(), SQL_NTS);
++ auto encoded = toSQLTCHAR(statement);
++ r = SQLExecDirect(hStmt, encoded.data(), SQLINTEGER(encoded.size()));
+ if (r == SQL_SUCCESS)
+ break;
+ }
diff --git a/debian/patches/sql_odbc_more_unicode_checks.diff b/debian/patches/sql_odbc_more_unicode_checks.diff
new file mode 100644
index 00000000..de7d2d9a
--- /dev/null
+++ b/debian/patches/sql_odbc_more_unicode_checks.diff
@@ -0,0 +1,35 @@
+Description: SQL/ODBC: add another check to detect unicode availability in driver
+ Since ODBC does not have a direct way finding out if unicode is
+ supported by the underlying driver the ODBC plugin does some checks. As
+ a last resort a sql statement is executed which returns a string. But
+ even this may fail because the select statement has no FROM part which
+ is rejected by at least Oracle does not allow. Therefore add another
+ query which is correct for Oracle & DB2 as a workaround. The question
+ why the first three statements to check for unicode availability fail
+ is still open but can't be checked since I've no access to an oracle
+ database.
+Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=f19320748d282b1e
+Last-Update: 2023-06-30
+
+--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
++++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+@@ -2111,7 +2111,18 @@ void QODBCDriverPrivate::checkUnicode()
+ hDbc,
+ &hStmt);
+
+- r = SQLExecDirect(hStmt, toSQLTCHAR(QLatin1String("select 'test'")).data(), SQL_NTS);
++ // for databases which do not return something useful in SQLGetInfo and are picky about a
++ // 'SELECT' statement without 'FROM' but support VALUE(foo) statement like e.g. DB2 or Oracle
++ const auto statements = {
++ QLatin1String("select 'test'"),
++ QLatin1String("values('test')"),
++ QLatin1String("select 'test' from dual"),
++ };
++ for (const auto &statement : statements) {
++ r = SQLExecDirect(hStmt, toSQLTCHAR(statement).data(), SQL_NTS);
++ if (r == SQL_SUCCESS)
++ break;
++ }
+ if(r == SQL_SUCCESS) {
+ r = SQLFetch(hStmt);
+ if(r == SQL_SUCCESS) {
diff --git a/debian/patches/xdg_filechooser_portal_send_window_id_in_hex.diff b/debian/patches/xdg_filechooser_portal_send_window_id_in_hex.diff
deleted file mode 100644
index 76abafe1..00000000
--- a/debian/patches/xdg_filechooser_portal_send_window_id_in_hex.diff
+++ /dev/null
@@ -1,18 +0,0 @@
-Description: FileChooser portal: send window id in hex
- We send window id in decimal, however, it is expected to be send in hex.
- This causes a mismatch and makes portal dialog to show in background.
-Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=acaabc9108dfe75530960cf8e3ec4f3602cd82e0
-Last-Update: 2021-11-04
-Index: qtbase-opensource-src/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
-===================================================================
---- qtbase-opensource-src.orig/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
-+++ qtbase-opensource-src/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
-@@ -185,7 +185,7 @@ void QXdgDesktopPortalFileDialog::openPo
- QLatin1String("/org/freedesktop/portal/desktop"),
- QLatin1String("org.freedesktop.portal.FileChooser"),
- d->saveFile ? QLatin1String("SaveFile") : QLatin1String("OpenFile"));
-- QString parentWindowId = QLatin1String("x11:") + QString::number(d->winId);
-+ QString parentWindowId = QLatin1String("x11:") + QString::number(d->winId, 16);
-
- QVariantMap options;
- if (!d->acceptLabel.isEmpty())
More information about the Neon-commits
mailing list