From 8e3eb8519b0aa19e7a474bd61dfb681b5de978ee Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Fri, 18 Feb 2022 21:23:26 +0100 Subject: [PATCH] Fix potential crashes when adding or removing macro segments I wrongly assumed that std::deque would guarantee that pointers to elements in deque would not be invalidated by insert() or erase() but this is not the case it seems. "" An erase in the middle of the deque invalidates all the iterators and references to elements of the deque. An erase at either end of the deque invalidates only the iterators and the references to the erased elements. "" I guess I got lucky noone ran into these sorts of crashes for now? --- src/headers/advanced-scene-switcher.hpp | 2 ++ src/headers/macro-action-edit.hpp | 1 + src/headers/macro-condition-edit.hpp | 1 + src/macro-action-edit.cpp | 7 ++++++ src/macro-condition-edit.cpp | 7 ++++++ src/macro-tab.cpp | 33 +++++++++++++++++++++++++ 6 files changed, 51 insertions(+) diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index 87324651..1bfc7136 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -54,6 +54,8 @@ public: void HighlightCondition(int idx); void PopulateMacroActions(Macro &m, uint32_t afterIdx = 0); void PopulateMacroConditions(Macro &m, uint32_t afterIdx = 0); + void SetActionData(Macro &m); + void SetConditionData(Macro &m); void ConnectControlSignals(MacroActionEdit *); void ConnectControlSignals(MacroConditionEdit *); void SwapActions(Macro *m, int pos1, int pos2); diff --git a/src/headers/macro-action-edit.hpp b/src/headers/macro-action-edit.hpp index c33343f9..adfd0df8 100644 --- a/src/headers/macro-action-edit.hpp +++ b/src/headers/macro-action-edit.hpp @@ -34,6 +34,7 @@ public: std::shared_ptr * = nullptr, const std::string &id = "scene_switch"); void UpdateEntryData(const std::string &id); + void SetEntryData(std::shared_ptr *); private slots: void ActionSelectionChanged(const QString &text); diff --git a/src/headers/macro-condition-edit.hpp b/src/headers/macro-condition-edit.hpp index daebbd52..8e1ac4aa 100644 --- a/src/headers/macro-condition-edit.hpp +++ b/src/headers/macro-condition-edit.hpp @@ -38,6 +38,7 @@ public: bool IsRootNode(); void SetRootNode(bool); void UpdateEntryData(const std::string &id); + void SetEntryData(std::shared_ptr *); private slots: void LogicSelectionChanged(int idx); diff --git a/src/macro-action-edit.cpp b/src/macro-action-edit.cpp index 839e0aca..67090c1a 100644 --- a/src/macro-action-edit.cpp +++ b/src/macro-action-edit.cpp @@ -128,6 +128,11 @@ void MacroActionEdit::UpdateEntryData(const std::string &id) SetFocusPolicyOfWidgets(); } +void MacroActionEdit::SetEntryData(std::shared_ptr *data) +{ + _entryData = data; +} + MacroSegment *MacroActionEdit::Data() { return _entryData->get(); @@ -165,6 +170,7 @@ void AdvSceneSwitcher::AddMacroAction(int idx) clearLayout(actionsList->ContentLayout(), idx); PopulateMacroActions(*macro, idx); HighlightAction(idx); + SetActionData(*macro); } void AdvSceneSwitcher::on_actionAdd_clicked() @@ -208,6 +214,7 @@ void AdvSceneSwitcher::RemoveMacroAction(int idx) clearLayout(actionsList->ContentLayout(), idx); PopulateMacroActions(*macro, idx); + SetActionData(*macro); } void AdvSceneSwitcher::on_actionRemove_clicked() diff --git a/src/macro-condition-edit.cpp b/src/macro-condition-edit.cpp index ad719135..bcc96b9e 100644 --- a/src/macro-condition-edit.cpp +++ b/src/macro-condition-edit.cpp @@ -188,6 +188,11 @@ void MacroConditionEdit::UpdateEntryData(const std::string &id) SetFocusPolicyOfWidgets(); } +void MacroConditionEdit::SetEntryData(std::shared_ptr *data) +{ + _entryData = data; +} + void MacroConditionEdit::ConditionSelectionChanged(const QString &text) { if (_loading || !_entryData) { @@ -293,6 +298,7 @@ void AdvSceneSwitcher::AddMacroCondition(int idx) clearLayout(conditionsList->ContentLayout(), idx); PopulateMacroConditions(*macro, idx); HighlightCondition(idx); + SetConditionData(*macro); } void AdvSceneSwitcher::on_conditionAdd_clicked() @@ -339,6 +345,7 @@ void AdvSceneSwitcher::RemoveMacroCondition(int idx) clearLayout(conditionsList->ContentLayout(), idx); PopulateMacroConditions(*macro, idx); + SetConditionData(*macro); } void AdvSceneSwitcher::on_conditionRemove_clicked() diff --git a/src/macro-tab.cpp b/src/macro-tab.cpp index 3fab9a42..ac8349e9 100644 --- a/src/macro-tab.cpp +++ b/src/macro-tab.cpp @@ -254,6 +254,39 @@ void AdvSceneSwitcher::PopulateMacroConditions(Macro &m, uint32_t afterIdx) conditionsList->SetHelpMsgVisible(conditions.size() == 0); } +void AdvSceneSwitcher::SetActionData(Macro &m) +{ + auto &actions = m.Actions(); + for (int idx = 0; idx < actionsList->ContentLayout()->count(); idx++) { + auto item = actionsList->ContentLayout()->itemAt(idx); + if (!item) { + continue; + } + auto widget = static_cast(item->widget()); + if (!widget) { + continue; + } + widget->SetEntryData(&*(actions.begin() + idx)); + } +} + +void AdvSceneSwitcher::SetConditionData(Macro &m) +{ + auto &conditions = m.Conditions(); + for (int idx = 0; idx < conditionsList->ContentLayout()->count(); + idx++) { + auto item = conditionsList->ContentLayout()->itemAt(idx); + if (!item) { + continue; + } + auto widget = static_cast(item->widget()); + if (!widget) { + continue; + } + widget->SetEntryData(&*(conditions.begin() + idx)); + } +} + void AdvSceneSwitcher::SetEditMacro(Macro &m) { {