Check for null driver() before trying to exec()
QSqlQuery::exec() took for granted that it can dereference driver(), which should be true for all sane usage; however, it should not crash if used misguidedly. Added regression test, based on bug report's reproducer, which crashes without the fix. Fixes: QTBUG-100037 Pick-to: 6.3 6.2 5.15 5.12 Change-Id: I94600bc60f89e82a1121b418144006a683921a38 Reviewed-by: Andy Shaw <andy.shaw@qt.io>
This commit is contained in:
parent
f172b964f6
commit
78eac57f3d
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtSql module of the Qt Toolkit.
|
||||
@ -406,6 +406,10 @@ bool QSqlQuery::exec(const QString& query)
|
||||
QElapsedTimer t;
|
||||
t.start();
|
||||
#endif
|
||||
if (!driver()) {
|
||||
qWarning("QSqlQuery::exec: called before driver has been set up");
|
||||
return false;
|
||||
}
|
||||
if (d->ref.loadRelaxed() != 1) {
|
||||
bool fo = isForwardOnly();
|
||||
*this = QSqlQuery(driver()->createResult());
|
||||
|
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2022 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
@ -70,6 +70,8 @@ private slots:
|
||||
void query_exec();
|
||||
void execErrorRecovery_data() { generic_data(); }
|
||||
void execErrorRecovery();
|
||||
void prematureExec_data() { generic_data(); }
|
||||
void prematureExec();
|
||||
void first_data() { generic_data(); }
|
||||
void first();
|
||||
void next_data() { generic_data(); }
|
||||
@ -2878,6 +2880,35 @@ void tst_QSqlQuery::execErrorRecovery()
|
||||
QVERIFY_SQL( q, exec() );
|
||||
}
|
||||
|
||||
void tst_QSqlQuery::prematureExec()
|
||||
{
|
||||
QFETCH(QString, dbName);
|
||||
// We only want the engine name, for addDatabase():
|
||||
int cut = dbName.indexOf(QChar('@'));
|
||||
if (cut < 0)
|
||||
QSKIP("Failed to parse database type out of name");
|
||||
dbName.truncate(cut);
|
||||
cut = dbName.indexOf(QChar('_'));
|
||||
if (cut >= 0)
|
||||
dbName = dbName.sliced(cut + 1);
|
||||
|
||||
auto db = QSqlDatabase::addDatabase(dbName);
|
||||
QSqlQuery q(db);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"QSqlDatabasePrivate::removeDatabase: connection "
|
||||
"'qt_sql_default_connection' is still in use, all "
|
||||
"queries will cease to work.");
|
||||
QTest::ignoreMessage(QtWarningMsg,
|
||||
"QSqlDatabasePrivate::addDatabase: duplicate connection name "
|
||||
"'qt_sql_default_connection', old connection removed.");
|
||||
auto otherDb = QSqlDatabase::addDatabase(dbName);
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "QSqlQuery::exec: called before driver has been set up");
|
||||
// QTBUG-100037: shouldn't crash !
|
||||
QVERIFY(!q.exec("select stuff from TheVoid"));
|
||||
}
|
||||
|
||||
void tst_QSqlQuery::lastInsertId()
|
||||
{
|
||||
QFETCH( QString, dbName );
|
||||
|
Loading…
x
Reference in New Issue
Block a user