Adapt ASN.1 datetime parsing to use the new century control

It previously had to kludge a 1900-to-1999 date into a 1950-to-2049
range; it can now tell QDTP to do that for it. In particular, this
fixes a problem with 00-02-29, which failed to parse using 1900 as
base year so couldn't be corrected to 2000-02-29, which is now the
date it finds directly.

Task-number: QTBUG-46843
Change-Id: I7ac936bdfb15b78daed5d237c5d921c800af4951
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Edward Welbourne 2023-11-09 17:25:01 +01:00
parent 41f84f3ddb
commit 9bf7d2a76a
2 changed files with 9 additions and 15 deletions

View File

@ -225,31 +225,28 @@ QDateTime QAsn1Element::toDateTime() const
return result; return result;
if (mType == UtcTimeType && mValue.size() == 13) { if (mType == UtcTimeType && mValue.size() == 13) {
const QLatin1StringView inputView(mValue);
QDate date = QDate::fromString(inputView.first(6), u"yyMMdd");
if (!date.isValid())
return result;
// RFC 2459: // RFC 2459:
// Where YY is greater than or equal to 50, the year shall be // Where YY is greater than or equal to 50, the year shall be
// interpreted as 19YY; and // interpreted as 19YY; and
// //
// Where YY is less than 50, the year shall be interpreted as 20YY. // Where YY is less than 50, the year shall be interpreted as 20YY.
// //
// QDateTime interprets the 'yy' format as 19yy, so we may need to adjust // so use 1950 as base year.
// the year (bring it in the [1950, 2049] range). constexpr int rfc2459CenturyStart = 1950;
if (date.year() < 1950) const QLatin1StringView inputView(mValue);
date = date.addYears(100); QDate date = QDate::fromString(inputView.first(6), u"yyMMdd", rfc2459CenturyStart);
if (!date.isValid())
return result;
Q_ASSERT(date.year() >= 1950); Q_ASSERT(date.year() >= rfc2459CenturyStart);
Q_ASSERT(date.year() <= 2049); Q_ASSERT(date.year() < 100 + rfc2459CenturyStart);
QTime time = QTime::fromString(inputView.sliced(6, 6), u"HHmmss"); QTime time = QTime::fromString(inputView.sliced(6, 6), u"HHmmss");
if (!time.isValid()) if (!time.isValid())
return result; return result;
result = QDateTime(date, time, QTimeZone::UTC); result = QDateTime(date, time, QTimeZone::UTC);
} else if (mType == GeneralizedTimeType && mValue.size() == 15) { } else if (mType == GeneralizedTimeType && mValue.size() == 15) {
result = QDateTime::fromString(QString::fromLatin1(mValue), result = QDateTime::fromString(QString::fromLatin1(mValue), u"yyyyMMddHHmmsst");
u"yyyyMMddHHmmsst");
} }
return result; return result;

View File

@ -166,9 +166,6 @@ void tst_QAsn1Element::dateTime()
QAsn1Element elem; QAsn1Element elem;
QVERIFY(elem.read(encoded)); QVERIFY(elem.read(encoded));
QEXPECT_FAIL("UTCTime - leap day year 2000",
"We decode as 1900, and then adjust to 2000. But there was no leap day in 1900!",
Continue);
QCOMPARE(elem.toDateTime(), value); QCOMPARE(elem.toDateTime(), value);
} }