forked from pool/libqt5-qtbase
Accepting request 602103 from KDE:Qt5
- 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 OBS-URL: https://build.opensuse.org/request/show/602103 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/libqt5-qtbase?expand=0&rev=80
This commit is contained in:
parent
f4d805462a
commit
24f02395f2
@ -0,0 +1,33 @@
|
||||
From cd12671fac459b71d2f5f65d3e221e4e8fca25f1 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Shaw <andy.shaw@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.welbourne@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
|
||||
|
@ -0,0 +1,91 @@
|
||||
From 0c8aa32d9a1b1952c5d53529655c485f5b34a695 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Shaw <andy.shaw@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.Fernandez@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
|
||||
|
@ -0,0 +1,97 @@
|
||||
From f9b3ad5f5f6a36e7c45bdfbe61b364dcba70836d Mon Sep 17 00:00:00 2001
|
||||
From: Andy Shaw <andy.shaw@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.kobus@qt.io>
|
||||
Reviewed-by: Edward Welbourne <edward.welbourne@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
|
||||
|
@ -1,3 +1,11 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Apr 27 16:25:43 UTC 2018 - fabian@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
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Mar 27 18:22:40 UTC 2018 - fabian@ritter-vogt.de
|
||||
|
||||
|
@ -102,6 +102,9 @@ Patch2026: 0016-CUPS-Rework-set-clearCupsOption-API.patch
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user