diff options
author | Bill King <bking@trolltech.com> | 2009-12-15 03:09:12 (GMT) |
---|---|---|
committer | Bill King <bking@trolltech.com> | 2009-12-15 03:09:12 (GMT) |
commit | 82ec0a6c26c683dedd20fb6dd3923dce98c3f7e3 (patch) | |
tree | 47e095977dc9ae6e20bedff0b1e8f963ede741e5 | |
parent | 504d6d4ac0d782c1fbca1f2dc1e8425dac773113 (diff) | |
download | Qt-82ec0a6c26c683dedd20fb6dd3923dce98c3f7e3.zip Qt-82ec0a6c26c683dedd20fb6dd3923dce98c3f7e3.tar.gz Qt-82ec0a6c26c683dedd20fb6dd3923dce98c3f7e3.tar.bz2 |
(ODBC) Fixes segfault when error string is larger than 256 chars.
SqlServer can throw custom error messages (via RaiseError) that can be
up to 8000 chars long. Fixed this with a pre-query as to the length of
the error string, then allocating enough space to retrieve the whole
error string at once.
Task-number: QTBUG-6618
Reviewed-by: Derick Hawcroft
-rw-r--r-- | src/sql/drivers/odbc/qsql_odbc.cpp | 23 | ||||
-rw-r--r-- | tests/auto/qsqlquery/tst_qsqlquery.cpp | 24 |
2 files changed, 41 insertions, 6 deletions
diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index e686873..fdf0c2c 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -172,28 +172,39 @@ static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode SQLSMALLINT msgLen = 0; SQLRETURN r = SQL_NO_DATA; SQLTCHAR state_[SQL_SQLSTATE_SIZE+1]; - SQLTCHAR description_[SQL_MAX_MESSAGE_LENGTH]; + QVarLengthArray<SQLTCHAR> description_(SQL_MAX_MESSAGE_LENGTH); QString result; int i = 1; description_[0] = 0; + r = SQLGetDiagRec(handleType, + handle, + i, + state_, + &nativeCode_, + 0, + NULL, + &msgLen); + if(r == SQL_NO_DATA) + return QString(); + description_.resize(msgLen+1); do { r = SQLGetDiagRec(handleType, handle, i, - (SQLTCHAR*)state_, + state_, &nativeCode_, - (SQLTCHAR*)description_, - SQL_MAX_MESSAGE_LENGTH, /* in bytes, not in characters */ + description_.data(), + description_.size(), &msgLen); if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) { if (nativeCode) *nativeCode = nativeCode_; QString tmpstore; #ifdef UNICODE - tmpstore = QString((const QChar*)description_, msgLen); + tmpstore = QString((const QChar*)description_.data(), msgLen); #else - tmpstore = QString::fromLocal8Bit((const char*)description_, msgLen); + tmpstore = QString::fromLocal8Bit((const char*)description_.data(), msgLen); #endif if(result != tmpstore) { if(!result.isEmpty()) diff --git a/tests/auto/qsqlquery/tst_qsqlquery.cpp b/tests/auto/qsqlquery/tst_qsqlquery.cpp index a8908fd..2a55c32 100644 --- a/tests/auto/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/qsqlquery/tst_qsqlquery.cpp @@ -201,6 +201,8 @@ private slots: void QTBUG_5251(); void QTBUG_6421_data() { generic_data("QOCI"); } void QTBUG_6421(); + void QTBUG_6618_data() { generic_data("QODBC"); } + void QTBUG_6618(); private: // returns all database connections @@ -2961,5 +2963,27 @@ void tst_QSqlQuery::QTBUG_6421() QCOMPARE(q.value(0).toString(), QLatin1String("\"COL3\"")); } +void tst_QSqlQuery::QTBUG_6618() +{ + QFETCH( QString, dbName ); + QSqlDatabase db = QSqlDatabase::database( dbName ); + CHECK_DATABASE( db ); + if (!tst_Databases::isSqlServer( db )) + QSKIP("SQL Server specific test", SkipSingle); + + QSqlQuery q(db); + q.exec( "drop procedure " + qTableName( "tst_raiseError" ) ); //non-fatal + QString errorString; + for (int i=0;i<110;i++) + errorString+="reallylong"; + errorString+=" error"; + QVERIFY_SQL( q, exec("create procedure " + qTableName( "tst_raiseError" ) + " as\n" + "begin\n" + " raiserror('" + errorString + "', 16, 1)\n" + "end\n" )); + q.exec( "{call " + qTableName( "tst_raiseError" ) + "}" ); + QVERIFY(q.lastError().text().contains(errorString)); +} + QTEST_MAIN( tst_QSqlQuery ) #include "tst_qsqlquery.moc" |