From 52410813f22def236c7ce28390fbd18cb0b582d4 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Feb 2024 04:40:25 +0100 Subject: [PATCH 1/2] Common: Add utility function that wraps localtime_s() or localtime_t(). --- Source/Core/Common/CMakeLists.txt | 2 ++ Source/Core/Common/TimeUtil.cpp | 24 ++++++++++++++++++++++++ Source/Core/Common/TimeUtil.h | 13 +++++++++++++ Source/Core/DolphinLib.props | 2 ++ 4 files changed, 41 insertions(+) create mode 100644 Source/Core/Common/TimeUtil.cpp create mode 100644 Source/Core/Common/TimeUtil.h diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 61bc9155da..1431239af2 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -138,6 +138,8 @@ add_library(common Thread.h Timer.cpp Timer.h + TimeUtil.cpp + TimeUtil.h TraversalClient.cpp TraversalClient.h TraversalProto.h diff --git a/Source/Core/Common/TimeUtil.cpp b/Source/Core/Common/TimeUtil.cpp new file mode 100644 index 0000000000..39d989fb3f --- /dev/null +++ b/Source/Core/Common/TimeUtil.cpp @@ -0,0 +1,24 @@ +// Copyright 2024 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "Common/TimeUtil.h" + +#include +#include + +namespace Common +{ +std::optional Localtime(std::time_t time) +{ + std::tm local_time; +#ifdef _MSC_VER + if (localtime_s(&local_time, &time) != 0) + return std::nullopt; +#else + std::tm* result = localtime_r(&time, &local_time); + if (result != &local_time) + return std::nullopt; +#endif + return local_time; +} +} // Namespace Common diff --git a/Source/Core/Common/TimeUtil.h b/Source/Core/Common/TimeUtil.h new file mode 100644 index 0000000000..ff9ca02a12 --- /dev/null +++ b/Source/Core/Common/TimeUtil.h @@ -0,0 +1,13 @@ +// Copyright 2024 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +namespace Common +{ +// Threadsafe and error-checking variant of std::localtime() +std::optional Localtime(std::time_t time); +} // Namespace Common diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index 74b3185753..42ae7ba5e6 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -161,6 +161,7 @@ + @@ -832,6 +833,7 @@ + From d3140e72c3f59f203c6c85049c5bcd25f9b14f3b Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 18 Feb 2024 04:45:37 +0100 Subject: [PATCH 2/2] Core: Fix crash when inspecting a savestate with a timestamp that causes localtime() to error out. --- Source/Core/Core/State.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index e3e9a441c2..d60747deeb 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -29,6 +29,7 @@ #include "Common/IOFile.h" #include "Common/MsgHandler.h" #include "Common/Thread.h" +#include "Common/TimeUtil.h" #include "Common/Timer.h" #include "Common/Version.h" #include "Common/WorkQueueThread.h" @@ -282,10 +283,12 @@ static std::string SystemTimeAsDoubleToString(double time) { // revert adjustments from GetSystemTimeAsDouble() to get a normal Unix timestamp again const time_t seconds = static_cast(time) + DOUBLE_TIME_OFFSET; - const tm local_time = fmt::localtime(seconds); + const auto local_time = Common::Localtime(seconds); + if (!local_time) + return ""; // fmt is locale agnostic by default, so explicitly use current locale. - return fmt::format(std::locale{""}, "{:%x %X}", local_time); + return fmt::format(std::locale{""}, "{:%x %X}", *local_time); } static std::string MakeStateFilename(int number);