From 147aa291620d9e2533bbea536a748a8f8a7ed14b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 5 May 2017 16:57:56 +0100 Subject: Fix sending UTC-offset QTimeZones through QDataStream QTimeZone("UTC") should be valid, as "UTC" appears in the list of availableTimeZoneIds(), and tst_QTimeZone::dataStreamTest() constructs timezones like this, which are considered valid. The internal representation of a QTimeZone("UTC") as created by QTimeZone::QTimeZone(const QByteArray &ianaId) is a QUtcTimeZonePrivate which isValid(), so the containing QTimeZone isValid() too. When QTimeZone is serialized into a QDataStream, it calls tz.d->serialize(ds) which is QUtcTimeZonePrivate::serialize. This writes QStringLiteral("OffsetFromUtc") followed by the IANA ID and the offset (etc.) to the datastream. When QTimeZone is deserialized it looks for this marker string, and if present, it passed all of the parameters to the QTimeZone constructor (not just the name). However, that constructor does not support standard IANA timezones (only custom ones), and when it detects that the supplied IANA ID is actually listed in availableTimeZoneIds(), it leaves the pointer to the QTimeZonePrivate uninitialized (NULL), which leaves the QTimeZone invalid (isValid() returns false). Thus, a valid timezone which was serialized and then deserialized has become invalid. This also affects serialization of QDateTimes with timezones. Fixed by calling the name-only constructor first, which works (only) for IANA standard timezones and leaves the QTimeZone invalid (isValid() returns false) otherwise. In which case, we can call the many-argument contructor to create a custom timezone with the same offset as the one which was originally serialized. [ChangeLog][QtCore][QTimeZone] Fixed sending IANA standard UTC-offset QTimeZones through QDataStream, which previously came out invalid after deserialization. Task-number: QTBUG-60595 Change-Id: Id9c47e8bda701faae4d800e012afb6db545b2fe9 Reviewed-by: Oswald Buddenhagen Reviewed-by: Edward Welbourne --- tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp') diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp index c1f2822b74..e75ed5cc67 100644 --- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp @@ -299,7 +299,7 @@ void tst_QTimeZone::nullTest() void tst_QTimeZone::dataStreamTest() { - // Test the OffsetFromUtc backend serialization + // Test the OffsetFromUtc backend serialization. First with a custom timezone: QTimeZone tz1("QST", 123456, "Qt Standard Time", "QST", QLocale::Norway, "Qt Testing"); QByteArray tmp; { @@ -321,6 +321,20 @@ void tst_QTimeZone::dataStreamTest() QString("Qt Standard Time")); QCOMPARE(tz2.offsetFromUtc(QDateTime::currentDateTime()), 123456); + // And then with a standard IANA timezone (QTBUG-60595): + tz1 = QTimeZone("UTC"); + QCOMPARE(tz1.isValid(), true); + { + QDataStream ds(&tmp, QIODevice::WriteOnly); + ds << tz1; + } + { + QDataStream ds(&tmp, QIODevice::ReadOnly); + ds >> tz2; + } + QCOMPARE(tz2.isValid(), true); + QCOMPARE(tz2.id(), tz1.id()); + // Test the system backend serialization tz1 = QTimeZone("Pacific/Auckland"); -- cgit v1.2.3