From c7b23f4a1aec49b445bf88196d7206c93b1a8759 Mon Sep 17 00:00:00 2001 From: crueter Date: Sun, 8 Mar 2026 20:53:37 +0100 Subject: [PATCH] [time] fix: guard timezone out buffer logging (#3668) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original text, per the emailed patch: --------------- Hello, I am submitting a small fix to prevent an unintended abort when _GLIBCXX_ASSERTIONS is enabled, caused by out-of-bounds access in debug logging. Background / Issue In the server-side implementations of ITimeZoneService::ToPosixTime and ToPosixTimeWithMyRule, the SCOPE_EXIT debug logging previously accessed out_times[0] and out_times[1] unconditionally. However, out_times is an IPC-provided output buffer (OutArray, which inherits from std::span). Its length depends on the caller-provided buffer capacity. During debugging, I encountered a case where out_times.size() == 1. Under _GLIBCXX_ASSERTIONS, accessing out_times[1] triggers a std::span::operator[] assertion failure (std::__glibcxx_assert_fail) and aborts the process, causing the service thread to crash. This results in an unintended crash caused solely by debug logging. Change Description In the SCOPE_EXIT logging blocks of both ToPosixTime and ToPosixTimeWithMyRule, I added bounds checks before accessing out_times[0] and out_times[1]: Access out_times[0] only if out_times.size() > 0 Access out_times[1] only if out_times.size() > 1 Print 0 when the corresponding element is unavailable This change only affects debug log output. It does not modify IPC semantics or the time conversion logic itself. Reproduction Context (for reference) I encountered this issue while running 13 Sentinels: Aegis Rim (title ID: 01008D7016438000). During the “Load Game” flow, ToPosixTimeWithMyRule is invoked with an out_times buffer of length 1, which previously led to the out-of-bounds access in the logging code. Thank you for your time and review. Best regards, darkpaper Environment: Arch Linux / KDE / X11 This email and the accompanying patch were prepared with assistance from an LLM. Authored-by: darkpaper Signed-off-by: crueter Co-authored-by: darkpaper Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3668 --- src/core/hle/service/glue/time/time_zone.cpp | 12 +++++++++--- src/core/hle/service/psc/time/time_zone_service.cpp | 9 +++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp index b2e8159653..c358cfbf28 100644 --- a/src/core/hle/service/glue/time/time_zone.cpp +++ b/src/core/hle/service/glue/time/time_zone.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -104,7 +107,8 @@ Result TimeZoneService::LoadLocationNameList( OutArray out_names, u32 index) { SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. index={} out_count={} out_names[0]={} out_names[1]={}", - index, *out_count, out_names[0], out_names[1]); + index, *out_count, out_names.size() > 0 ? out_names[0] : Service::PSC::Time::LocationName{}, + out_names.size() > 1 ? out_names[1] : Service::PSC::Time::LocationName{}); }; std::scoped_lock l{m_mutex}; @@ -208,7 +212,8 @@ Result TimeZoneService::ToPosixTime(Out out_count, SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}", - calendar_time, *out_count, out_times[0], out_times[1]); + calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0}, + out_times.size() > 1 ? out_times[1] : s64{0}); }; R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule)); @@ -220,7 +225,8 @@ Result TimeZoneService::ToPosixTimeWithMyRule( SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}", - calendar_time, *out_count, out_times[0], out_times[1]); + calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0}, + out_times.size() > 1 ? out_times[1] : s64{0}); }; R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time)); diff --git a/src/core/hle/service/psc/time/time_zone_service.cpp b/src/core/hle/service/psc/time/time_zone_service.cpp index 9e0674f275..d49c0056ec 100644 --- a/src/core/hle/service/psc/time/time_zone_service.cpp +++ b/src/core/hle/service/psc/time/time_zone_service.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -148,7 +151,8 @@ Result TimeZoneService::ToPosixTime(Out out_count, SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ", - calendar_time, *out_count, out_times[0], out_times[1]); + calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0}, + out_times.size() > 1 ? out_times[1] : s64{0}); }; R_RETURN( @@ -161,7 +165,8 @@ Result TimeZoneService::ToPosixTimeWithMyRule(Out out_count, SCOPE_EXIT { LOG_DEBUG(Service_Time, "called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ", - calendar_time, *out_count, out_times[0], out_times[1]); + calendar_time, *out_count, out_times.size() > 0 ? out_times[0] : s64{0}, + out_times.size() > 1 ? out_times[1] : s64{0}); }; R_RETURN(