Fix crash on serializing default-constructed QTimeZone

The serialization code neglected to check against null.  Sinze zones
are saved either by IANA ID or in our special OffsetFromUtc format,
representing an invalid zone by a string that cannot possibly be a
valid IANA ID will do.

Fixes: QTBUG-86019
Change-Id: I6882026403d00f8b254aab34c645f1cf8f9fcc2d
Reviewed-by: Taylor Braun-Jones <taylor@braun-jones.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 14f3f419b0864944d75283a850dc0ce141feaf0e)
This commit is contained in:
Edward Welbourne 2020-08-13 10:40:11 +02:00
parent 5cbebeda54
commit f919d9a2da
2 changed files with 40 additions and 3 deletions

View File

@ -1,5 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2013 John Layt <jlayt@kde.org>
** Contact: https://www.qt.io/licensing/
**
@ -953,9 +954,15 @@ QList<QByteArray> QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId,
}
#ifndef QT_NO_DATASTREAM
// Invalid, as an IANA ID: too long, starts with - and has other invalid characters in it
static inline QString invalidId() { return QStringLiteral("-No Time Zone Specified!"); }
QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz)
{
tz.d->serialize(ds);
if (tz.isValid())
tz.d->serialize(ds);
else
ds << invalidId();
return ds;
}
@ -963,7 +970,9 @@ QDataStream &operator>>(QDataStream &ds, QTimeZone &tz)
{
QString ianaId;
ds >> ianaId;
if (ianaId == QLatin1String("OffsetFromUtc")) {
if (ianaId == invalidId()) {
tz = QTimeZone();
} else if (ianaId == QLatin1String("OffsetFromUtc")) {
int utcOffset;
QString name;
QString abbreviation;

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@ -59,6 +59,7 @@ private slots:
void windowsId();
void isValidId_data();
void isValidId();
void serialize();
// Backend tests
void utcTest();
void icuTest();
@ -782,6 +783,33 @@ void tst_QTimeZone::isValidId()
#endif
}
void tst_QTimeZone::serialize()
{
int parts = 0;
#ifndef QT_NO_DEBUG_STREAM
qDebug() << QTimeZone(); // to verify no crash
parts++;
#endif
#ifndef QT_NO_DATASTREAM
QByteArray blob;
{
QDataStream stream(&blob, QIODevice::WriteOnly);
stream << QTimeZone("Europe/Oslo") << QTimeZone(420) << QTimeZone() << qint64(-1);
}
QDataStream stream(&blob, QIODevice::ReadOnly);
QTimeZone invalid, offset, oslo;
qint64 minusone;
stream >> oslo >> offset >> invalid >> minusone;
QCOMPARE(oslo, QTimeZone("Europe/Oslo"));
QCOMPARE(offset, QTimeZone(420));
QVERIFY(!invalid.isValid());
QCOMPARE(minusone, qint64(-1));
parts++;
#endif
if (!parts)
QSKIP("No serialization enabled");
}
void tst_QTimeZone::utcTest()
{
#ifdef QT_BUILD_INTERNAL