From 064c3d35e6809672323e8d912e9140ddd0ad48cd Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 29 Nov 2021 13:43:16 +0100 Subject: Don't allocate an OCIDateTime object unless we're going to use it The QOCIDateTime destructor carefully checks that dateTime is non-null before tidying it away, but the constructor allocated it independently of whether it was used, leaving it in a still-not-constructed state if the date-time it was to represent was invalid. Only allocate if the date-time is valid; and check against null when an OCIDateTime is being converted back to QDateTime. Add warnings if either allocation or construction fails. Incidentally use static_cast<> instead of C-casting (and split a long line) in the other place that allocates an OCIDateTime descriptor. Pick-to: 6.2 5.15 Task-number: QTBUG-98471 Change-Id: Idd5531d9f7101878802cb9a3a016d3fd80903543 Reviewed-by: Andy Shaw Reviewed-by: Qt CI Bot --- src/plugins/sqldrivers/oci/qsql_oci.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/plugins/sqldrivers/oci/qsql_oci.cpp b/src/plugins/sqldrivers/oci/qsql_oci.cpp index 638b01b022..b0f68c0d09 100644 --- a/src/plugins/sqldrivers/oci/qsql_oci.cpp +++ b/src/plugins/sqldrivers/oci/qsql_oci.cpp @@ -168,16 +168,27 @@ public: QOCIDateTime::QOCIDateTime(OCIEnv *env, OCIError *err, const QDateTime &dt) : dateTime(nullptr) { - OCIDescriptorAlloc(env, reinterpret_cast(&dateTime), OCI_DTYPE_TIMESTAMP_TZ, 0, 0); - if (dt.isValid()) { + if (!dt.isValid()) { + // nothing to do, leave dateTime null + } else if (OCIDescriptorAlloc(env, reinterpret_cast(&dateTime), + OCI_DTYPE_TIMESTAMP_TZ, 0, 0) == OCI_SUCCESS) { + Q_ASSERT(!dt.isNull()); const QDate date = dt.date(); + Q_ASSERT(date.isValid()); const QTime time = dt.time(); + Q_ASSERT(time.isValid()); // Zone in +hh:mm format (stripping UTC prefix from OffsetName) - QString timeZone = dt.timeZone().displayName(dt, QTimeZone::OffsetName).mid(3); + QString timeZone = dt.timeZone().displayName(dt, QTimeZone::OffsetName); + Q_ASSERT(timeZone.startsWith(u"UTC")); + timeZone = std::move(timeZone).sliced(3); const OraText *tz = reinterpret_cast(timeZone.utf16()); - OCIDateTimeConstruct(env, err, dateTime, date.year(), date.month(), date.day(), time.hour(), - time.minute(), time.second(), time.msec() * 1000000, - const_cast(tz), timeZone.length() * sizeof(QChar)); + if (OCIDateTimeConstruct(env, err, dateTime, date.year(), date.month(), date.day(), + time.hour(), time.minute(), time.second(), time.msec() * 1000000, + const_cast(tz), timeZone.length() * sizeof(QChar))) { + qWarning("QOCIDateTime: Failed to construct the OCIDateTime descriptor"); + } + } else { + qWarning("QOCIDateTime: Failed to allocate the OCIDateTime descriptor"); } } @@ -189,6 +200,9 @@ QOCIDateTime::~QOCIDateTime() QDateTime QOCIDateTime::fromOCIDateTime(OCIEnv *env, OCIError *err, OCIDateTime *dateTime) { + if (!dateTime) + return QDateTime(); + sb2 year; ub1 month, day, hour, minute, second; ub4 nsec; @@ -937,7 +951,8 @@ QOCICols::QOCICols(int size, QOCIResultPrivate* dp) switch (ofi.type.id()) { case QMetaType::QDateTime: - r = OCIDescriptorAlloc(d->env, (void **)&fieldInf[idx].dataPtr, OCI_DTYPE_TIMESTAMP_TZ, 0, 0); + r = OCIDescriptorAlloc(d->env, static_cast(&fieldInf[idx].dataPtr), + OCI_DTYPE_TIMESTAMP_TZ, 0, 0); if (r != OCI_SUCCESS) { qWarning("QOCICols: Unable to allocate the OCIDateTime descriptor"); break; -- cgit v1.2.3