Index: libcxx/src/chrono.cpp =================================================================== --- libcxx/src/chrono.cpp +++ libcxx/src/chrono.cpp @@ -185,23 +185,36 @@ // If the function fails, the return value is zero. // On systems that run Windows XP or later, the function will always succeed // and will thus never return zero. +// The same comment is made for QueryPerformanceCounter at +// https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter static LARGE_INTEGER __QueryPerformanceFrequency() { - LARGE_INTEGER val; - (void) QueryPerformanceFrequency(&val); - return val; + LARGE_INTEGER val; + (void) QueryPerformanceFrequency(&val); + return val; +} + +static LARGE_INTEGER +__QueryPerformanceCounter() +{ + LARGE_INTEGER val; + (void) QueryPerformanceCounter(&val); + return val; } steady_clock::time_point steady_clock::now() _NOEXCEPT { - static const LARGE_INTEGER freq = __QueryPerformanceFrequency(); + static const LARGE_INTEGER freq = __QueryPerformanceFrequency(); + const LARGE_INTEGER counter = __QueryPerformanceCounter(); + +// Do the multiplication in two parts to prevent overflow (See PR#43703) + const LONGLONG part1 = (counter.QuadPart / freq.QuadPart) * nano::den; + const LONGLONG part2 = (counter.QuadPart % freq.QuadPart) * nano::den / freq.QuadPart; - LARGE_INTEGER counter; - (void) QueryPerformanceCounter(&counter); - return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart)); + return time_point(duration(part1 + part2)); } #elif defined(CLOCK_MONOTONIC)