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
Pick-to: 5.15
Pick-to: 5.12
Change-Id: I6882026403d00f8b254aab34c645f1cf8f9fcc2d
Reviewed-by: Taylor Braun-Jones <taylor@braun-jones.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Edward Welbourne 2020-08-13 10:40:11 +02:00
parent 33031020e1
commit 14f3f419b0
2 changed files with 39 additions and 3 deletions

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2013 John Layt <jlayt@kde.org>
** Copyright (C) 2020 John Layt <jlayt@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@ -966,9 +966,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;
}
@ -976,7 +982,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

@ -62,6 +62,7 @@ private Q_SLOTS:
void windowsId();
void isValidId_data();
void isValidId();
void serialize();
// Backend tests
void utcTest();
void icuTest();
@ -935,6 +936,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