From 67be01ae5048138e894fa8d3eb0abe93c5699048 Mon Sep 17 00:00:00 2001 From: Honglei Zhang Date: Thu, 8 Dec 2011 15:38:25 +0200 Subject: Check driver validity before using it Even though it is stated in the documentation that the SQL driver must remain valid during the life time of QSqlQuery, there are users who don't follow the rule. It's common that the destructor of QSqlQuery is called after the driver is already deleted. This fix checks the validity of the SQLite driver before QSqliteResult uses it in destructor. Task-number: QTBUG-16967 Change-Id: If0f52113f12e14102da1671cd6e12bdaa267114f Reviewed-by: Yunqiao Yin --- src/sql/drivers/sqlite/qsql_sqlite.cpp | 4 +++- src/sql/kernel/qsqlresult.cpp | 7 ++++--- tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp | 9 +++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index 38e4a63d57..d4acedc69b 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -292,7 +292,9 @@ QSQLiteResult::QSQLiteResult(const QSQLiteDriver* db) QSQLiteResult::~QSQLiteResult() { - qobject_cast(driver())->d->results.removeOne(this); + const QSqlDriver *sqlDriver = driver(); + if (sqlDriver) + qobject_cast(sqlDriver)->d->results.removeOne(this); d->cleanup(); delete d; } diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp index 71a81c0a8d..9065a6ad09 100644 --- a/src/sql/kernel/qsqlresult.cpp +++ b/src/sql/kernel/qsqlresult.cpp @@ -48,6 +48,7 @@ #include "qsqlresult.h" #include "qvector.h" #include "qsqldriver.h" +#include "qpointer.h" #include QT_BEGIN_NAMESPACE @@ -64,7 +65,7 @@ class QSqlResultPrivate { public: QSqlResultPrivate(QSqlResult* d) - : q(d), sqldriver(0), idx(QSql::BeforeFirstRow), active(false), + : q(d), idx(QSql::BeforeFirstRow), active(false), isSel(false), forwardOnly(false), precisionPolicy(QSql::LowPrecisionDouble), bindCount(0), binds(QSqlResult::PositionalBinding) {} @@ -98,7 +99,7 @@ public: public: QSqlResult* q; - const QSqlDriver* sqldriver; + QPointer sqldriver; int idx; QString sql; bool active; @@ -250,7 +251,7 @@ QString QSqlResultPrivate::namedToPositionalBinding() QSqlResult::QSqlResult(const QSqlDriver *db) { d = new QSqlResultPrivate(this); - d->sqldriver = db; + d->sqldriver = const_cast(db); if(db) { setNumericalPrecisionPolicy(db->numericalPrecisionPolicy()); } diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index c970020a01..2d96dbae76 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -3135,6 +3135,7 @@ void tst_QSqlQuery::QTBUG_21884() */ void tst_QSqlQuery::QTBUG_16967() { + QSqlQuery q2; QFETCH(QString, dbName); { QSqlDatabase db = QSqlDatabase::database(dbName); @@ -3146,6 +3147,7 @@ void tst_QSqlQuery::QTBUG_16967() QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); QSqlQuery q(db); + q2 = q; q.prepare("CREATE TABLE t1 (id INTEGER PRIMARY KEY, str TEXT);"); db.close(); QCOMPARE(db.lastError().type(), QSqlError::NoError); @@ -3154,8 +3156,9 @@ void tst_QSqlQuery::QTBUG_16967() QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); QSqlQuery q(db); - q.prepare("CREATE TABLE t1 (id INTEGER PRIMARY KEY, str TEXT);"); - q.exec(); + q2 = q; + q2.prepare("CREATE TABLE t1 (id INTEGER PRIMARY KEY, str TEXT);"); + q2.exec(); db.close(); QCOMPARE(db.lastError().type(), QSqlError::NoError); } @@ -3163,6 +3166,7 @@ void tst_QSqlQuery::QTBUG_16967() QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); QSqlQuery q(db); + q2 = q; q.exec("INSERT INTO t1 (id, str) VALUES(1, \"test1\");"); db.close(); QCOMPARE(db.lastError().type(), QSqlError::NoError); @@ -3171,6 +3175,7 @@ void tst_QSqlQuery::QTBUG_16967() QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); QSqlQuery q(db); + q2 = q; q.exec("SELECT * FROM t1;"); db.close(); QCOMPARE(db.lastError().type(), QSqlError::NoError); -- cgit v1.2.3