diff options
Diffstat (limited to 'src/corelib/global/qtenvironmentvariables.cpp')
-rw-r--r-- | src/corelib/global/qtenvironmentvariables.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/corelib/global/qtenvironmentvariables.cpp b/src/corelib/global/qtenvironmentvariables.cpp index 4f2a263cc4..cf5955902a 100644 --- a/src/corelib/global/qtenvironmentvariables.cpp +++ b/src/corelib/global/qtenvironmentvariables.cpp @@ -353,6 +353,10 @@ void qTzSet() time_t qMkTime(struct tm *when) { const auto locker = qt_scoped_lock(environmentMutex); +#if defined(Q_OS_WIN) + // QTBUG-83881 MS's mktime() seems to need _tzset() called first. + _tzset(); +#endif return mktime(when); } @@ -377,6 +381,7 @@ bool qLocalTime(time_t utc, struct tm *local) tzset(); if (tm *res = localtime_r(&utc, local)) { Q_ASSERT(res == local); + Q_UNUSED(res); return true; } return false; @@ -392,4 +397,33 @@ bool qLocalTime(time_t utc, struct tm *local) #endif } +/* Access to the tzname[] global in one thread is UB if any other is calling + tzset() or anything that behaves as if it called tzset(). So also lock this + access to prevent such collisions. + + Parameter dstIndex must be 1 for DST or 0 for standard time. + Returns the relevant form of the name of local-time's zone. +*/ +QString qTzName(int dstIndex) +{ + char name[512]; + bool ok; +#if defined(_UCRT) // i.e., MSVC and MinGW-UCRT + size_t s = 0; + { + const auto locker = qt_scoped_lock(environmentMutex); + ok = _get_tzname(&s, name, 512, dstIndex) != 0; + } +#else + { + const auto locker = qt_scoped_lock(environmentMutex); + const char *const src = tzname[dstIndex]; + ok = src != nullptr; + if (ok) + memcpy(name, src, std::min(sizeof(name), strlen(src) + 1)); + } +#endif // Q_OS_WIN + return ok ? QString::fromLocal8Bit(name) : QString(); +} + QT_END_NAMESPACE |