aboutsummaryrefslogtreecommitdiffstats
path: root/src/helperfuncs.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2026-06-10 09:55:54 +0100
committerGravatar Sadie Powell2026-06-10 11:07:51 +0100
commit9533f488fdc166637cd271f54d1b56b3dc850ec5 (patch)
tree4eaf32b063309745fe872a1dfc6bfb030d2d6d8a /src/helperfuncs.cpp
parentFix storing configuration tags in the wrong container type. (diff)
Switch Time::ToString to use re-entrant time functions.
This is safer and has a cleaner failure path (if the functions fail the struct remains zero initialised). I have also removed some legacy checks that aren't needed now we use strftime not asctime.
Diffstat (limited to 'src/helperfuncs.cpp')
-rw-r--r--src/helperfuncs.cpp42
1 files changed, 22 insertions, 20 deletions
diff --git a/src/helperfuncs.cpp b/src/helperfuncs.cpp
index 01d49cc41..0f113e9f5 100644
--- a/src/helperfuncs.cpp
+++ b/src/helperfuncs.cpp
@@ -491,32 +491,34 @@ std::string Duration::ToLongString(unsigned long duration, bool brief)
std::string Time::ToString(time_t curtime, const char* format, bool utc)
{
-#ifdef _WIN32
- if (curtime < 0)
- curtime = 0;
-#endif
+ if (!format)
+ format = Time::DEFAULT_SHORT;
- struct tm* timeinfo = utc ? gmtime(&curtime) : localtime(&curtime);
- if (!timeinfo)
+ tm time_info{};
+ if (utc ? !gmtime_r(&curtime, &time_info) : !localtime_r(&curtime, &time_info)) [[unlikely]]
{
+ // If we've reached this point then either the time_t represents a year
+ // that can't be represented by tm_year (i.e. the year 2038 problem on
+ // 32-bit systems) or we are running on Windows which clamps the valid
+ // years on 64-bit systems to 1970-3000. There's not a lot we can do to
+ // give a correct timestamp here so we just return the UNIX epoch as
+ // that should never fail.
curtime = 0;
- timeinfo = localtime(&curtime);
+ if (utc)
+ gmtime_r(&curtime, &time_info);
+ else
+ localtime_r(&curtime, &time_info);
}
- // If the calculated year exceeds four digits or is less than the year 1000,
- // the behavior of asctime() is undefined
- if (timeinfo->tm_year + 1900 > 9999)
- timeinfo->tm_year = 9999 - 1900;
- else if (timeinfo->tm_year + 1900 < 1000)
- timeinfo->tm_year = 0;
-
- // This is the default format used by asctime without the terminating new line.
- if (!format)
- format = Time::DEFAULT_SHORT;
-
- char buffer[512];
- if (!strftime(buffer, sizeof(buffer), format, timeinfo))
+ static char buffer[512];
+ if (!strftime(buffer, sizeof(buffer), format, &time_info)) [[unlikely]]
+ {
+ // If we've reached this point then the buffer is not big enough to
+ // contain the formatted date. This probably will never happen because
+ // we give it a large buffer but in the cases it does happen we null
+ // terminate the buffer so the returned string is empty.
buffer[0] = '\0';
+ }
return buffer;
}