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 <[email protected]>
Claude-Session: https://claude.ai/code/session_01L4QAoxV2KY7ek4PcZw3WvY
This commit is contained in:
Henrik RydgårdandClaude Sonnet 5 committed 2026-08-09 21:41:54 +02:00
1 parent 472ff6ac71
commit 7ff9fbdb47
1 file changed
+17
+17
View File
@@ -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<std::string_view> 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());