From eefb254de16a9336525ebbfb2e72aa760d215a7e Mon Sep 17 00:00:00 2001 From: Ronny Dudeck Date: Wed, 6 May 2026 08:20:08 +0200 Subject: [PATCH] config(legacy): null-check getConfigValueSafeDevice in getDevice* getters getConfigValueSafeDevice can return nullptr when: - the device has no matching special config entry, and - the fallback string is empty (default for getDevice* caller) This caused a null dereference in getDeviceInt, getDeviceFloat, getDeviceVec, and getDeviceString when called for devices without a explicit config block. InputManager.cpp:1170 (keyboard tags) and :1301 (mouse tags) hit this on startup for any device that doesn't has a device { name = ...; tags = ...; } entry. The tags feature was added in r320, exposing this latent bugs. Fix by storing the pointer local and returning type-appropriate defaults (0, 0.F, {0,0}, "") when nullptr. Fixes: 497b48e ("config: add device tags (#13728)") --- src/config/legacy/ConfigManager.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/config/legacy/ConfigManager.cpp b/src/config/legacy/ConfigManager.cpp index e4c485e03..95a93cb80 100644 --- a/src/config/legacy/ConfigManager.cpp +++ b/src/config/legacy/ConfigManager.cpp @@ -1134,25 +1134,34 @@ bool CConfigManager::deviceConfigExplicitlySet(const std::string& dev, const std } int CConfigManager::getDeviceInt(const std::string& dev, const std::string& v, const std::string& fallback) { - return std::any_cast(getConfigValueSafeDevice(dev, v, fallback)->getValue()); + const auto VAL = getConfigValueSafeDevice(dev, v, fallback); + return VAL ? std::any_cast(VAL->getValue()) : 0; } float CConfigManager::getDeviceFloat(const std::string& dev, const std::string& v, const std::string& fallback) { - return std::any_cast(getConfigValueSafeDevice(dev, v, fallback)->getValue()); + const auto VAL = getConfigValueSafeDevice(dev, v, fallback); + return VAL ? std::any_cast(VAL->getValue()) : 0.F; } Vector2D CConfigManager::getDeviceVec(const std::string& dev, const std::string& v, const std::string& fallback) { - auto vec = std::any_cast(getConfigValueSafeDevice(dev, v, fallback)->getValue()); + const auto VAL = getConfigValueSafeDevice(dev, v, fallback); + if (!VAL) + return {0, 0}; + auto vec = std::any_cast(VAL->getValue()); return {vec.x, vec.y}; } std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v, const std::string& fallback) { - auto VAL = std::string{std::any_cast(getConfigValueSafeDevice(dev, v, fallback)->getValue())}; - - if (VAL == STRVAL_EMPTY) + const auto VAL = getConfigValueSafeDevice(dev, v, fallback); + if (!VAL) return ""; - return VAL; + auto STR = std::string{std::any_cast(VAL->getValue())}; + + if (STR == STRVAL_EMPTY) + return ""; + + return STR; } SConfigOptionReply CConfigManager::getConfigValue(const std::string& val) {