mirror of https://github.com/PCSX2/pcsx2.git
FullscreenUI: Fix descriptor use-after-free when deleting state
This commit is contained in:
parent
2ef2f5db1d
commit
613a9964a1
|
@ -402,8 +402,7 @@ namespace FullscreenUI
|
|||
s32 slot;
|
||||
};
|
||||
|
||||
static void InitializePlaceholderSaveStateListEntry(
|
||||
SaveStateListEntry* li, const std::string& title, const std::string& serial, u32 crc, s32 slot);
|
||||
static void InitializePlaceholderSaveStateListEntry(SaveStateListEntry* li, s32 slot);
|
||||
static bool InitializeSaveStateListEntry(
|
||||
SaveStateListEntry* li, const std::string& title, const std::string& serial, u32 crc, s32 slot);
|
||||
static void ClearSaveStateEntryList();
|
||||
|
@ -4496,8 +4495,7 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
|
|||
#endif
|
||||
}
|
||||
|
||||
void FullscreenUI::InitializePlaceholderSaveStateListEntry(
|
||||
SaveStateListEntry* li, const std::string& title, const std::string& serial, u32 crc, s32 slot)
|
||||
void FullscreenUI::InitializePlaceholderSaveStateListEntry(SaveStateListEntry* li, s32 slot)
|
||||
{
|
||||
li->title = (slot == 0) ? std::string("Quick Save Slot") : fmt::format("Save Slot {0}##game_slot_{0}", slot);
|
||||
li->summary = "No save present in this slot.";
|
||||
|
@ -4514,7 +4512,7 @@ bool FullscreenUI::InitializeSaveStateListEntry(
|
|||
FILESYSTEM_STAT_DATA sd;
|
||||
if (filename.empty() || !FileSystem::StatFile(filename.c_str(), &sd))
|
||||
{
|
||||
InitializePlaceholderSaveStateListEntry(li, title, serial, crc, slot);
|
||||
InitializePlaceholderSaveStateListEntry(li, slot);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -4686,16 +4684,126 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading)
|
|||
|
||||
u32 grid_x = 0;
|
||||
ImGui::SetCursorPos(ImVec2(start_x, 0.0f));
|
||||
for (u32 i = 0; i < s_save_state_selector_slots.size(); i++)
|
||||
for (u32 i = 0; i < s_save_state_selector_slots.size();)
|
||||
{
|
||||
if (i == 0)
|
||||
ResetFocusHere();
|
||||
|
||||
const SaveStateListEntry& entry = s_save_state_selector_slots[i];
|
||||
if (static_cast<s32>(i) == s_save_state_selector_submenu_index)
|
||||
{
|
||||
SaveStateListEntry& entry = s_save_state_selector_slots[i];
|
||||
|
||||
// can't use a choice dialog here, because we're already in a modal...
|
||||
ImGuiFullscreen::PushResetLayout();
|
||||
ImGui::PushFont(g_large_font);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_TitleBg, UIPrimaryDarkColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, UIPrimaryColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, MulAlpha(UIBackgroundColor, 0.95f));
|
||||
|
||||
const float width = LayoutScale(600.0f);
|
||||
const float title_height =
|
||||
g_large_font->FontSize + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f;
|
||||
const float height =
|
||||
title_height + LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY + (LAYOUT_MENU_BUTTON_Y_PADDING * 2.0f)) * 3.0f;
|
||||
ImGui::SetNextWindowSize(ImVec2(width, height));
|
||||
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
ImGui::OpenPopup(entry.title.c_str());
|
||||
|
||||
// don't let the back button flow through to the main window
|
||||
bool submenu_open = !WantsToCloseMenu();
|
||||
close_handled ^= submenu_open;
|
||||
|
||||
bool closed = false;
|
||||
if (ImGui::BeginPopupModal(
|
||||
entry.title.c_str(), &is_open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, UIBackgroundTextColor);
|
||||
|
||||
BeginMenuButtons();
|
||||
|
||||
if (ActiveButton(is_loading ? ICON_FA_FOLDER_OPEN " Load State" : ICON_FA_FOLDER_OPEN " Save State", false, true,
|
||||
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
||||
{
|
||||
if (is_loading)
|
||||
DoLoadState(std::move(entry.path));
|
||||
else
|
||||
Host::RunOnCPUThread([slot = entry.slot]() { VMManager::SaveStateToSlot(slot); });
|
||||
|
||||
CloseSaveStateSelector();
|
||||
closed = true;
|
||||
}
|
||||
|
||||
if (ActiveButton(ICON_FA_FOLDER_MINUS " Delete Save", false, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
||||
{
|
||||
if (!FileSystem::FileExists(entry.path.c_str()))
|
||||
{
|
||||
ShowToast({}, fmt::format("{} does not exist.", ImGuiFullscreen::RemoveHash(entry.title)));
|
||||
is_open = true;
|
||||
}
|
||||
else if (FileSystem::DeleteFilePath(entry.path.c_str()))
|
||||
{
|
||||
ShowToast({}, fmt::format("{} deleted.", ImGuiFullscreen::RemoveHash(entry.title)));
|
||||
if (s_save_state_selector_loading)
|
||||
s_save_state_selector_slots.erase(s_save_state_selector_slots.begin() + i);
|
||||
else
|
||||
InitializePlaceholderSaveStateListEntry(&entry, entry.slot);
|
||||
|
||||
// Close if this was the last state.
|
||||
if (s_save_state_selector_slots.empty())
|
||||
{
|
||||
CloseSaveStateSelector();
|
||||
closed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_open = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowToast({}, fmt::format("Failed to delete {}.", ImGuiFullscreen::RemoveHash(entry.title)));
|
||||
is_open = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ActiveButton(ICON_FA_WINDOW_CLOSE " Close Menu", false, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
||||
{
|
||||
is_open = false;
|
||||
}
|
||||
|
||||
EndMenuButtons();
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
if (!is_open)
|
||||
{
|
||||
s_save_state_selector_submenu_index = -1;
|
||||
if (!closed)
|
||||
QueueResetFocus();
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(4);
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopFont();
|
||||
ImGuiFullscreen::PopResetLayout();
|
||||
|
||||
if (closed || i >= s_save_state_selector_slots.size())
|
||||
break;
|
||||
}
|
||||
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const SaveStateListEntry& entry = s_save_state_selector_slots[i];
|
||||
const ImGuiID id = window->GetID(static_cast<int>(i));
|
||||
const ImVec2 pos(window->DC.CursorPos);
|
||||
ImRect bb(pos, pos + item_size);
|
||||
|
@ -4765,108 +4873,6 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading)
|
|||
{
|
||||
s_save_state_selector_submenu_index = static_cast<s32>(i);
|
||||
}
|
||||
|
||||
if (static_cast<s32>(i) == s_save_state_selector_submenu_index)
|
||||
{
|
||||
// can't use a choice dialog here, because we're already in a modal...
|
||||
ImGuiFullscreen::PushResetLayout();
|
||||
ImGui::PushFont(g_large_font);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
|
||||
ImGui::PushStyleVar(
|
||||
ImGuiStyleVar_FramePadding, LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_TitleBg, UIPrimaryDarkColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, UIPrimaryColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, MulAlpha(UIBackgroundColor, 0.95f));
|
||||
|
||||
const float width = LayoutScale(600.0f);
|
||||
const float title_height =
|
||||
g_large_font->FontSize + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f;
|
||||
const float height =
|
||||
title_height + LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY + (LAYOUT_MENU_BUTTON_Y_PADDING * 2.0f)) * 3.0f;
|
||||
ImGui::SetNextWindowSize(ImVec2(width, height));
|
||||
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
ImGui::OpenPopup(entry.title.c_str());
|
||||
|
||||
// don't let the back button flow through to the main window
|
||||
bool submenu_open = !WantsToCloseMenu();
|
||||
close_handled ^= submenu_open;
|
||||
|
||||
bool closed = false;
|
||||
if (ImGui::BeginPopupModal(entry.title.c_str(), &is_open,
|
||||
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, UIBackgroundTextColor);
|
||||
|
||||
BeginMenuButtons();
|
||||
|
||||
if (ActiveButton(is_loading ? ICON_FA_FOLDER_OPEN " Load State" : ICON_FA_FOLDER_OPEN " Save State", false, true,
|
||||
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
||||
{
|
||||
if (is_loading)
|
||||
DoLoadState(std::move(entry.path));
|
||||
else
|
||||
Host::RunOnCPUThread([slot = entry.slot]() { VMManager::SaveStateToSlot(slot); });
|
||||
|
||||
CloseSaveStateSelector();
|
||||
closed = true;
|
||||
}
|
||||
|
||||
if (ActiveButton(ICON_FA_FOLDER_MINUS " Delete Save", false, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
||||
{
|
||||
if (!FileSystem::FileExists(entry.path.c_str()))
|
||||
{
|
||||
ShowToast({}, fmt::format("{} does not exist.", ImGuiFullscreen::RemoveHash(entry.title)));
|
||||
is_open = true;
|
||||
}
|
||||
else if (FileSystem::DeleteFilePath(entry.path.c_str()))
|
||||
{
|
||||
ShowToast({}, fmt::format("{} deleted.", ImGuiFullscreen::RemoveHash(entry.title)));
|
||||
s_save_state_selector_slots.erase(s_save_state_selector_slots.begin() + i);
|
||||
|
||||
if (s_save_state_selector_slots.empty())
|
||||
{
|
||||
CloseSaveStateSelector();
|
||||
closed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_open = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowToast({}, fmt::format("Failed to delete {}.", ImGuiFullscreen::RemoveHash(entry.title)));
|
||||
is_open = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ActiveButton(ICON_FA_WINDOW_CLOSE " Close Menu", false, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
||||
{
|
||||
is_open = false;
|
||||
}
|
||||
|
||||
EndMenuButtons();
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
if (!is_open)
|
||||
{
|
||||
s_save_state_selector_submenu_index = -1;
|
||||
if (!closed)
|
||||
QueueResetFocus();
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(4);
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopFont();
|
||||
ImGuiFullscreen::PopResetLayout();
|
||||
|
||||
if (closed)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
grid_x++;
|
||||
|
@ -4880,6 +4886,8 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading)
|
|||
{
|
||||
ImGui::SameLine(start_x + static_cast<float>(grid_x) * (item_width + item_spacing));
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
EndMenuButtons();
|
||||
|
|
Loading…
Reference in New Issue