From 3536c1d0a9c80b558da40e8234ea519c61958317 Mon Sep 17 00:00:00 2001 From: Jeod <47716344+JeodC@users.noreply.github.com> Date: Sun, 2 Aug 2026 19:26:24 -0400 Subject: [PATCH] Fix two asan triggers --- src/port/Rando/Logic/GlitchlessLogic.cpp | 4 +++- src/port/Save/Types.h | 3 +++ src/port/UI/Notification.cpp | 26 +++++++++++++++++++----- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/port/Rando/Logic/GlitchlessLogic.cpp b/src/port/Rando/Logic/GlitchlessLogic.cpp index e93031ccc..75390a401 100644 --- a/src/port/Rando/Logic/GlitchlessLogic.cpp +++ b/src/port/Rando/Logic/GlitchlessLogic.cpp @@ -241,7 +241,9 @@ void PopulateJinjoCheckIds() { } void ResetSaveData() { - for (int s = 0; s < sizeof(SaveData); s++) { + // [port] `data` is the 112-byte vanilla payload, not the whole SaveData, which is + // ~43 KB once shipSaveData (rando checks, note/jinjo retention) is counted. + for (size_t s = 0; s < sizeof(gameFile_saveData[selectedFileNum].data); s++) { gameFile_saveData[selectedFileNum].data[s] = 0; } diff --git a/src/port/Save/Types.h b/src/port/Save/Types.h index 49a1aa2f9..d5bede421 100644 --- a/src/port/Save/Types.h +++ b/src/port/Save/Types.h @@ -417,6 +417,9 @@ static constexpr int kSnsItemCount = sizeof(kSnsUnlocked) / sizeof(kSnsUnlocked[ // so internal gamenum 0/1/2 corresponds to displayed Game 1/3/2. static int SlotToFileIndex(int gameNum) { static const int fileMap[3] = { 1, 3, 2 }; + if (gameNum < 0 || gameNum >= 3) { + return 0; + } return fileMap[gameNum]; } diff --git a/src/port/UI/Notification.cpp b/src/port/UI/Notification.cpp index e7380efb0..cb89c0311 100644 --- a/src/port/UI/Notification.cpp +++ b/src/port/UI/Notification.cpp @@ -2,11 +2,15 @@ #include "port/UI/cvar_prefixes.h" #include #include +#include +#include namespace Notification { static uint32_t nextId = 0; static std::vector notifications = {}; +// Emit() runs on the game thread; Draw()/UpdateElement() run on the render thread. +static std::mutex notificationsMutex; #define ABS(x) ((x) >= 0 ? (x) : -(x)) @@ -46,9 +50,17 @@ void Window::Draw() { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0f * CVarGetFloat(CVAR_SETTING("Notifications.Size"), 1.8f), 8.0f)); - for (size_t index = 0; index < notifications.size(); ++index) { - auto& notification = notifications[index]; - int inverseIndex = -ABS((int)index - (int)(notifications.size() - 1)); + // Render from a snapshot rather than the live vector, so a concurrent Emit() can + // reallocate without invalidating anything this loop is reading. + std::vector snapshot; + { + std::lock_guard lock(notificationsMutex); + snapshot = notifications; + } + + for (size_t index = 0; index < snapshot.size(); ++index) { + auto& notification = snapshot[index]; + int inverseIndex = -ABS((int)index - (int)(snapshot.size() - 1)); ImGui::SetNextWindowViewport(vp->ID); if (notification.remainingTime < 4.0f) { @@ -114,6 +126,7 @@ void Window::Draw() { } void Window::UpdateElement() { + std::lock_guard lock(notificationsMutex); for (int index = 0; index < notifications.size(); ++index) { auto& notification = notifications[index]; @@ -129,11 +142,14 @@ void Window::UpdateElement() { } void Emit(Options notification) { - notification.id = nextId++; if (notification.remainingTime == 0.0f) { notification.remainingTime = CVarGetFloat(CVAR_SETTING("Notifications.Duration"), 10.0f); } - notifications.push_back(notification); + { + std::lock_guard lock(notificationsMutex); + notification.id = nextId++; + notifications.push_back(notification); + } if (!notification.mute) { // TODO: play game notification sound }