summaryrefslogtreecommitdiffstats
path: root/src/corelib/time
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2022-01-04 16:55:03 +0100
committerMarc Mutz <marc.mutz@qt.io>2022-01-05 20:29:42 +0000
commit23aa51991dee2864d7f1d1acee953fd5c7b409fe (patch)
treeebcc2e5e6ac2ad2c5ede75556b7c5c3e01aa855b /src/corelib/time
parent2dea20e4b075f2367a069793ece2327eff5ac4bd (diff)
QTzTimeZonePrivate: fix permanently-detaching m_icu
The m_icu member is a mutable QSharedDataPointer, which means that only the non-const API subset is accessible, and so any access to it will always detach, in 5.15 even a check like if (m_icu), which the code luckily doesn't use (Qt 6 added a operator bool() const). We don't need detaching behavior here, though, since, once set, m_icu is never changed. So just use a QExplicitlySharedDataPointer instead, and never call detach() (which would do the wrong thing). Just in case someone does add a detach() later, instantiate QExplicitlySharedDataPointer over QIcuTimeZonePrivate directly. This requires making displayName() overloads from QTimeZonePrivate visible in QIcuTimeZonePrivate. Add an assertion that QIcuTimeZonePrivate is final, with instructions on what to do if it fails. Finally, hold a pointer-to-const to avoid race conditions in the pointee. The code still contains a data race, due to the lazy initialization of m_icu, but now we have at least a fighting change to fix it. Pick-to: 6.3 6.2 5.15 Change-Id: I32c343822dac43f96d9fbc4c759fa44138861eae Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/time')
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h8
1 files changed, 7 insertions, 1 deletions
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index 129f0343b3..b37d9995e3 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -243,6 +243,7 @@ public:
QIcuTimeZonePrivate *clone() const override;
+ using QTimeZonePrivate::displayName;
QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
const QLocale &locale) const override;
QString abbreviation(qint64 atMSecsSinceEpoch) const override;
@@ -353,7 +354,12 @@ private:
Data dataForTzTransition(QTzTransitionTime tran) const;
Data dataFromRule(QTzTransitionRule rule, qint64 msecsSinceEpoch) const;
#if QT_CONFIG(icu)
- mutable QSharedDataPointer<QTimeZonePrivate> m_icu;
+# ifdef __cpp_lib_is_final
+ static_assert(std::is_final<QIcuTimeZonePrivate>::value,
+ "if QIcuTimeZonePrivate isn't final, we may need to specialize "
+ "QExplicitlySharedDataPointer::clone() to call QTimeZonePrivate::clone()");
+# endif
+ mutable QExplicitlySharedDataPointer<const QIcuTimeZonePrivate> m_icu;
#endif
QTzTimeZoneCacheEntry cached_data;
QList<QTzTransitionTime> tranCache() const { return cached_data.m_tranTimes; }