diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2021-03-01 14:22:55 +0100 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2021-05-26 18:00:01 +0200 |
commit | 451500f8f81b562d65208141785e3b2077768576 (patch) | |
tree | a1e9b2b00566c4c12cab439d11cbcf489f546144 /tests/auto/corelib | |
parent | fc6629b6bbe1ef3fb9cf58da32b5a0bf082caa4d (diff) |
Check for overflow in QDateTime::setMSecsSinceEpoch()
When adding an offset from UTC, arithmetic may overflow. Likewise
when combining a date and time (that have been offset for UTC). Also
check the return from epochMSecsToLocalTime(), as it can fail; and pay
attention to the status stored by setDateTime(), to notice when it
hits an overflow. Fixed some tests that only passed because we
neglected these checks. Extended a test to check we detect overflow in
a couple of cases close to the extremes.
Change-Id: I127a670302f94a07bb9b087b1b9c608b7c08785c
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Øystein Heskestad <oystein.heskestad@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib')
-rw-r--r-- | tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index 4342161345..6e68b4af05 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -573,6 +573,7 @@ void tst_QDateTime::setSecsSinceEpoch() QCOMPARE(dt1.offsetFromUtc(), 60 * 60); // Only testing UTC; see fromSecsSinceEpoch() for fuller test. + dt1.setTimeSpec(Qt::UTC); const qint64 maxSeconds = std::numeric_limits<qint64>::max() / 1000; dt1.setSecsSinceEpoch(maxSeconds); QVERIFY(dt1.isValid()); @@ -727,6 +728,17 @@ void tst_QDateTime::setMSecsSinceEpoch() QDateTime reference(QDate(1970, 1, 1), QTime(0, 0), Qt::UTC); QCOMPARE(dt, reference.addMSecs(msecs)); + // Tests that we correctly recognize when we fall off the extremities: + if (msecs == std::numeric_limits<qint64>::max()) { + QDateTime off(QDate(1970, 1, 1).startOfDay(Qt::OffsetFromUTC, 1)); + off.setMSecsSinceEpoch(msecs); + QVERIFY(!off.isValid()); + } else if (msecs == std::numeric_limits<qint64>::min()) { + QDateTime off(QDate(1970, 1, 1).startOfDay(Qt::OffsetFromUTC, -1)); + off.setMSecsSinceEpoch(msecs); + QVERIFY(!off.isValid()); + } + if ((localTimeType == LocalTimeAheadOfUtc && msecs == std::numeric_limits<qint64>::max()) || (localTimeType == LocalTimeBehindUtc && msecs == std::numeric_limits<qint64>::min())) { QDateTime curt = QDate(1970, 1, 1).startOfDay(); // initially in short-form @@ -766,32 +778,39 @@ void tst_QDateTime::fromMSecsSinceEpoch() QCOMPARE(dtUtc.date(), utc.date()); QCOMPARE(dtUtc.time(), utc.time()); - QCOMPARE(dtOffset, utc); - QCOMPARE(dtOffset.offsetFromUtc(), 60*60); - if (msecs != Bound::max()) // Offset is positive, so overflows max + if (msecs == Bound::max()) { // Offset is positive, so overflows max + QVERIFY(!dtOffset.isValid()); + } else { + QCOMPARE(dtOffset, utc); + QCOMPARE(dtOffset.offsetFromUtc(), 60*60); QCOMPARE(dtOffset.time(), utc.time().addMSecs(60*60*1000)); + } if (zoneIsCET) { QCOMPARE(dtLocal.toLocalTime(), cet); QCOMPARE(dtUtc.toLocalTime(), cet); - QCOMPARE(dtOffset.toLocalTime(), cet); + if (msecs != Bound::max()) + QCOMPARE(dtOffset.toLocalTime(), cet); } if (!localOverflow) QCOMPARE(dtLocal.toMSecsSinceEpoch(), msecs); QCOMPARE(dtUtc.toMSecsSinceEpoch(), msecs); - QCOMPARE(dtOffset.toMSecsSinceEpoch(), msecs); + if (msecs != Bound::max()) + QCOMPARE(dtOffset.toMSecsSinceEpoch(), msecs); if (!localOverflow) QCOMPARE(qint64(dtLocal.toSecsSinceEpoch()), msecs / 1000); QCOMPARE(qint64(dtUtc.toSecsSinceEpoch()), msecs / 1000); - QCOMPARE(qint64(dtOffset.toSecsSinceEpoch()), msecs / 1000); + if (msecs != Bound::max()) + QCOMPARE(qint64(dtOffset.toSecsSinceEpoch()), msecs / 1000); QDateTime reference(QDate(1970, 1, 1), QTime(0, 0), Qt::UTC); if (!localOverflow) QCOMPARE(dtLocal, reference.addMSecs(msecs)); QCOMPARE(dtUtc, reference.addMSecs(msecs)); - QCOMPARE(dtOffset, reference.addMSecs(msecs)); + if (msecs != Bound::max()) + QCOMPARE(dtOffset, reference.addMSecs(msecs)); } void tst_QDateTime::fromSecsSinceEpoch() @@ -815,10 +834,10 @@ void tst_QDateTime::fromSecsSinceEpoch() QVERIFY(!QDateTime::fromSecsSinceEpoch(first - 1).isValid()); // Use an offset for which .toUTC()'s return would flip the validity: - QVERIFY(QDateTime::fromSecsSinceEpoch(maxSeconds, Qt::OffsetFromUTC, 7200).isValid()); - QVERIFY(!QDateTime::fromSecsSinceEpoch(maxSeconds + 1, Qt::OffsetFromUTC, -7200).isValid()); - QVERIFY(QDateTime::fromSecsSinceEpoch(-maxSeconds, Qt::OffsetFromUTC, -7200).isValid()); - QVERIFY(!QDateTime::fromSecsSinceEpoch(-maxSeconds - 1, Qt::OffsetFromUTC, 7200).isValid()); + QVERIFY(QDateTime::fromSecsSinceEpoch(maxSeconds - 7200, Qt::OffsetFromUTC, 7200).isValid()); + QVERIFY(!QDateTime::fromSecsSinceEpoch(maxSeconds - 7199, Qt::OffsetFromUTC, 7200).isValid()); + QVERIFY(QDateTime::fromSecsSinceEpoch(7200 - maxSeconds, Qt::OffsetFromUTC, -7200).isValid()); + QVERIFY(!QDateTime::fromSecsSinceEpoch(7199 - maxSeconds, Qt::OffsetFromUTC, -7200).isValid()); #if QT_CONFIG(timezone) // As for offset, use zones each side of UTC: |