fix(time): check properly for timestamp + nsec overflows in MakeTime and BreakTime

This commit is contained in:
phaneron 2023-07-30 14:24:50 -04:00
parent 4470aeabae
commit 0297a77a50

View file

@ -119,6 +119,8 @@ uint64_t Seconds() {
} }
Timestamp MakeTime(const TimeRec& date) { Timestamp MakeTime(const TimeRec& date) {
Timestamp timestamp = 0;
#if defined(WHOA_SYSTEM_WIN) #if defined(WHOA_SYSTEM_WIN)
// Win32 implementation // Win32 implementation
FILETIME fileTime = {}; FILETIME fileTime = {};
@ -138,14 +140,7 @@ Timestamp MakeTime(const TimeRec& date) {
ul.HighPart = fileTime.dwHighDateTime; ul.HighPart = fileTime.dwHighDateTime;
ul.LowPart = fileTime.dwLowDateTime; ul.LowPart = fileTime.dwLowDateTime;
auto timestamp = FromWinFiletime(ul.QuadPart); timestamp = FromWinFiletime(ul.QuadPart);
if (timestamp == std::numeric_limits<Timestamp>::min()
|| timestamp == std::numeric_limits<Timestamp>::max()) {
return timestamp;
}
timestamp += date.nsec;
return timestamp;
#endif #endif
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX) #if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
@ -161,23 +156,29 @@ Timestamp MakeTime(const TimeRec& date) {
// Convert date into UNIX timestamp // Convert date into UNIX timestamp
auto unixTime = ::timegm(&t); auto unixTime = ::timegm(&t);
auto timestamp = FromUnixTime(unixTime); timestamp = FromUnixTime(unixTime);
if (timestamp == std::numeric_limits< || timestamp == 2147483647L) { #endif
// Add nsec to result
auto nsec = date.nsec;
// overflow check
if ((timestamp + static_cast<Timestamp>(nsec)) < timestamp) {
return timestamp; return timestamp;
} }
timestamp += date.nsec; timestamp += nsec;
return timestamp; return timestamp;
#endif
} }
void BreakTime(Timestamp timestamp, TimeRec& date) { void BreakTime(Timestamp timestamp, TimeRec& date) {
auto nsec = timestamp % TimeConst::TimestampsPerSecond; auto mod = (timestamp % TimeConst::TimestampsPerSecond);
if (nsec < 0) { auto nsec = static_cast<uint32_t>(mod + TimeConst::TimestampsPerSecond);
nsec += TimeConst::TimestampsPerSecond;
if (mod < std::numeric_limits<uint32_t>::max()) {
nsec = mod;
} }
#if defined(WHOA_SYSTEM_WIN) #if defined(WHOA_SYSTEM_WIN)
// Win32 implementation // Win32 implementation
ULARGE_INTEGER ul = {}; ULARGE_INTEGER ul = {};