summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Ehrlicher <ch.ehrlicher@gmx.de>2019-10-06 12:56:34 +0200
committerChristian Ehrlicher <ch.ehrlicher@gmx.de>2019-10-15 13:37:42 +0200
commited7dd9a6edd7afd8798751c8b1d3ee7802ae253f (patch)
tree642dffad5d18cbad3f7bf723d89af0ab6874b50f
parent2ec93e29f75e0cb37650255d478b8e3a9da4dc25 (diff)
QODBC: Fix crash when a prepared statement is deleted after the db was removed5.13
When a prepared statement is still alive after the database was removed with QSqlDatabase::removeDatabase(), the cleanup routine is trying to access the driver which is no longer alive which results in a crash. Fixes: QTBUG-79019 Change-Id: I4630e3b947a12b23ed062f015abc373fc0e246c1 Reviewed-by: Andy Shaw <andy.shaw@qt.io>
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc.cpp10
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp27
2 files changed, 18 insertions, 19 deletions
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
index 7f98efccba..7709b13cd1 100644
--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
@@ -221,18 +221,18 @@ public:
int disconnectCount;
bool hasSQLFetchScroll;
- bool isStmtHandleValid();
+ bool isStmtHandleValid() const;
void updateStmtHandleState();
};
-bool QODBCResultPrivate::isStmtHandleValid()
+bool QODBCResultPrivate::isStmtHandleValid() const
{
- return disconnectCount == drv_d_func()->disconnectCount;
+ return drv_d_func() && disconnectCount == drv_d_func()->disconnectCount;
}
void QODBCResultPrivate::updateStmtHandleState()
{
- disconnectCount = drv_d_func()->disconnectCount;
+ disconnectCount = drv_d_func() ? drv_d_func()->disconnectCount : 0;
}
static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode = 0)
@@ -975,7 +975,7 @@ QODBCResult::QODBCResult(const QODBCDriver *db)
QODBCResult::~QODBCResult()
{
Q_D(QODBCResult);
- if (d->hStmt && d->isStmtHandleValid() && driver()->isOpen()) {
+ if (d->hStmt && d->isStmtHandleValid() && driver() && driver()->isOpen()) {
SQLRETURN r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt);
if (r != SQL_SUCCESS)
qSqlWarning(QLatin1String("QODBCDriver: Unable to free statement handle ")
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index 784d0a70d7..fd7f24f308 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -196,8 +196,7 @@ private slots:
void task_250026_data() { generic_data("QODBC"); }
void task_250026();
- void task_205701_data() { generic_data("QMYSQL"); }
- void task_205701();
+ void crashQueryOnCloseDatabase();
void task_233829_data() { generic_data("QPSQL"); }
void task_233829();
@@ -311,6 +310,8 @@ void tst_QSqlQuery::init()
void tst_QSqlQuery::cleanup()
{
+ if (QTest::currentTestFunction() == QLatin1String("crashQueryOnCloseDatabase"))
+ return;
QFETCH( QString, dbName );
QSqlDatabase db = QSqlDatabase::database( dbName );
CHECK_DATABASE( db );
@@ -3448,19 +3449,17 @@ void tst_QSqlQuery::task_250026()
QCOMPARE( q.value( 0 ).toString().length(), data1026.length() );
}
-void tst_QSqlQuery::task_205701()
+void tst_QSqlQuery::crashQueryOnCloseDatabase()
{
- QSqlDatabase qsdb = QSqlDatabase::addDatabase("QMYSQL", "atest");
- qsdb.setHostName("test");
- qsdb.setDatabaseName("test");
- qsdb.setUserName("test");
- qsdb.setPassword("test");
- qsdb.open();
-
-// {
- QSqlQuery query(qsdb);
-// }
- QSqlDatabase::removeDatabase("atest");
+ for (const auto &dbName : qAsConst(dbs.dbNames)) {
+ QSqlDatabase clonedDb = QSqlDatabase::cloneDatabase(
+ QSqlDatabase::database(dbName), "crashTest");
+ qDebug() << "Testing crash in sqlquery dtor for driver" << clonedDb.driverName();
+ QVERIFY(clonedDb.open());
+ QSqlQuery q(clonedDb);
+ clonedDb.close();
+ QSqlDatabase::removeDatabase("crashTest");
+ }
}
#ifdef NOT_READY_YET