From 92f0f99c23f981a551fde0d0242d414fac4dacbd Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 13 Jun 2018 19:12:15 +0200 Subject: [PATCH] Check validity before adding to a QDateTime QDateTime's addDays(), addMonths() and addYears() neglected to check for validity before doing their job, with the result that they could produce "valid" (but wildly inappropriate) results if used on an invalid date-time. Added tests for this case (and the boundary). Change-Id: I7b0d638501cb5d875a678cde213547a83ed7529e Reviewed-by: Andrei Golubev Reviewed-by: Thiago Macieira --- src/corelib/time/qdatetime.cpp | 9 ++++ .../corelib/time/qdatetime/tst_qdatetime.cpp | 46 ++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 0be4f290be7..98b5dc82125 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -4154,6 +4154,9 @@ static inline void massageAdjustedDateTime(QDateTimeData &d, QDate date, QTime t QDateTime QDateTime::addDays(qint64 ndays) const { + if (isNull()) + return QDateTime(); + QDateTime dt(*this); QPair p = getDateTime(d); massageAdjustedDateTime(dt.d, p.first.addDays(ndays), p.second); @@ -4176,6 +4179,9 @@ QDateTime QDateTime::addDays(qint64 ndays) const QDateTime QDateTime::addMonths(int nmonths) const { + if (isNull()) + return QDateTime(); + QDateTime dt(*this); QPair p = getDateTime(d); massageAdjustedDateTime(dt.d, p.first.addMonths(nmonths), p.second); @@ -4198,6 +4204,9 @@ QDateTime QDateTime::addMonths(int nmonths) const QDateTime QDateTime::addYears(int nyears) const { + if (isNull()) + return QDateTime(); + QDateTime dt(*this); QPair p = getDateTime(d); massageAdjustedDateTime(dt.d, p.first.addYears(nyears), p.second); diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index 9d80583e725..13176e5afc5 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -83,6 +83,7 @@ private Q_SLOTS: void toString_strformat(); #endif void addDays(); + void addInvalid(); void addMonths(); void addMonths_data(); void addYears(); @@ -1095,10 +1096,51 @@ void tst_QDateTime::addDays() dt1 = QDateTime(QDate(1970, 1, 1), QTime(23, 59, 59)); dt2 = dt1.addDays(-1); QVERIFY(dt2.isValid()); - - // ### test invalid QDateTime() } +void tst_QDateTime::addInvalid() +{ + QDateTime bad; + QVERIFY(!bad.isValid()); + QVERIFY(bad.isNull()); + + QDateTime offset = bad.addDays(2); + QVERIFY(offset.isNull()); + offset = bad.addMonths(-1); + QVERIFY(offset.isNull()); + offset = bad.addYears(23); + QVERIFY(offset.isNull()); + offset = bad.addSecs(73); + QVERIFY(offset.isNull()); + offset = bad.addMSecs(73); + QVERIFY(offset.isNull()); + + QDateTime bound = QDateTime::fromMSecsSinceEpoch(std::numeric_limits::min(), Qt::UTC); + QVERIFY(bound.isValid()); + offset = bound.addMSecs(-1); + QVERIFY(!offset.isValid()); + offset = bound.addSecs(-1); + QVERIFY(!offset.isValid()); + offset = bound.addDays(-1); + QVERIFY(!offset.isValid()); + offset = bound.addMonths(-1); + QVERIFY(!offset.isValid()); + offset = bound.addYears(-1); + QVERIFY(!offset.isValid()); + + bound.setMSecsSinceEpoch(std::numeric_limits::max()); + QVERIFY(bound.isValid()); + offset = bound.addMSecs(1); + QVERIFY(!offset.isValid()); + offset = bound.addSecs(1); + QVERIFY(!offset.isValid()); + offset = bound.addDays(1); + QVERIFY(!offset.isValid()); + offset = bound.addMonths(1); + QVERIFY(!offset.isValid()); + offset = bound.addYears(1); + QVERIFY(!offset.isValid()); +} void tst_QDateTime::addMonths_data() {