From eab07866a3301bdd1c1def0ae891df1d4488c611 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 12 Jul 2020 12:36:58 -0500 Subject: [PATCH] Common/Timer: Fix integer underflow in Timer::GetDoubleTime for dates before ~2008. --- Source/Core/Common/Timer.cpp | 40 +++++++++--------------------------- Source/Core/Common/Timer.h | 2 +- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/Source/Core/Common/Timer.cpp b/Source/Core/Common/Timer.cpp index 794f2dfd49..3e953f24b4 100644 --- a/Source/Core/Common/Timer.cpp +++ b/Source/Core/Common/Timer.cpp @@ -4,7 +4,7 @@ #include "Common/Timer.h" -#include +#include #include #ifdef _WIN32 @@ -233,37 +233,17 @@ std::string Timer::GetTimeFormatted() // Returns a timestamp with decimals for precise time comparisons double Timer::GetDoubleTime() { -#ifdef _WIN32 - struct timeb tp; - (void)::ftime(&tp); -#elif defined __APPLE__ - struct timeval t; - (void)gettimeofday(&t, nullptr); -#else - struct timespec t; - (void)clock_gettime(CLOCK_MONOTONIC, &t); -#endif - // Get continuous timestamp - u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970(); + // FYI: std::chrono::system_clock epoch is not required to be 1970 until c++20. + // We will however assume time_t IS unix time. + using Clock = std::chrono::system_clock; - // Remove a few years. We only really want enough seconds to make - // sure that we are detecting actual actions, perhaps 60 seconds is - // enough really, but I leave a year of seconds anyway, in case the - // user's clock is incorrect or something like that. - TmpSeconds = TmpSeconds - DOUBLE_TIME_OFFSET; + // TODO: Use this on switch to c++20: + // const auto since_epoch = Clock::now().time_since_epoch(); + const auto unix_epoch = Clock::from_time_t({}); + const auto since_epoch = Clock::now() - unix_epoch; - // Make a smaller integer that fits in the double - u32 Seconds = (u32)TmpSeconds; -#ifdef _WIN32 - double ms = tp.millitm / 1000.0 / 1000.0; -#elif defined __APPLE__ - double ms = t.tv_usec / 1000000.0; -#else - double ms = t.tv_nsec / 1000000000.0; -#endif - double TmpTime = Seconds + ms; - - return TmpTime; + const auto since_double_time_epoch = since_epoch - std::chrono::seconds(DOUBLE_TIME_OFFSET); + return std::chrono::duration_cast>(since_double_time_epoch).count(); } // Formats a timestamp from GetDoubleTime() into a date and time string diff --git a/Source/Core/Common/Timer.h b/Source/Core/Common/Timer.h index aa82ebf6b0..021f94a736 100644 --- a/Source/Core/Common/Timer.h +++ b/Source/Core/Common/Timer.h @@ -41,7 +41,7 @@ public: // Arbitrarily chosen value (38 years) that is subtracted in GetDoubleTime() // to increase sub-second precision of the resulting double timestamp - static const int DOUBLE_TIME_OFFSET = (38 * 365 * 24 * 60 * 60); + static constexpr int DOUBLE_TIME_OFFSET = (38 * 365 * 24 * 60 * 60); private: u64 m_LastTime;