summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qtenvironmentvariables.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/global/qtenvironmentvariables.cpp')
-rw-r--r--src/corelib/global/qtenvironmentvariables.cpp34
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