From d5ff16bc8ebf0f17fae3a28f08018db26567e81c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 2 Apr 2014 10:37:59 +0200 Subject: 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 --- src/sql/drivers/odbc/qsql_odbc.cpp | 45 +++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index ac6d677d54..c950d2c2ef 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -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 tmpStorage; // holds temporary buffers - QVarLengthArray indicators(boundValues().count()); + QVector& values = boundValues(); + QVector tmpStorage(values.count(), QByteArray()); // holds temporary buffers + QVarLengthArray indicators(values.count()); memset(indicators.data(), 0, indicators.size() * sizeof(SQLLEN)); // bind parameters - only positional binding allowed - QVector& 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 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 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) -- cgit v1.2.3