Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian....@packages.debian.org
Usertags: pu


The attached debdiff for qtbase-opensource-src fixes several CVEs in Bullseye. All CVEs are marked as no-dsa by the security team.

  Thorsten
diff -Nru qtbase-opensource-src-5.15.2+dfsg/debian/changelog 
qtbase-opensource-src-5.15.2+dfsg/debian/changelog
--- qtbase-opensource-src-5.15.2+dfsg/debian/changelog  2021-07-02 
17:58:04.000000000 +0200
+++ qtbase-opensource-src-5.15.2+dfsg/debian/changelog  2024-04-28 
22:48:02.000000000 +0200
@@ -1,3 +1,33 @@
+qtbase-opensource-src (5.15.2+dfsg-9+deb11u1) bullseye; urgency=medium
+
+  * Non-maintainer upload by the LTS Team.
+  * CVE-2024-25580 (Closes: #1064053)
+    fix buffer overflow due to crafted KTX image file
+  * CVE-2023-32763 (Closes: #1036702)
+    fix QTextLayout buffer overflow due to crafted SVG file
+  * CVE-2022-25255
+    prevent QProcess from execution of a binary from the current working
+    directory when not found in the PATH
+  * CVE-2023-24607 (Closes: #1031872)
+    fix denial of service via a crafted string when the SQL ODBC driver
+    plugin is used
+  * fix regression caused by patch for CVE-2023-24607
+  * CVE-2023-32762
+    prevent incorrect parsing of the strict-transport-security (HSTS) header
+  * CVE-2023-51714 (Closes: #1060694)
+    fix incorrect HPack integer overflow check.
+  * CVE-2023-38197 (Closes: #1041105)
+    fix infinite loop in recursive entity expansion
+  * CVE-2023-37369 (Closes: #1059302)
+    fix crash of application in QXmlStreamReader due to crafted XML string
+  * CVE-2023-34410 (Closes: #1037210)
+    fix checking during TLS whether root of the chain really is a
+    configured CA certificate
+  * CVE-2023-33285 (Closes: #1036848)
+    fix buffer overflow in QDnsLookup
+
+ -- Thorsten Alteholz <deb...@alteholz.de>  Sun, 28 Apr 2024 22:48:02 +0200
+
 qtbase-opensource-src (5.15.2+dfsg-9) unstable; urgency=medium
 
   * Revert adding fix-misplacement-of-placeholder-text-in-QLineEdit.diff.
diff -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2022-25255.diff 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2022-25255.diff
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2022-25255.diff        
1970-01-01 01:00:00.000000000 +0100
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2022-25255.diff        
2024-03-05 13:22:01.000000000 +0100
@@ -0,0 +1,96 @@
+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
+
+Index: qtbase-opensource-src-5.15.2+dfsg/src/corelib/io/qprocess_unix.cpp
+===================================================================
+--- qtbase-opensource-src-5.15.2+dfsg.orig/src/corelib/io/qprocess_unix.cpp    
2024-03-05 13:21:06.432881985 +0100
++++ qtbase-opensource-src-5.15.2+dfsg/src/corelib/io/qprocess_unix.cpp 
2024-03-05 13:21:06.428881981 +0100
+@@ -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 @@
+     // 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 @@
+                 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);
+Index: 
qtbase-opensource-src-5.15.2+dfsg/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
 2024-03-05 13:21:06.432881985 +0100
++++ 
qtbase-opensource-src-5.15.2+dfsg/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
      2024-03-05 13:21:57.744931492 +0100
+@@ -1449,7 +1449,7 @@
+ {
+ #if QT_CONFIG(process)
+     QProcess testProcess;
+-    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));
+@@ -2365,7 +2365,7 @@
+ #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 -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-24607.diff 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-24607.diff
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-24607.diff        
1970-01-01 01:00:00.000000000 +0100
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-24607.diff        
2024-03-05 13:24:50.000000000 +0100
@@ -0,0 +1,332 @@
+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
+
+Index: 
qtbase-opensource-src-5.15.2+dfsg/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
   2024-03-05 13:24:44.661090169 +0100
++++ 
qtbase-opensource-src-5.15.2+dfsg/src/plugins/sqldrivers/odbc/qsql_odbc.cpp     
   2024-03-05 13:24:44.657090165 +0100
+@@ -92,23 +92,39 @@
+     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 @@
+     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 @@
+             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 @@
+             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 @@
+         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));
+@@ -1370,9 +1391,12 @@
+         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",
+@@ -1400,7 +1424,7 @@
+         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));
+ 
+@@ -1579,35 +1603,36 @@
+             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;
+@@ -1715,10 +1740,11 @@
+             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;
+                 }
+@@ -1965,14 +1991,16 @@
+     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));
+@@ -2351,17 +2379,15 @@
+     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);
+@@ -2435,28 +2461,30 @@
+                         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);
+@@ -2537,15 +2565,17 @@
+                         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 -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-32762.diff 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-32762.diff
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-32762.diff        
1970-01-01 01:00:00.000000000 +0100
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-32762.diff        
2024-03-05 13:48:39.000000000 +0100
@@ -0,0 +1,47 @@
+commit 1b736a815be0222f4b24289cf17575fc15707305
+Author: Mårten Nordheim <marten.nordh...@qt.io>
+Date:   Fri May 5 11:07:26 2023 +0200
+
+    Hsts: match header names case insensitively
+    
+    Header field names are always considered to be case-insensitive.
+    
+    Pick-to: 6.5 6.5.1 6.2 5.15
+    Fixes: QTBUG-113392
+    Change-Id: Ifb4def4bb7f2ac070416cdc76581a769f1e52b43
+    Reviewed-by: Qt CI Bot <qt_ci_...@qt-project.org>
+    Reviewed-by: Edward Welbourne <edward.welbou...@qt.io>
+    Reviewed-by: Volker Hilsheimer <volker.hilshei...@qt.io>
+
+Index: qtbase-opensource-src-5.15.2+dfsg/src/network/access/qhsts.cpp
+===================================================================
+--- qtbase-opensource-src-5.15.2+dfsg.orig/src/network/access/qhsts.cpp        
2024-03-05 13:48:37.054356050 +0100
++++ qtbase-opensource-src-5.15.2+dfsg/src/network/access/qhsts.cpp     
2024-03-05 13:48:37.054356050 +0100
+@@ -364,8 +364,8 @@
+ 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:
+             //
+Index: 
qtbase-opensource-src-5.15.2+dfsg/tests/auto/network/access/hsts/tst_qhsts.cpp
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/tests/auto/network/access/hsts/tst_qhsts.cpp
        2024-03-05 13:48:37.054356050 +0100
++++ 
qtbase-opensource-src-5.15.2+dfsg/tests/auto/network/access/hsts/tst_qhsts.cpp  
   2024-03-05 13:48:37.054356050 +0100
+@@ -242,6 +242,12 @@
+     QVERIFY(parser.includeSubDomains());
+ 
+     list.pop_back();
++    list << Header("strict-transport-security", 
"includeSubDomains;max-age=1000");
++    QVERIFY(parser.parse(list));
++    QVERIFY(parser.expirationDate() > QDateTime::currentDateTimeUtc());
++    QVERIFY(parser.includeSubDomains());
++
++    list.pop_back();
+     // Invalid (includeSubDomains twice):
+     list << Header("Strict-Transport-Security", "max-age = 1000 ; 
includeSubDomains;includeSubDomains");
+     QVERIFY(!parser.parse(list));
diff -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-32763.diff 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-32763.diff
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-32763.diff        
1970-01-01 01:00:00.000000000 +0100
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-32763.diff        
2024-03-05 12:57:24.000000000 +0100
@@ -0,0 +1,54 @@
+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
+
+Index: qtbase-opensource-src-5.15.2+dfsg/src/gui/painting/qfixed_p.h
+===================================================================
+--- qtbase-opensource-src-5.15.2+dfsg.orig/src/gui/painting/qfixed_p.h 
2024-03-05 12:57:22.447571651 +0100
++++ qtbase-opensource-src-5.15.2+dfsg/src/gui/painting/qfixed_p.h      
2024-03-05 12:57:22.443571651 +0100
+@@ -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>(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(); }
+Index: qtbase-opensource-src-5.15.2+dfsg/src/gui/text/qtextlayout.cpp
+===================================================================
+--- qtbase-opensource-src-5.15.2+dfsg.orig/src/gui/text/qtextlayout.cpp        
2024-03-05 12:57:22.447571651 +0100
++++ qtbase-opensource-src-5.15.2+dfsg/src/gui/text/qtextlayout.cpp     
2024-03-05 12:57:22.443571651 +0100
+@@ -2138,11 +2138,14 @@
+         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 -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-33285.diff 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-33285.diff
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-33285.diff        
1970-01-01 01:00:00.000000000 +0100
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-33285.diff        
2023-05-25 12:45:05.000000000 +0200
@@ -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 -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-34410.diff 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-34410.diff
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-34410.diff        
1970-01-01 01:00:00.000000000 +0100
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-34410.diff        
2024-04-28 22:48:02.000000000 +0200
@@ -0,0 +1,56 @@
+Index: 
qtbase-opensource-src-5.15.2+dfsg/src/network/ssl/qsslsocket_schannel.cpp
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/src/network/ssl/qsslsocket_schannel.cpp  
   2024-04-25 14:19:26.756392964 +0200
++++ qtbase-opensource-src-5.15.2+dfsg/src/network/ssl/qsslsocket_schannel.cpp  
2024-04-25 14:19:26.752392971 +0200
+@@ -1877,6 +1877,28 @@
+     if (configuration.peerVerifyDepth > 0 && 
DWORD(configuration.peerVerifyDepth) < verifyDepth)
+         verifyDepth = DWORD(configuration.peerVerifyDepth);
+ 
++    const auto &caCertificates = q->sslConfiguration().caCertificates();
++
++    if (!rootCertOnDemandLoadingAllowed()
++            && !(chain->TrustStatus.dwErrorStatus & 
CERT_TRUST_IS_PARTIAL_CHAIN)
++            && (q->peerVerifyMode() == QSslSocket::VerifyPeer
++                    || (isClient && q->peerVerifyMode() == 
QSslSocket::AutoVerifyPeer))) {
++        // When verifying a peer Windows "helpfully" builds a chain that
++        // may include roots from the system store. But we don't want that if
++        // the user has set their own CA certificates.
++        // Since Windows claims this is not a partial chain the root is 
included
++        // and we have to check that it is one of our configured CAs.
++        CERT_CHAIN_ELEMENT *element = chain->rgpElement[chain->cElement - 1];
++        QSslCertificate certificate = getCertificateFromChainElement(element);
++        if (!caCertificates.contains(certificate)) {
++            auto error = QSslError(QSslError::CertificateUntrusted, 
certificate);
++            sslErrors += error;
++            emit q->peerVerifyError(error);
++            if (q->state() != QAbstractSocket::ConnectedState)
++                return false;
++        }
++    }
++
+     for (DWORD i = 0; i < verifyDepth; i++) {
+         CERT_CHAIN_ELEMENT *element = chain->rgpElement[i];
+         QSslCertificate certificate = getCertificateFromChainElement(element);
+Index: qtbase-opensource-src-5.15.2+dfsg/src/network/ssl/qsslsocket.cpp
+===================================================================
+--- qtbase-opensource-src-5.15.2+dfsg.orig/src/network/ssl/qsslsocket.cpp      
2024-04-25 14:19:26.756392964 +0200
++++ qtbase-opensource-src-5.15.2+dfsg/src/network/ssl/qsslsocket.cpp   
2024-04-25 14:19:26.752392971 +0200
+@@ -2221,6 +2221,10 @@
+     , 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 @@
+     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 -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-37369.diff 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-37369.diff
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-37369.diff        
1970-01-01 01:00:00.000000000 +0100
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-37369.diff        
2024-04-28 22:48:02.000000000 +0200
@@ -0,0 +1,202 @@
+Index: 
qtbase-opensource-src-5.15.2+dfsg/src/corelib/serialization/qxmlstream.cpp
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/src/corelib/serialization/qxmlstream.cpp 
   2024-04-26 13:23:27.490939469 +0200
++++ qtbase-opensource-src-5.15.2+dfsg/src/corelib/serialization/qxmlstream.cpp 
2024-04-26 13:24:24.074800856 +0200
+@@ -1302,11 +1302,19 @@
+     return n;
+ }
+ 
+-inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
++// Fast scan an XML attribute name (e.g. "xml:lang").
++inline QXmlStreamReaderPrivate::FastScanNameResult
++QXmlStreamReaderPrivate::fastScanName(Value *val)
+ {
+     int n = 0;
+     uint c;
+     while ((c = getChar()) != StreamEOF) {
++        if (n >= 4096) {
++            // This is too long to be a sensible name, and
++            // can exhaust memory, or the range of decltype(*prefix)
++            raiseNamePrefixTooLongError();
++            return {};
++        }
+         switch (c) {
+         case '\n':
+         case ' ':
+@@ -1334,23 +1342,23 @@
+         case '+':
+         case '*':
+             putChar(c);
+-            if (prefix && *prefix == n+1) {
+-                *prefix = 0;
++            if (val && val->prefix == n + 1) {
++                val->prefix = 0;
+                 putChar(':');
+                 --n;
+             }
+-            return n;
++            return FastScanNameResult(n);
+         case ':':
+-            if (prefix) {
+-                if (*prefix == 0) {
+-                    *prefix = n+2;
++            if (val) {
++                if (val->prefix == 0) {
++                    val->prefix = n + 2;
+                 } else { // only one colon allowed according to the namespace 
spec.
+                     putChar(c);
+-                    return n;
++                    return FastScanNameResult(n);
+                 }
+             } else {
+                 putChar(c);
+-                return n;
++                return FastScanNameResult(n);
+             }
+             Q_FALLTHROUGH();
+         default:
+@@ -1359,12 +1367,12 @@
+         }
+     }
+ 
+-    if (prefix)
+-        *prefix = 0;
++    if (val)
++        val->prefix = 0;
+     int pos = textBuffer.size() - n;
+     putString(textBuffer, pos);
+     textBuffer.resize(pos);
+-    return 0;
++    return FastScanNameResult(0);
+ }
+ 
+ enum NameChar { NameBeginning, NameNotBeginning, NotName };
+@@ -1873,6 +1881,14 @@
+     raiseError(QXmlStreamReader::NotWellFormedError, message);
+ }
+ 
++void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError()
++{
++    // TODO: add a ImplementationLimitsExceededError and use it instead
++    raiseError(QXmlStreamReader::NotWellFormedError,
++               QXmlStream::tr("Length of XML attribute name exceeds 
implemnetation limits (4KiB "
++                              "characters)."));
++}
++
+ void QXmlStreamReaderPrivate::parseError()
+ {
+ 
+Index: qtbase-opensource-src-5.15.2+dfsg/src/corelib/serialization/qxmlstream.g
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/src/corelib/serialization/qxmlstream.g   
   2024-04-26 13:23:27.490939469 +0200
++++ qtbase-opensource-src-5.15.2+dfsg/src/corelib/serialization/qxmlstream.g   
2024-04-26 13:23:27.486939479 +0200
+@@ -516,7 +516,16 @@
+     int fastScanLiteralContent();
+     int fastScanSpace();
+     int fastScanContentCharList();
+-    int fastScanName(int *prefix = nullptr);
++
++    struct FastScanNameResult {
++        FastScanNameResult() : ok(false) {}
++        explicit FastScanNameResult(int len) : addToLen(len), ok(true) { }
++        operator bool() { return ok; }
++        int operator*() { Q_ASSERT(ok); return addToLen; }
++        int addToLen;
++        bool ok;
++    };
++    FastScanNameResult fastScanName(Value *val = nullptr);
+     inline int fastScanNMTOKEN();
+ 
+ 
+@@ -525,6 +534,7 @@
+ 
+     void raiseError(QXmlStreamReader::Error error, const QString& message = 
QString());
+     void raiseWellFormedError(const QString &message);
++    void raiseNamePrefixTooLongError();
+ 
+     QXmlStreamEntityResolver *entityResolver;
+ 
+@@ -1809,7 +1819,12 @@
+ qname ::= LETTER;
+ /.
+         case $rule_number: {
+-            sym(1).len += fastScanName(&sym(1).prefix);
++            Value &val = sym(1);
++            if (auto res = fastScanName(&val))
++                val.len += *res;
++            else
++                return false;
++
+             if (atEnd) {
+                 resume($rule_number);
+                 return false;
+@@ -1820,7 +1835,11 @@
+ name ::= LETTER;
+ /.
+         case $rule_number:
+-            sym(1).len += fastScanName();
++            if (auto res = fastScanName())
++                sym(1).len += *res;
++            else
++                return false;
++
+             if (atEnd) {
+                 resume($rule_number);
+                 return false;
+Index: 
qtbase-opensource-src-5.15.2+dfsg/src/corelib/serialization/qxmlstream_p.h
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/src/corelib/serialization/qxmlstream_p.h 
   2024-04-26 13:23:27.490939469 +0200
++++ qtbase-opensource-src-5.15.2+dfsg/src/corelib/serialization/qxmlstream_p.h 
2024-04-26 13:23:27.486939479 +0200
+@@ -1005,7 +1005,16 @@
+     int fastScanLiteralContent();
+     int fastScanSpace();
+     int fastScanContentCharList();
+-    int fastScanName(int *prefix = nullptr);
++
++    struct FastScanNameResult {
++        FastScanNameResult() : ok(false) {}
++        explicit FastScanNameResult(int len) : addToLen(len), ok(true) { }
++        operator bool() { return ok; }
++        int operator*() { Q_ASSERT(ok); return addToLen; }
++        int addToLen;
++        bool ok;
++    };
++    FastScanNameResult fastScanName(Value *val = nullptr);
+     inline int fastScanNMTOKEN();
+ 
+ 
+@@ -1014,6 +1023,7 @@
+ 
+     void raiseError(QXmlStreamReader::Error error, const QString& message = 
QString());
+     void raiseWellFormedError(const QString &message);
++    void raiseNamePrefixTooLongError();
+ 
+     QXmlStreamEntityResolver *entityResolver;
+ 
+@@ -1937,7 +1947,12 @@
+         break;
+ 
+         case 262: {
+-            sym(1).len += fastScanName(&sym(1).prefix);
++            Value &val = sym(1);
++            if (auto res = fastScanName(&val))
++                val.len += *res;
++            else
++                return false;
++
+             if (atEnd) {
+                 resume(262);
+                 return false;
+@@ -1945,7 +1960,11 @@
+         } break;
+ 
+         case 263:
+-            sym(1).len += fastScanName();
++            if (auto res = fastScanName())
++                sym(1).len += *res;
++            else
++                return false;
++
+             if (atEnd) {
+                 resume(263);
+                 return false;
diff -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-38197.diff 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-38197.diff
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-38197.diff        
1970-01-01 01:00:00.000000000 +0100
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-38197.diff        
2024-04-28 22:48:02.000000000 +0200
@@ -0,0 +1,219 @@
+Index: 
qtbase-opensource-src-5.15.2+dfsg/src/corelib/serialization/qxmlstream.cpp
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/src/corelib/serialization/qxmlstream.cpp 
   2024-04-25 08:25:46.389994553 +0200
++++ qtbase-opensource-src-5.15.2+dfsg/src/corelib/serialization/qxmlstream.cpp 
2024-04-25 08:25:46.385994556 +0200
+@@ -160,7 +160,7 @@
+     addData() or by waiting for it to arrive on the device().
+ 
+     \value UnexpectedElementError The parser encountered an element
+-    that was different to those it expected.
++    or token that was different to those it expected.
+ 
+ */
+ 
+@@ -295,13 +295,34 @@
+ 
+   QXmlStreamReader is a well-formed XML 1.0 parser that does \e not
+   include external parsed entities. As long as no error occurs, the
+-  application code can thus be assured that the data provided by the
+-  stream reader satisfies the W3C's criteria for well-formed XML. For
+-  example, you can be certain that all tags are indeed nested and
+-  closed properly, that references to internal entities have been
+-  replaced with the correct replacement text, and that attributes have
+-  been normalized or added according to the internal subset of the
+-  DTD.
++  application code can thus be assured, that
++  \list
++  \li the data provided by the stream reader satisfies the W3C's
++      criteria for well-formed XML,
++  \li tokens are provided in a valid order.
++  \endlist
++
++  Unless QXmlStreamReader raises an error, it guarantees the following:
++  \list
++  \li All tags are nested and closed properly.
++  \li References to internal entities have been replaced with the
++      correct replacement text.
++  \li Attributes have been normalized or added according to the
++      internal subset of the \l DTD.
++  \li Tokens of type \l StartDocument happen before all others,
++      aside from comments and processing instructions.
++  \li At most one DOCTYPE element (a token of type \l DTD) is present.
++  \li If present, the DOCTYPE appears before all other elements,
++      aside from StartDocument, comments and processing instructions.
++  \endlist
++
++  In particular, once any token of type \l StartElement, \l EndElement,
++  \l Characters, \l EntityReference or \l EndDocument is seen, no
++  tokens of type StartDocument or DTD will be seen. If one is present in
++  the input stream, out of order, an error is raised.
++
++  \note The token types \l Comment and \l ProcessingInstruction may appear
++  anywhere in the stream.
+ 
+   If an error occurs while parsing, atEnd() and hasError() return
+   true, and error() returns the error that occurred. The functions
+@@ -620,6 +641,7 @@
+         d->token = -1;
+         return readNext();
+     }
++    d->checkToken();
+     return d->type;
+ }
+ 
+@@ -740,6 +762,14 @@
+ };
+ 
+ 
++static const char QXmlStreamReader_XmlContextString[] =
++    "Prolog\0"
++    "Body\0";
++
++static const short QXmlStreamReader_XmlContextString_indices[] = {
++    0, 7
++};
++
+ /*!
+     \property  QXmlStreamReader::namespaceProcessing
+     The namespace-processing flag of the stream reader
+@@ -775,6 +805,16 @@
+                          QXmlStreamReader_tokenTypeString_indices[d->type]);
+ }
+ 
++/*!
++   \internal
++   \return \param ctxt (Prolog/Body) as a string.
++ */
++QString contextString(QXmlStreamReaderPrivate::XmlContext ctxt)
++{
++    return QLatin1String(QXmlStreamReader_XmlContextString +
++                         
QXmlStreamReader_XmlContextString_indices[static_cast<int>(ctxt)]);
++}
++
+ #endif // QT_NO_XMLSTREAMREADER
+ 
+ QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
+@@ -866,6 +906,8 @@
+ 
+     type = QXmlStreamReader::NoToken;
+     error = QXmlStreamReader::NoError;
++    currentContext = XmlContext::Prolog;
++    foundDTD = false;
+ }
+ 
+ /*
+@@ -4059,6 +4101,92 @@
+     }
+ }
+ 
++static bool isTokenAllowedInContext(QXmlStreamReader::TokenType type,
++                                               
QXmlStreamReaderPrivate::XmlContext loc)
++{
++    switch (type) {
++    case QXmlStreamReader::StartDocument:
++    case QXmlStreamReader::DTD:
++        return loc == QXmlStreamReaderPrivate::XmlContext::Prolog;
++
++    case QXmlStreamReader::StartElement:
++    case QXmlStreamReader::EndElement:
++    case QXmlStreamReader::Characters:
++    case QXmlStreamReader::EntityReference:
++    case QXmlStreamReader::EndDocument:
++        return loc == QXmlStreamReaderPrivate::XmlContext::Body;
++
++    case QXmlStreamReader::Comment:
++    case QXmlStreamReader::ProcessingInstruction:
++        return true;
++
++    case QXmlStreamReader::NoToken:
++    case QXmlStreamReader::Invalid:
++        return false;
++    default:
++        return false;
++    }
++}
++
++/*!
++   \internal
++   \brief QXmlStreamReader::isValidToken
++   \return \c true if \param type is a valid token type.
++   \return \c false if \param type is an unexpected token,
++   which indicates a non-well-formed or invalid XML stream.
++ */
++bool QXmlStreamReaderPrivate::isValidToken(QXmlStreamReader::TokenType type)
++{
++    // Don't change currentContext, if Invalid or NoToken occur in the prolog
++    if (type == QXmlStreamReader::Invalid || type == 
QXmlStreamReader::NoToken)
++        return false;
++
++    // If a token type gets rejected in the body, there is no recovery
++    const bool result = isTokenAllowedInContext(type, currentContext);
++    if (result || currentContext == XmlContext::Body)
++        return result;
++
++    // First non-Prolog token observed => switch context to body and check 
again.
++    currentContext = XmlContext::Body;
++    return isTokenAllowedInContext(type, currentContext);
++}
++
++/*!
++   \internal
++   Checks token type and raises an error, if it is invalid
++   in the current context (prolog/body).
++ */
++void QXmlStreamReaderPrivate::checkToken()
++{
++    Q_Q(QXmlStreamReader);
++
++    // The token type must be consumed, to keep track if the body has been 
reached.
++    const XmlContext context = currentContext;
++    const bool ok = isValidToken(type);
++
++    // Do nothing if an error has been raised already (going along with an 
unexpected token)
++    if (error != QXmlStreamReader::Error::NoError)
++        return;
++
++    if (!ok) {
++        raiseError(QXmlStreamReader::UnexpectedElementError,
++                   QLatin1String("Unexpected token type %1 in %2.")
++                   .arg(q->tokenString(), contextString(context)));
++        return;
++    }
++
++    if (type != QXmlStreamReader::DTD)
++        return;
++
++    // Raise error on multiple DTD tokens
++    if (foundDTD) {
++        raiseError(QXmlStreamReader::UnexpectedElementError,
++                   QLatin1String("Found second DTD token in 
%1.").arg(contextString(context)));
++    } else {
++        foundDTD = true;
++    }
++}
++
+ /*!
+  \fn bool QXmlStreamAttributes::hasAttribute(const QString &qualifiedName) 
const
+  \since 4.5
+Index: 
qtbase-opensource-src-5.15.2+dfsg/src/corelib/serialization/qxmlstream_p.h
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/src/corelib/serialization/qxmlstream_p.h 
   2024-04-25 08:25:46.389994553 +0200
++++ qtbase-opensource-src-5.15.2+dfsg/src/corelib/serialization/qxmlstream_p.h 
2024-04-25 08:25:46.385994556 +0200
+@@ -804,6 +804,17 @@
+ #endif
+     bool atEnd;
+ 
++    enum class XmlContext
++    {
++        Prolog,
++        Body,
++    };
++
++    XmlContext currentContext = XmlContext::Prolog;
++    bool foundDTD = false;
++    bool isValidToken(QXmlStreamReader::TokenType type);
++    void checkToken();
++
+     /*!
+       \sa setType()
+      */
diff -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-51714.diff 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-51714.diff
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-51714.diff        
1970-01-01 01:00:00.000000000 +0100
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2023-51714.diff        
2024-04-28 22:48:02.000000000 +0200
@@ -0,0 +1,61 @@
+From 23c3fc483e8b6e21012a61f0bea884446f727776 Mon Sep 17 00:00:00 2001
+From: Marc Mutz <marc.m...@qt.io>
+Date: Tue, 12 Dec 2023 22:08:07 +0100
+Subject: [PATCH] HPack: fix incorrect integer overflow check
+
+This code never worked:
+
+For the comparison with max() - 32 to trigger, on 32-bit platforms (or
+Qt 5) signed interger overflow would have had to happen in the
+addition of the two sizes. The compiler can therefore remove the
+overflow check as dead code.
+
+On Qt 6 and 64-bit platforms, the signed integer addition would be
+very unlikely to overflow, but the following truncation to uint32
+would yield the correct result only in a narrow 32-value window just
+below UINT_MAX, if even that.
+
+Fix by using the proper tool, qAddOverflow.
+
+Manual conflict resolutions:
+ - qAddOverflow doesn't exist in Qt 5, use private add_overflow
+   predecessor API instead
+
+Change-Id: I7599f2e75ff7f488077b0c60b81022591005661c
+Reviewed-by: Allan Sandfeld Jensen <allan.jen...@qt.io>
+(cherry picked from commit ee5da1f2eaf8932aeca02ffea6e4c618585e29e3)
+Reviewed-by: Qt Cherry-pick Bot <cherrypick_...@qt-project.org>
+(cherry picked from commit debeb8878da2dc706ead04b6072ecbe7e5313860)
+Reviewed-by: Thiago Macieira <thiago.macie...@intel.com>
+Reviewed-by: Marc Mutz <marc.m...@qt.io>
+(cherry picked from commit 811b9eef6d08d929af8708adbf2a5effb0eb62d7)
+(cherry picked from commit f931facd077ce945f1e42eaa3bead208822d3e00)
+(cherry picked from commit 9ef4ca5ecfed771dab890856130e93ef5ceabef5)
+Reviewed-by: Mårten Nordheim <marten.nordh...@qt.io>
+---
+
+Index: 
qtbase-opensource-src-5.15.2+dfsg/src/network/access/http2/hpacktable.cpp
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/src/network/access/http2/hpacktable.cpp  
   2024-04-24 16:05:41.491907436 +0200
++++ qtbase-opensource-src-5.15.2+dfsg/src/network/access/http2/hpacktable.cpp  
2024-04-24 16:07:20.779882496 +0200
+@@ -40,6 +40,7 @@
+ #include "hpacktable_p.h"
+ 
+ #include <QtCore/qdebug.h>
++#include <QtCore/private/qnumeric_p.h>
+ 
+ #include <algorithm>
+ #include <cstddef>
+@@ -62,8 +63,10 @@
+     // for counting the number of references to the name and value would have
+     // 32 octets of overhead."
+ 
+-    const unsigned sum = unsigned(name.size() + value.size());
+-    if (std::numeric_limits<unsigned>::max() - 32 < sum)
++    size_t sum;
++    if (add_overflow(size_t(name.size()), size_t(value.size()), &sum))
++        return HeaderSize();
++    if (sum > (std::numeric_limits<unsigned>::max() - 32))
+         return HeaderSize();
+     return HeaderSize(true, quint32(sum + 32));
+ }
diff -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2024-25580.diff 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2024-25580.diff
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2024-25580.diff        
1970-01-01 01:00:00.000000000 +0100
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/CVE-2024-25580.diff        
2024-02-27 23:25:41.000000000 +0100
@@ -0,0 +1,197 @@
+diff --git a/src/gui/util/qktxhandler.cpp b/src/gui/util/qktxhandler.cpp
+index 0d98e97453..6a79e55109 100644
+--- a/src/gui/util/qktxhandler.cpp
++++ b/src/gui/util/qktxhandler.cpp
+@@ -73,7 +73,7 @@ struct KTXHeader {
+     quint32 bytesOfKeyValueData;
+ };
+ 
+-static const quint32 headerSize = sizeof(KTXHeader);
++static constexpr quint32 qktxh_headerSize = sizeof(KTXHeader);
+ 
+ // Currently unused, declared for future reference
+ struct KTXKeyValuePairItem {
+@@ -103,11 +103,36 @@ struct KTXMipmapLevel {
+     */
+ };
+ 
+-bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block)
++static bool qAddOverflow(quint32 v1, quint32 v2, quint32 *r) {
++    // unsigned additions are well-defined
++    *r = v1 + v2;
++    return v1 > quint32(v1 + v2);
++}
++
++// Returns the nearest multiple of 4 greater than or equal to 'value'
++static bool nearestMultipleOf4(quint32 value, quint32 *result)
++{
++    constexpr quint32 rounding = 4;
++    *result = 0;
++    if (qAddOverflow(value, rounding - 1, result))
++        return true;
++    *result &= ~(rounding - 1);
++    return false;
++}
++
++// Returns a slice with prechecked bounds
++static QByteArray safeSlice(const QByteArray& array, quint32 start, quint32 
length)
+ {
+-    Q_UNUSED(suffix)
++    quint32 end = 0;
++    if (qAddOverflow(start, length, &end) || end > quint32(array.length()))
++        return {};
++    return QByteArray(array.data() + start, length);
++}
+ 
+-    return (qstrncmp(block.constData(), ktxIdentifier, KTX_IDENTIFIER_LENGTH) 
== 0);
++bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block)
++{
++    Q_UNUSED(suffix);
++    return block.startsWith(QByteArray::fromRawData(ktxIdentifier, 
KTX_IDENTIFIER_LENGTH));
+ }
+ 
+ QTextureFileData QKtxHandler::read()
+@@ -115,42 +140,97 @@ QTextureFileData QKtxHandler::read()
+     if (!device())
+         return QTextureFileData();
+ 
+-    QByteArray buf = device()->readAll();
+-    const quint32 dataSize = quint32(buf.size());
+-    if (dataSize < headerSize || !canRead(QByteArray(), buf)) {
+-        qCDebug(lcQtGuiTextureIO, "Invalid KTX file %s", 
logName().constData());
++    const QByteArray buf = device()->readAll();
++    if (size_t(buf.size()) > std::numeric_limits<quint32>::max()) {
++        qWarning(lcQtGuiTextureIO, "Too big KTX file %s", 
logName().constData());
++        return QTextureFileData();
++    }
++
++    if (!canRead(QByteArray(), buf)) {
++        qWarning(lcQtGuiTextureIO, "Invalid KTX file %s", 
logName().constData());
++        return QTextureFileData();
++    }
++
++    if (buf.size() < qsizetype(qktxh_headerSize)) {
++        qWarning(lcQtGuiTextureIO, "Invalid KTX header size in %s", 
logName().constData());
+         return QTextureFileData();
+     }
+ 
+-    const KTXHeader *header = reinterpret_cast<const KTXHeader 
*>(buf.constData());
+-    if (!checkHeader(*header)) {
+-        qCDebug(lcQtGuiTextureIO, "Unsupported KTX file format in %s", 
logName().constData());
++    KTXHeader header;
++    memcpy(&header, buf.data(), qktxh_headerSize);
++    if (!checkHeader(header)) {
++        qWarning(lcQtGuiTextureIO, "Unsupported KTX file format in %s", 
logName().constData());
+         return QTextureFileData();
+     }
+ 
+     QTextureFileData texData;
+     texData.setData(buf);
+ 
+-    texData.setSize(QSize(decode(header->pixelWidth), 
decode(header->pixelHeight)));
+-    texData.setGLFormat(decode(header->glFormat));
+-    texData.setGLInternalFormat(decode(header->glInternalFormat));
+-    texData.setGLBaseInternalFormat(decode(header->glBaseInternalFormat));
+-
+-    texData.setNumLevels(decode(header->numberOfMipmapLevels));
+-    quint32 offset = headerSize + decode(header->bytesOfKeyValueData);
+-    const int maxLevels = qMin(texData.numLevels(), 32);               // Cap 
iterations in case of corrupt file.
+-    for (int i = 0; i < maxLevels; i++) {
+-        if (offset + sizeof(KTXMipmapLevel) > dataSize)                // 
Corrupt file; avoid oob read
+-            break;
+-        const KTXMipmapLevel *level = reinterpret_cast<const KTXMipmapLevel 
*>(buf.constData() + offset);
+-        quint32 levelLen = decode(level->imageSize);
+-        texData.setDataOffset(offset + sizeof(KTXMipmapLevel::imageSize), i);
+-        texData.setDataLength(levelLen, i);
+-        offset += sizeof(KTXMipmapLevel::imageSize) + levelLen + (3 - 
((levelLen + 3) % 4));
++    texData.setSize(QSize(decode(header.pixelWidth), 
decode(header.pixelHeight)));
++    texData.setGLFormat(decode(header.glFormat));
++    texData.setGLInternalFormat(decode(header.glInternalFormat));
++    texData.setGLBaseInternalFormat(decode(header.glBaseInternalFormat));
++
++    texData.setNumLevels(decode(header.numberOfMipmapLevels));
++
++    const quint32 bytesOfKeyValueData = decode(header.bytesOfKeyValueData);
++    quint32 headerKeyValueSize;
++    if (qAddOverflow(qktxh_headerSize, bytesOfKeyValueData, 
&headerKeyValueSize)) {
++        qWarning(lcQtGuiTextureIO, "Overflow in size of key value data in 
header of KTX file %s",
++                 logName().constData());
++        return QTextureFileData();
++    }
++
++    if (headerKeyValueSize >= quint32(buf.size())) {
++        qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", 
logName().constData());
++        return QTextureFileData();
++    }
++
++    // Technically, any number of levels is allowed but if the value is 
bigger than
++    // what is possible in KTX V2 (and what makes sense) we return an error.
++    // maxLevels = log2(max(width, height, depth))
++    const int maxLevels = (sizeof(quint32) * 8)
++            - qCountLeadingZeroBits(std::max(
++                    { header.pixelWidth, header.pixelHeight, 
header.pixelDepth }));
++
++    if (texData.numLevels() > maxLevels) {
++        qWarning(lcQtGuiTextureIO, "Too many levels in KTX file %s", 
logName().constData());
++        return QTextureFileData();
++    }
++
++    quint32 offset = headerKeyValueSize;
++    for (int level = 0; level < texData.numLevels(); level++) {
++        const auto imageSizeSlice = safeSlice(buf, offset, sizeof(quint32));
++        if (imageSizeSlice.isEmpty()) {
++            qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", 
logName().constData());
++            return QTextureFileData();
++        }
++
++        const quint32 imageSize = 
decode(qFromUnaligned<quint32>(imageSizeSlice.data()));
++        offset += sizeof(quint32); // overflow checked indirectly above
++
++        texData.setDataOffset(offset, level);
++        texData.setDataLength(imageSize, level);
++
++        // Add image data and padding to offset
++        quint32 padded = 0;
++        if (nearestMultipleOf4(imageSize, &padded)) {
++            qWarning(lcQtGuiTextureIO, "Overflow in KTX file %s", 
logName().constData());
++            return QTextureFileData();
++        }
++
++        quint32 offsetNext;
++        if (qAddOverflow(offset, padded, &offsetNext)) {
++            qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", 
logName().constData());
++            return QTextureFileData();
++        }
++
++        offset = offsetNext;
+     }
+ 
+     if (!texData.isValid()) {
+-        qCDebug(lcQtGuiTextureIO, "Invalid values in header of KTX file %s", 
logName().constData());
++        qWarning(lcQtGuiTextureIO, "Invalid values in header of KTX file %s",
++                 logName().constData());
+         return QTextureFileData();
+     }
+ 
+@@ -191,7 +271,7 @@ bool QKtxHandler::checkHeader(const KTXHeader &header)
+             (decode(header.numberOfFaces) == 1));
+ }
+ 
+-quint32 QKtxHandler::decode(quint32 val)
++quint32 QKtxHandler::decode(quint32 val) const
+ {
+     return inverseEndian ? qbswap<quint32>(val) : val;
+ }
+diff --git a/src/gui/util/qktxhandler_p.h b/src/gui/util/qktxhandler_p.h
+index f831e59d95..cdf1b2eaf8 100644
+--- a/src/gui/util/qktxhandler_p.h
++++ b/src/gui/util/qktxhandler_p.h
+@@ -68,7 +68,7 @@ public:
+ 
+ private:
+     bool checkHeader(const KTXHeader &header);
+-    quint32 decode(quint32 val);
++    quint32 decode(quint32 val) const;
+ 
+     bool inverseEndian = false;
+ };
diff -Nru qtbase-opensource-src-5.15.2+dfsg/debian/patches/series 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/series
--- qtbase-opensource-src-5.15.2+dfsg/debian/patches/series     2021-07-02 
17:58:04.000000000 +0200
+++ qtbase-opensource-src-5.15.2+dfsg/debian/patches/series     2024-04-28 
22:48:02.000000000 +0200
@@ -6,6 +6,19 @@
 mime_globs.diff
 fix-invalid-pointer-return-with-QGridLayout.diff
 
+CVE-2024-25580.diff
+CVE-2023-32763.diff
+CVE-2022-25255.diff
+CVE-2023-24607.diff
+sql_odbc_fix_unicode_check.diff
+sql_odbc_more_unicode_checks.diff
+CVE-2023-32762.diff
+CVE-2023-51714.diff
+CVE-2023-37369.diff
+CVE-2023-38197.diff
+CVE-2023-34410.diff
+CVE-2023-33285.diff
+
 # Debian specific.
 gnukfreebsd.diff
 no_htmlinfo_example.diff
diff -Nru 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/sql_odbc_fix_unicode_check.diff
 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/sql_odbc_fix_unicode_check.diff
--- 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/sql_odbc_fix_unicode_check.diff
    1970-01-01 01:00:00.000000000 +0100
+++ 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/sql_odbc_fix_unicode_check.diff
    2024-04-28 22:48:02.000000000 +0200
@@ -0,0 +1,24 @@
+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
+
+Index: 
qtbase-opensource-src-5.15.2+dfsg/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
   2024-04-28 17:51:58.976069584 +0200
++++ 
qtbase-opensource-src-5.15.2+dfsg/src/plugins/sqldrivers/odbc/qsql_odbc.cpp     
   2024-04-28 17:51:58.972069583 +0200
+@@ -125,7 +125,6 @@
+ {
+     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;
+ }
+ 
diff -Nru 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/sql_odbc_more_unicode_checks.diff
 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/sql_odbc_more_unicode_checks.diff
--- 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/sql_odbc_more_unicode_checks.diff
  1970-01-01 01:00:00.000000000 +0100
+++ 
qtbase-opensource-src-5.15.2+dfsg/debian/patches/sql_odbc_more_unicode_checks.diff
  2024-04-28 22:48:02.000000000 +0200
@@ -0,0 +1,37 @@
+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
+
+Index: 
qtbase-opensource-src-5.15.2+dfsg/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+===================================================================
+--- 
qtbase-opensource-src-5.15.2+dfsg.orig/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
   2024-04-28 17:59:07.172222178 +0200
++++ 
qtbase-opensource-src-5.15.2+dfsg/src/plugins/sqldrivers/odbc/qsql_odbc.cpp     
   2024-04-28 17:59:07.172222178 +0200
+@@ -2109,7 +2109,18 @@
+                                   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) {

Reply via email to