From ba2782e9d1ac875aa176b610835c0e71ab74e869 Mon Sep 17 00:00:00 2001 From: Filoppi Date: Mon, 26 Apr 2021 19:41:31 +0300 Subject: [PATCH 1/2] InputCommon: fix hotkey suppression crash if nullptr suppressions were added to the map Update references was failing to update the references, causing input to stay nullptr and crashing. I fixed the case that triggered that, though also added checks against nullptrs for safety. (cherry picked from commit 4bdcf707555a5568eddff957fa3604975ffb6ed7) --- .../ControlReference/ExpressionParser.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 59c48f45dc..0aad39fd02 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -63,7 +63,7 @@ private: void RemoveSuppression(Device::Input* modifier, Device::Input* final_input) { auto it = m_suppressions.find({final_input, modifier}); - if ((--it->second) == 0) + if (it != m_suppressions.end() && (--it->second) == 0) m_suppressions.erase(it); } @@ -302,7 +302,7 @@ bool HotkeySuppressions::IsSuppressedIgnoringModifiers(Device::Input* input, // We need to ignore L_Ctrl R_Ctrl when supplied Ctrl and vice-versa. const auto is_same_modifier = [](Device::Input* i1, Device::Input* i2) { - return i1 == i2 || i1->IsChild(i2) || i2->IsChild(i1); + return i1 && i2 && (i1 == i2 || i1->IsChild(i2) || i2->IsChild(i1)); }; return std::any_of(it, it_end, [&](auto& s) { @@ -316,7 +316,13 @@ HotkeySuppressions::MakeSuppressor(const Modifiers* modifiers, const std::unique_ptr* final_input) { for (auto& modifier : *modifiers) - ++m_suppressions[{(*final_input)->GetInput(), modifier->GetInput()}]; + { + // Inputs might be null, don't add nullptr to the map + if ((*final_input)->GetInput() && modifier->GetInput()) + { + ++m_suppressions[{(*final_input)->GetInput(), modifier->GetInput()}]; + } + } return Suppressor(std::make_unique>([this, modifiers, final_input]() { for (auto& modifier : *modifiers) @@ -483,6 +489,7 @@ public: ControlState GetValue() const override { + // True if we have no modifiers const bool modifiers_pressed = std::all_of(m_modifiers.begin(), m_modifiers.end(), [](const std::unique_ptr& input) { return input->GetValue() > CONDITION_THRESHOLD; @@ -539,13 +546,13 @@ public: // We must update our suppression with valid pointers. if (m_suppressor) - EnableSuppression(); + EnableSuppression(true); } private: - void EnableSuppression() const + void EnableSuppression(bool force = false) const { - if (!m_suppressor) + if (!m_suppressor || force) m_suppressor = s_hotkey_suppressions.MakeSuppressor(&m_modifiers, &m_final_input); } From 799a368a7c673cfddd49a8663e4e0a827ab83b7f Mon Sep 17 00:00:00 2001 From: Filoppi Date: Mon, 26 Apr 2021 19:45:13 +0300 Subject: [PATCH 2/2] InputCommon: small hotkey threshold symmetry fix --- Source/Core/InputCommon/ControlReference/ExpressionParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp index 0aad39fd02..c8b88677f0 100644 --- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp +++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp @@ -503,7 +503,7 @@ public: const bool is_suppressed = s_hotkey_suppressions.IsSuppressedIgnoringModifiers( m_final_input->GetInput(), m_modifiers); - if (final_input_state < CONDITION_THRESHOLD) + if (final_input_state <= CONDITION_THRESHOLD) m_is_blocked = false; // If some other hotkey suppressed us, require a release of final input to be ready again.