From 7ff9fbdb479efda6a968f13c54bca75a26b4895a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 9 Aug 2026 16:03:12 +0200 Subject: [PATCH] InputMapping: fix OOB access, reject DEVICE_ID_ANY mappings FromConfigString() indexed parts[0]/parts[1] from SplitString() with no check that at least 2 parts were produced - a malformed/truncated line in a hand-edited controls.ini (no '-') was an OOB vector access. Separately, DEVICE_ID_ANY (-1) didn't round-trip correctly: ToConfigString() formats it as e.g. "-1-5", but splitting that on '-' produces "", "1", "5" instead of "-1", "5" - deviceId decoded to 0 and keyCode to 1 instead of 5. Rather than special-casing the negative sign to make it round-trip, just reject DEVICE_ID_ANY mappings outright - it's not something we want to support, and the whole ANY concept is likely going away. Preserves the existing (tested) behavior of tolerating a MultiInputMapping string and parsing just its first mapping, via atoi()'s stop-at-first-non-digit behavior. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01L4QAoxV2KY7ek4PcZw3WvY --- Common/Input/InputState.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Common/Input/InputState.cpp b/Common/Input/InputState.cpp index 50e82665e2..144eaa0839 100644 --- a/Common/Input/InputState.cpp +++ b/Common/Input/InputState.cpp @@ -3,6 +3,7 @@ #include "Common/Input/InputState.h" #include "Common/Input/KeyCodes.h" +#include "Common/Log.h" #include "Common/StringUtils.h" const char *GetDeviceName(int deviceId) { @@ -90,9 +91,25 @@ int GetAnalogYDirection(InputDeviceID deviceId) { // NOTE: Changing the format of FromConfigString/ToConfigString breaks controls.ini backwards compatibility. InputMapping InputMapping::FromConfigString(const std::string_view str) { + // DEVICE_ID_ANY (-1) is not a mapping we want to support (and the ANY concept is likely + // going away entirely), so reject it outright instead of trying to round-trip a negative + // device ID through the '-'-separated format. + if (str.size() >= 2 && str[0] == '-' && str[1] == '1') { + ERROR_LOG(Log::System, "Rejecting DEVICE_ID_ANY InputMapping config string: '%.*s'", (int)str.size(), str.data()); + return InputMapping(); + } + std::vector parts; SplitString(str, '-', parts); + if (parts.size() < 2) { + // Malformed entry, e.g. a corrupted/hand-edited controls.ini line. + ERROR_LOG(Log::System, "Bad InputMapping config string: '%.*s'", (int)str.size(), str.data()); + return InputMapping(); + } + // We only convert to std::string here to add null terminators for atoi. + // Note: atoi() stopping at the first non-digit character is relied upon elsewhere + // to let this parse just the first mapping out of a MultiInputMapping string. InputDeviceID deviceId = (InputDeviceID)(atoi(std::string(parts[0]).c_str())); InputKeyCode keyCode = (InputKeyCode)atoi(std::string(parts[1]).c_str());