Hello community,

here is the log from the commit of package libqt5-qtbase for openSUSE:Factory 
checked in at 2018-04-30 22:50:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libqt5-qtbase (Old)
 and      /work/SRC/openSUSE:Factory/.libqt5-qtbase.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libqt5-qtbase"

Mon Apr 30 22:50:53 2018 rev:80 rq:602103 version:5.10.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/libqt5-qtbase/libqt5-qtbase.changes      
2018-03-30 12:02:49.619704441 +0200
+++ /work/SRC/openSUSE:Factory/.libqt5-qtbase.new/libqt5-qtbase.changes 
2018-04-30 22:50:54.898027170 +0200
@@ -1,0 +2,8 @@
+Fri Apr 27 16:25:43 UTC 2018 - fab...@ritter-vogt.de
+
+- Add patches to fix crashes with certain sqlite queries:
+  * 0001-sqlite-Check-that-there-are-values-to-be-set-when-bi.patch
+  * 0002-sqlite-Bind-duplicated-named-placeholders-correctly.patch
+  * 0003-sqlite-Prevent-a-crash-when-sqlite-does-not-detect-a.patch
+
+-------------------------------------------------------------------

New:
----
  0001-sqlite-Check-that-there-are-values-to-be-set-when-bi.patch
  0002-sqlite-Bind-duplicated-named-placeholders-correctly.patch
  0003-sqlite-Prevent-a-crash-when-sqlite-does-not-detect-a.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libqt5-qtbase.spec ++++++
--- /var/tmp/diff_new_pack.nV3mlc/_old  2018-04-30 22:50:56.569966168 +0200
+++ /var/tmp/diff_new_pack.nV3mlc/_new  2018-04-30 22:50:56.573966022 +0200
@@ -102,6 +102,9 @@
 Patch2027:      0017-Cups-Print-Dialog-Change-the-message-box-titles-to-C.patch
 Patch2028:      0018-Fix-build-due-to-missing-QDebug-include.patch
 Patch2029:      0001-Do-a-static_cast-in-bit-blasts-that-are-UB.patch
+Patch2030:      0001-sqlite-Check-that-there-are-values-to-be-set-when-bi.patch
+Patch2031:      0002-sqlite-Bind-duplicated-named-placeholders-correctly.patch
+Patch2032:      0003-sqlite-Prevent-a-crash-when-sqlite-does-not-detect-a.patch
 BuildRequires:  alsa-devel
 BuildRequires:  cups-devel
 BuildRequires:  double-conversion-devel

++++++ 0001-sqlite-Check-that-there-are-values-to-be-set-when-bi.patch ++++++
>From cd12671fac459b71d2f5f65d3e221e4e8fca25f1 Mon Sep 17 00:00:00 2001
From: Andy Shaw <andy.s...@qt.io>
Date: Thu, 7 Dec 2017 16:01:48 +0100
Subject: [PATCH 1/3] sqlite: Check that there are values to be set when
 binding

If the values vector is empty then we know already that the paramCount
will still be invalid, so we should just accept that and not check the
reused named placeholders.

Task-number: QTBUG-64923
Change-Id: Ifaa755540c4574f1f76d3f9f129bf0f66b837b70
Reviewed-by: Edward Welbourne <edward.welbou...@qt.io>
---
 src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp 
b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
index e9f5ee9508..67dd1a6ee5 100644
--- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
+++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
@@ -467,7 +467,7 @@ bool QSQLiteResult::exec()
 
 #if (SQLITE_VERSION_NUMBER >= 3003011)
     // In the case of the reuse of a named placeholder
-    if (!paramCountIsValid) {
+    if (paramCount < values.count()) {
         const auto countIndexes = [](int counter, const QList<int>& indexList) 
{
                                       return counter + indexList.length();
                                   };
-- 
2.16.2

++++++ 0002-sqlite-Bind-duplicated-named-placeholders-correctly.patch ++++++
>From 0c8aa32d9a1b1952c5d53529655c485f5b34a695 Mon Sep 17 00:00:00 2001
From: Andy Shaw <andy.s...@qt.io>
Date: Tue, 2 Jan 2018 09:33:48 +0100
Subject: [PATCH 2/3] sqlite: Bind duplicated named placeholders correctly

sqlite will reuse the index for bound parameters when the named
placeholder is duplicated so we only need to call bind one time for each
placeholder. Therefore we need to have just one instance of each value
when doing the bind.

Task-number: QTBUG-65150
Change-Id: I75c4bcc4563e43c180a59a7a4cbb770dbe994642
Reviewed-by: Jesus Fernandez <jesus.fernan...@qt.io>
---
 src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp     | 16 ++++++++++++++-
 tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp | 25 +++++++++++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp 
b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
index 67dd1a6ee5..444b18686a 100644
--- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
+++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
@@ -446,7 +446,7 @@ static QString timespecToString(const QDateTime &dateTime)
 bool QSQLiteResult::exec()
 {
     Q_D(QSQLiteResult);
-    const QVector<QVariant> values = boundValues();
+    QVector<QVariant> values = boundValues();
 
     d->skippedStatus = false;
     d->skipRow = false;
@@ -478,6 +478,20 @@ bool QSQLiteResult::exec()
                                                    countIndexes);
 
         paramCountIsValid = bindParamCount == values.count();
+        // When using named placeholders, it will reuse the index for 
duplicated
+        // placeholders. So we need to ensure the QVector has only one 
instance of
+        // each value as SQLite will do the rest for us.
+        QVector<QVariant> prunedValues;
+        QList<int> handledIndexes;
+        for (int i = 0, currentIndex = 0; i < values.size(); ++i) {
+            if (handledIndexes.contains(i))
+                continue;
+            const auto placeHolder = 
QString::fromUtf8(sqlite3_bind_parameter_name(d->stmt, currentIndex + 1));
+            handledIndexes << d->indexes[placeHolder];
+            prunedValues << values.at(d->indexes[placeHolder].first());
+            ++currentIndex;
+        }
+        values = prunedValues;
     }
 #endif
 
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp 
b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index 3ea13896d8..1a0340f153 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -2017,6 +2017,31 @@ void tst_QSqlQuery::prepare_bind_exec()
         QCOMPARE( q.value(1).toString(), QString("name") );
         QCOMPARE( q.value(2).toString(), QString("name") );
 
+        // Test that duplicated named placeholders before the next unique one 
works correctly - QTBUG-65150
+        QVERIFY(q.prepare("insert into " + qtest_prepare + " (id, name, name2) 
values (:id, :id, :name)"));
+        for (i = 104; i < 106; ++i) {
+            q.bindValue(":id", i);
+            q.bindValue(":name", "name");
+            QVERIFY(q.exec());
+        }
+        QVERIFY(q.exec("select * from " + qtest_prepare + " where id > 103 
order by id"));
+        QVERIFY(q.next());
+        QCOMPARE(q.value(0).toInt(), 104);
+        QCOMPARE(q.value(1).toString(), QString("104"));
+        QCOMPARE(q.value(2).toString(), QString("name"));
+
+        // Test that duplicated named placeholders in any order
+        QVERIFY(q.prepare("insert into " + qtest_prepare + " (id, name, name2) 
values (:id, :name, :id)"));
+        for (i = 107; i < 109; ++i) {
+            q.bindValue(":id", i);
+            q.bindValue(":name", "name");
+            QVERIFY(q.exec());
+        }
+        QVERIFY(q.exec("select * from " + qtest_prepare + " where id > 106 
order by id"));
+        QVERIFY(q.next());
+        QCOMPARE(q.value(0).toInt(), 107);
+        QCOMPARE(q.value(1).toString(), QString("name"));
+        QCOMPARE(q.value(2).toString(), QString("107"));
     } // end of SQLite scope
 }
 
-- 
2.16.2

++++++ 0003-sqlite-Prevent-a-crash-when-sqlite-does-not-detect-a.patch ++++++
>From f9b3ad5f5f6a36e7c45bdfbe61b364dcba70836d Mon Sep 17 00:00:00 2001
From: Andy Shaw <andy.s...@qt.io>
Date: Wed, 7 Mar 2018 15:12:13 +0100
Subject: [PATCH 3/3] sqlite: Prevent a crash when sqlite does not detect any
 parameters

When using a virtual table inside a SQLite database it is possible that
it does not report the right number of parameters. Therefore we need
to account for this case to prevent it from crashing when trying to
bind parameters it thinks does not exist.

Task-number: QTBUG-66816
Change-Id: I3ff70bb1fe73091f43c3df53616f75858e451cfd
Reviewed-by: Jarek Kobus <jaroslaw.ko...@qt.io>
Reviewed-by: Edward Welbourne <edward.welbou...@qt.io>
---
 src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp     |  5 ++-
 tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp | 41 +++++++++++++++++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp 
b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
index 444b18686a..08875299b2 100644
--- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
+++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
@@ -467,7 +467,10 @@ bool QSQLiteResult::exec()
 
 #if (SQLITE_VERSION_NUMBER >= 3003011)
     // In the case of the reuse of a named placeholder
-    if (paramCount < values.count()) {
+    // We need to check explicitly that paramCount is greater than 1, as sqlite
+    // can end up in a case where for virtual tables it returns 0 even though 
it
+    // has parameters
+    if (paramCount > 1 && paramCount < values.count()) {
         const auto countIndexes = [](int counter, const QList<int>& indexList) 
{
                                       return counter + indexList.length();
                                   };
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp 
b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index 1a0340f153..c57dbb8a01 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -172,6 +172,8 @@ private slots:
     void emptyTableNavigate();
     void timeStampParsing_data() { generic_data(); }
     void timeStampParsing();
+    void sqliteVirtualTable_data() { generic_data("QSQLITE"); }
+    void sqliteVirtualTable();
 
 #ifdef NOT_READY_YET
     void task_229811();
@@ -4167,5 +4169,44 @@ void tst_QSqlQuery::QTBUG_57138()
     QCOMPARE(q.value(2).toDateTime(), tzoffset);
 }
 
+void tst_QSqlQuery::sqliteVirtualTable()
+{
+    // Virtual tables can behave differently when it comes to prepared
+    // queries, so we need to check these explicitly
+    QFETCH(QString, dbName);
+    QSqlDatabase db = QSqlDatabase::database(dbName);
+    CHECK_DATABASE(db);
+    const auto tableName = qTableName("sqliteVirtual", __FILE__, db);
+    QSqlQuery qry(db);
+    QVERIFY_SQL(qry, exec("create virtual table " + tableName + " using 
fts3(id, name)"));
+
+    // Delibrately malform the query to try and provoke a potential crash 
situation
+    QVERIFY_SQL(qry, prepare("select * from " + tableName + " where name match 
'?'"));
+    qry.addBindValue("Andy");
+    QVERIFY(!qry.exec());
+
+    QVERIFY_SQL(qry, prepare("insert into " + tableName + "(id, name) VALUES 
(?, ?)"));
+    qry.addBindValue(1);
+    qry.addBindValue("Andy");
+    QVERIFY_SQL(qry, exec());
+
+    QVERIFY_SQL(qry, exec("select * from " + tableName));
+    QVERIFY(qry.next());
+    QCOMPARE(qry.value(0).toInt(), 1);
+    QCOMPARE(qry.value(1).toString(), "Andy");
+
+    QVERIFY_SQL(qry, prepare("insert into " + tableName + "(id, name) values 
(:id, :name)"));
+    qry.bindValue(":id", 2);
+    qry.bindValue(":name", "Peter");
+    QVERIFY_SQL(qry, exec());
+
+    QVERIFY_SQL(qry, prepare("select * from " + tableName + " where name match 
?"));
+    qry.addBindValue("Peter");
+    QVERIFY_SQL(qry, exec());
+    QVERIFY(qry.next());
+    QCOMPARE(qry.value(0).toInt(), 2);
+    QCOMPARE(qry.value(1).toString(), "Peter");
+}
+
 QTEST_MAIN( tst_QSqlQuery )
 #include "tst_qsqlquery.moc"
-- 
2.16.2


Reply via email to