diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2022-04-01 12:07:10 +0200 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2022-04-25 22:54:07 +0200 |
commit | 27e0ca05a022cf0e7406e8d4ea7ba7256be2c4a5 (patch) | |
tree | 3cd0d56a341d12801c707c6573acac322969823f /src/corelib/time/qdatetimeparser.cpp | |
parent | a2e5dcfbde7b3bf6db5da58cd578debf246dc3af (diff) |
Fix assertion failure when parsing a doubly-invalid date-time text
When the date-time string falls in a spring-forward (so is invalid)
and one of the fields of the parsed string doesn't match the format
it's meant to (e.g. a single-digit seconds field when format ss was
specified), a check that the current fall-back date-time is between
the minimum and maximum for the parser object failed, triggering an
assertion.
In any case, an invalid default-value wasn't useful to the code that
parsed a single section of the date-time string, so brute-force the
current value to a valid date-time (when possible) using the usual
round-trip via milliseconds since the epoch.
Added the test-case which first revealed the problem, plus a couple
more informed by it, to exercise the same code-paths with fewer things
failing. (For 5.15: converted u"..."_qs to QStringLiteral("...").)
Fixes: QTBUG-102199
Change-Id: I658308614505ef25f4c97d0de6148acb54a65a0f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 9fee35a2eda68b5968d911d5e14d298b91418d2c)
Reviewed-by: Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io>
Diffstat (limited to 'src/corelib/time/qdatetimeparser.cpp')
-rw-r--r-- | src/corelib/time/qdatetimeparser.cpp | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp index 5df4b373c4..5f8267c2b9 100644 --- a/src/corelib/time/qdatetimeparser.cpp +++ b/src/corelib/time/qdatetimeparser.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -761,6 +761,11 @@ QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex, const int sectionmaxsize = sectionMaxSize(sectionIndex); QStringRef sectionTextRef = text->midRef(offset, sectionmaxsize); + // If the fields we've read thus far imply a time in a spring-forward, + // coerce to a nearby valid time: + const QDateTime defaultValue = currentValue.isValid() ? currentValue + : QDateTime::fromMSecsSinceEpoch(currentValue.toMSecsSinceEpoch()); + QDTPDEBUG << "sectionValue for" << sn.name() << "with text" << *text << "and (at" << offset << ") st:" << sectionTextRef; @@ -793,7 +798,7 @@ QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex, text->replace(offset, used, sectiontext.constData(), used); break; } case TimeZoneSection: - result = findTimeZone(sectionTextRef, currentValue, + result = findTimeZone(sectionTextRef, defaultValue, absoluteMax(sectionIndex), absoluteMin(sectionIndex)); break; @@ -805,7 +810,7 @@ QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex, int num = 0, used = 0; if (sn.type == MonthSection) { const QDate minDate = getMinimum().date(); - const int year = currentValue.date().year(calendar); + const int year = defaultValue.date().year(calendar); const int min = (year == minDate.year(calendar)) ? minDate.month(calendar) : 1; num = findMonth(sectiontext.toLower(), min, sectionIndex, year, §iontext, &used); } else { @@ -887,7 +892,7 @@ QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex, else QDTPDEBUG << "invalid because" << last << "is less than absoluteMin" << absMin; } else if (unfilled && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) { - if (skipToNextSection(sectionIndex, currentValue, digitsStr)) { + if (skipToNextSection(sectionIndex, defaultValue, digitsStr)) { const int missingZeroes = sectionmaxsize - digitsStr.size(); result = ParsedSection(Acceptable, last, sectionmaxsize, missingZeroes); text->insert(offset, QString(missingZeroes, QLatin1Char('0'))); |