Fix access of tmpStorage in QODBCResult::exec().

Instead of using a list and appending / popping of elements, use
a vector of constant size and access via index to avoid
bookkeeping errors.

Task-number: QTBUG-37831

Change-Id: Icb5a182626c63e693b04daaf7a2f70997d9aeae1
Reviewed-by: Mark Brand <mabrand@mabrand.nl>
bb10
Friedemann Kleint 2014-04-02 10:37:59 +02:00 committed by The Qt Project
parent 00cfcfefb3
commit d5ff16bc8e
1 changed files with 20 additions and 25 deletions

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSql module of the Qt Toolkit.
@ -1323,12 +1323,12 @@ bool QODBCResult::exec()
if (isSelect())
SQLCloseCursor(d->hStmt);
QList<QByteArray> tmpStorage; // holds temporary buffers
QVarLengthArray<SQLLEN, 32> indicators(boundValues().count());
QVector<QVariant>& values = boundValues();
QVector<QByteArray> tmpStorage(values.count(), QByteArray()); // holds temporary buffers
QVarLengthArray<SQLLEN, 32> indicators(values.count());
memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN));
// bind parameters - only positional binding allowed
QVector<QVariant>& values = boundValues();
int i;
SQLRETURN r;
for (i = 0; i < values.count(); ++i) {
@ -1340,7 +1340,7 @@ bool QODBCResult::exec()
*ind = SQL_NULL_DATA;
switch (val.type()) {
case QVariant::Date: {
QByteArray ba;
QByteArray &ba = tmpStorage[i];
ba.resize(sizeof(DATE_STRUCT));
DATE_STRUCT *dt = (DATE_STRUCT *)ba.constData();
QDate qdt = val.toDate();
@ -1357,10 +1357,9 @@ bool QODBCResult::exec()
(void *) dt,
0,
*ind == SQL_NULL_DATA ? ind : NULL);
tmpStorage.append(ba);
break; }
case QVariant::Time: {
QByteArray ba;
QByteArray &ba = tmpStorage[i];
ba.resize(sizeof(TIME_STRUCT));
TIME_STRUCT *dt = (TIME_STRUCT *)ba.constData();
QTime qdt = val.toTime();
@ -1377,10 +1376,9 @@ bool QODBCResult::exec()
(void *) dt,
0,
*ind == SQL_NULL_DATA ? ind : NULL);
tmpStorage.append(ba);
break; }
case QVariant::DateTime: {
QByteArray ba;
QByteArray &ba = tmpStorage[i];
ba.resize(sizeof(TIMESTAMP_STRUCT));
TIMESTAMP_STRUCT * dt = (TIMESTAMP_STRUCT *)ba.constData();
QDateTime qdt = val.toDateTime();
@ -1412,7 +1410,6 @@ bool QODBCResult::exec()
(void *) dt,
0,
*ind == SQL_NULL_DATA ? ind : NULL);
tmpStorage.append(ba);
break; }
case QVariant::Int:
r = SQLBindParameter(d->hStmt,
@ -1503,6 +1500,7 @@ bool QODBCResult::exec()
break;
case QVariant::String:
if (d->unicode) {
QByteArray &ba = tmpStorage[i];
QString str = val.toString();
if (*ind != SQL_NULL_DATA)
*ind = str.length() * sizeof(SQLTCHAR);
@ -1510,7 +1508,7 @@ bool QODBCResult::exec()
if (bindValueType(i) & QSql::Out) {
const QVarLengthArray<SQLTCHAR> a(toSQLTCHAR(str));
QByteArray ba((const char *)a.constData(), a.size() * sizeof(SQLTCHAR));
ba = QByteArray((const char *)a.constData(), a.size() * sizeof(SQLTCHAR));
r = SQLBindParameter(d->hStmt,
i + 1,
qParamType[bindValueType(i) & QSql::InOut],
@ -1521,10 +1519,9 @@ bool QODBCResult::exec()
(void *)ba.data(),
ba.size(),
ind);
tmpStorage.append(ba);
break;
}
QByteArray strba((const char *)toSQLTCHAR(str).constData(), str.size()*sizeof(SQLTCHAR));
ba = QByteArray ((const char *)toSQLTCHAR(str).constData(), str.size()*sizeof(SQLTCHAR));
r = SQLBindParameter(d->hStmt,
i + 1,
qParamType[bindValueType(i) & QSql::InOut],
@ -1532,15 +1529,15 @@ bool QODBCResult::exec()
strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR,
strSize,
0,
(SQLPOINTER)strba.constData(),
strba.size(),
(SQLPOINTER)ba.constData(),
ba.size(),
ind);
tmpStorage.append(strba);
break;
}
else
{
QByteArray str = val.toString().toUtf8();
QByteArray &str = tmpStorage[i];
str = val.toString().toUtf8();
if (*ind != SQL_NULL_DATA)
*ind = str.length();
int strSize = str.length();
@ -1555,12 +1552,11 @@ bool QODBCResult::exec()
(void *)str.constData(),
strSize,
ind);
tmpStorage.append(str);
break;
}
// fall through
default: {
QByteArray ba = val.toByteArray();
QByteArray &ba = tmpStorage[i];
if (*ind != SQL_NULL_DATA)
*ind = ba.size();
r = SQLBindParameter(d->hStmt,
@ -1573,7 +1569,6 @@ bool QODBCResult::exec()
(void *) ba.constData(),
ba.length() + 1,
ind);
tmpStorage.append(ba);
break; }
}
if (r != SQL_SUCCESS) {
@ -1617,16 +1612,16 @@ bool QODBCResult::exec()
for (i = 0; i < values.count(); ++i) {
switch (values.at(i).type()) {
case QVariant::Date: {
DATE_STRUCT ds = *((DATE_STRUCT *)tmpStorage.takeFirst().constData());
DATE_STRUCT ds = *((DATE_STRUCT *)tmpStorage.at(i).constData());
values[i] = QVariant(QDate(ds.year, ds.month, ds.day));
break; }
case QVariant::Time: {
TIME_STRUCT dt = *((TIME_STRUCT *)tmpStorage.takeFirst().constData());
TIME_STRUCT dt = *((TIME_STRUCT *)tmpStorage.at(i).constData());
values[i] = QVariant(QTime(dt.hour, dt.minute, dt.second));
break; }
case QVariant::DateTime: {
TIMESTAMP_STRUCT dt = *((TIMESTAMP_STRUCT*)
tmpStorage.takeFirst().constData());
tmpStorage.at(i).constData());
values[i] = QVariant(QDateTime(QDate(dt.year, dt.month, dt.day),
QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000)));
break; }
@ -1642,7 +1637,7 @@ bool QODBCResult::exec()
case QVariant::String:
if (d->unicode) {
if (bindValueType(i) & QSql::Out) {
QByteArray first = tmpStorage.takeFirst();
const QByteArray &first = tmpStorage.at(i);
QVarLengthArray<SQLTCHAR> array;
array.append((SQLTCHAR *)first.constData(), first.size());
values[i] = fromSQLTCHAR(array, first.size()/sizeof(SQLTCHAR));
@ -1652,7 +1647,7 @@ bool QODBCResult::exec()
// fall through
default: {
if (bindValueType(i) & QSql::Out)
values[i] = tmpStorage.takeFirst();
values[i] = tmpStorage.at(i);
break; }
}
if (indicators[i] == SQL_NULL_DATA)