From b3ff1f3e6170ed5895b4e3c9de76d6132f8a2f96 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 12 Mar 2023 18:54:26 +0100 Subject: [PATCH] Fix data race in wxGetTimeZone() We could return a wrong value from this function if two threads called it simultaneously, as gmtoffset value could be returned without DST adjustment in one of them. And just accessing it from two different threads without synchronization was a data race on its own. Fix both problems by using an atomic int for it and taking care to only set it to the correct value. --- src/common/time.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/common/time.cpp b/src/common/time.cpp index 2ad2d9ad6d..c2f7f637fd 100644 --- a/src/common/time.cpp +++ b/src/common/time.cpp @@ -37,6 +37,10 @@ #endif #endif +#ifdef WX_GMTOFF_IN_TM + #include +#endif + #include wxDECL_FOR_STRICT_MINGW32(void, tzset, (void)); @@ -119,12 +123,10 @@ struct tm *wxGmtime_r(const time_t* ticks, struct tm* temp) int wxGetTimeZone() { #ifdef WX_GMTOFF_IN_TM - // set to true when the timezone is set - static bool s_timezoneSet = false; - static long gmtoffset = LONG_MAX; // invalid timezone + static std::atomic s_gmtoffset{INT_MAX}; // invalid timezone // ensure that the timezone variable is set by calling wxLocaltime_r - if ( !s_timezoneSet ) + if ( s_gmtoffset == INT_MAX ) { // just call wxLocaltime_r() instead of figuring out whether this // system supports tzset(), _tzset() or something else @@ -132,20 +134,21 @@ int wxGetTimeZone() struct tm tm; wxLocaltime_r(&t, &tm); - s_timezoneSet = true; // note that GMT offset is the opposite of time zone and so to return // consistent results in both WX_GMTOFF_IN_TM and !WX_GMTOFF_IN_TM // cases we have to negate it - gmtoffset = -tm.tm_gmtoff; + int gmtoffset = static_cast(-tm.tm_gmtoff); // this function is supposed to return the same value whether DST is // enabled or not, so we need to use an additional offset if DST is on // as tm_gmtoff already does include it if ( tm.tm_isdst ) gmtoffset += 3600; + + s_gmtoffset = gmtoffset; } - return (int)gmtoffset; + return s_gmtoffset; #elif defined(__WINE__) struct timeb tb; ftime(&tb);