diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2020-09-07 14:48:57 +0200 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2020-10-09 01:11:00 +0200 |
commit | 2a6f2fe9ef9a5d0755443ba94183d97b2fac1a28 (patch) | |
tree | 0306fe462f93f293f94b9869749c775dce3744ca /src/corelib/time | |
parent | cb0ecd6b6dfaea372d7973e4d78e661deb441540 (diff) |
Check against {und,ov}erflow in more QDateTime methods
QDateTime's range of possible values is wider than anyone generally
needs, but let's not do confusing things when someone does overflow
it.
Change-Id: Ifbaf7a0f02cd3afe7d3d13c829bf0887eba29f7f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Diffstat (limited to 'src/corelib/time')
-rw-r--r-- | src/corelib/time/qdatetime.cpp | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 559b3764a1..0be4f290be 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -3959,7 +3959,15 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs) */ void QDateTime::setSecsSinceEpoch(qint64 secs) { - setMSecsSinceEpoch(secs * 1000); + qint64 msecs; + if (!mul_overflow(secs, std::integral_constant<qint64, 1000>(), &msecs)) { + setMSecsSinceEpoch(msecs); + } else if (d.isShort()) { + d.data.status &= ~QDateTimePrivate::ValidWhenMask; + } else { + d.detach(); + d->m_status &= ~QDateTimePrivate::ValidWhenMask; + } } #if QT_CONFIG(datestring) // depends on, so implies, textdate @@ -4208,7 +4216,10 @@ QDateTime QDateTime::addYears(int nyears) const QDateTime QDateTime::addSecs(qint64 s) const { - return addMSecs(s * 1000); + qint64 msecs; + if (mul_overflow(s, std::integral_constant<qint64, 1000>(), &msecs)) + return QDateTime(); + return addMSecs(msecs); } /*! @@ -4226,15 +4237,31 @@ QDateTime QDateTime::addMSecs(qint64 msecs) const return QDateTime(); QDateTime dt(*this); - auto spec = getSpec(d); - if (spec == Qt::LocalTime || spec == Qt::TimeZone) { - // Convert to real UTC first in case crosses DST transition - dt.setMSecsSinceEpoch(toMSecsSinceEpoch() + msecs); - } else { + switch (getSpec(d)) { + case Qt::LocalTime: + case Qt::TimeZone: + // Convert to real UTC first in case this crosses a DST transition: + if (!add_overflow(toMSecsSinceEpoch(), msecs, &msecs)) { + dt.setMSecsSinceEpoch(msecs); + } else if (dt.d.isShort()) { + dt.d.data.status &= ~QDateTimePrivate::ValidWhenMask; + } else { + dt.d.detach(); + dt.d->m_status &= ~QDateTimePrivate::ValidWhenMask; + } + break; + case Qt::UTC: + case Qt::OffsetFromUTC: // No need to convert, just add on - if (d.isShort()) { + if (add_overflow(getMSecs(d), msecs, &msecs)) { + if (dt.d.isShort()) { + dt.d.data.status &= ~QDateTimePrivate::ValidWhenMask; + } else { + dt.d.detach(); + dt.d->m_status &= ~QDateTimePrivate::ValidWhenMask; + } + } else if (d.isShort()) { // need to check if we need to enlarge first - msecs += dt.d.data.msecs; if (msecsCanBeSmall(msecs)) { dt.d.data.msecs = qintptr(msecs); } else { @@ -4243,8 +4270,9 @@ QDateTime QDateTime::addMSecs(qint64 msecs) const } } else { dt.d.detach(); - dt.d->m_msecs += msecs; + dt.d->m_msecs = msecs; } + break; } return dt; } @@ -4289,7 +4317,7 @@ qint64 QDateTime::daysTo(const QDateTime &other) const qint64 QDateTime::secsTo(const QDateTime &other) const { - return (msecsTo(other) / 1000); + return msecsTo(other) / 1000; } /*! |