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> ** Copyright (C) 2013 John Layt <jlayt@kde.org>
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
@ -953,9 +954,15 @@ QList<QByteArray> QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId,
} }
#ifndef QT_NO_DATASTREAM #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) QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz)
{ {
tz.d->serialize(ds); if (tz.isValid())
tz.d->serialize(ds);
else
ds << invalidId();
return ds; return ds;
} }
@ -963,7 +970,9 @@ QDataStream &operator>>(QDataStream &ds, QTimeZone &tz)
{ {
QString ianaId; QString ianaId;
ds >> ianaId; ds >> ianaId;
if (ianaId == QLatin1String("OffsetFromUtc")) { if (ianaId == invalidId()) {
tz = QTimeZone();
} else if (ianaId == QLatin1String("OffsetFromUtc")) {
int utcOffset; int utcOffset;
QString name; QString name;
QString abbreviation; 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/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the test suite of the Qt Toolkit. ** This file is part of the test suite of the Qt Toolkit.
@ -59,6 +59,7 @@ private slots:
void windowsId(); void windowsId();
void isValidId_data(); void isValidId_data();
void isValidId(); void isValidId();
void serialize();
// Backend tests // Backend tests
void utcTest(); void utcTest();
void icuTest(); void icuTest();
@ -782,6 +783,33 @@ void tst_QTimeZone::isValidId()
#endif #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() void tst_QTimeZone::utcTest()
{ {
#ifdef QT_BUILD_INTERNAL #ifdef QT_BUILD_INTERNAL