fix: guard std::stoi/stof calls at input boundaries against exceptions

Wrap string-to-number conversions in try-catch where input comes from
external sources (realm address port, last_world.cfg, keybinding config,
ADT tile filenames) to prevent crashes on malformed data.
This commit is contained in:
Kelsi 2026-03-27 10:14:49 -07:00
parent ee20f823f7
commit ff77febb36
3 changed files with 23 additions and 11 deletions

View file

@ -2232,7 +2232,8 @@ void Application::setupUICallbacks() {
size_t colonPos = realmAddress.find(':'); size_t colonPos = realmAddress.find(':');
if (colonPos != std::string::npos) { if (colonPos != std::string::npos) {
host = realmAddress.substr(0, colonPos); host = realmAddress.substr(0, colonPos);
port = static_cast<uint16_t>(std::stoi(realmAddress.substr(colonPos + 1))); try { port = static_cast<uint16_t>(std::stoi(realmAddress.substr(colonPos + 1))); }
catch (...) { LOG_WARNING("Invalid port in realm address: ", realmAddress); }
} }
// Connect to world server // Connect to world server
@ -9715,10 +9716,15 @@ Application::LastWorldInfo Application::loadLastWorldInfo() const {
std::ifstream f(dir + "/last_world.cfg"); std::ifstream f(dir + "/last_world.cfg");
if (!f) return info; if (!f) return info;
std::string line; std::string line;
try {
if (std::getline(f, line)) info.mapId = static_cast<uint32_t>(std::stoul(line)); if (std::getline(f, line)) info.mapId = static_cast<uint32_t>(std::stoul(line));
if (std::getline(f, line)) info.mapName = line; if (std::getline(f, line)) info.mapName = line;
if (std::getline(f, line)) info.x = std::stof(line); if (std::getline(f, line)) info.x = std::stof(line);
if (std::getline(f, line)) info.y = std::stof(line); if (std::getline(f, line)) info.y = std::stof(line);
} catch (...) {
LOG_WARNING("Malformed last_world.cfg, ignoring saved position");
return info;
}
info.valid = !info.mapName.empty(); info.valid = !info.mapName.empty();
return info; return info;
} }

View file

@ -6036,8 +6036,12 @@ bool Renderer::loadTestTerrain(pipeline::AssetManager* assetManager, const std::
if (secondUnderscore != std::string::npos) { if (secondUnderscore != std::string::npos) {
size_t dot = filename.find('.', secondUnderscore); size_t dot = filename.find('.', secondUnderscore);
if (dot != std::string::npos) { if (dot != std::string::npos) {
try {
tileX = std::stoi(filename.substr(firstUnderscore + 1, secondUnderscore - firstUnderscore - 1)); tileX = std::stoi(filename.substr(firstUnderscore + 1, secondUnderscore - firstUnderscore - 1));
tileY = std::stoi(filename.substr(secondUnderscore + 1, dot - secondUnderscore - 1)); tileY = std::stoi(filename.substr(secondUnderscore + 1, dot - secondUnderscore - 1));
} catch (...) {
LOG_WARNING("Failed to parse tile coords from: ", filename);
}
} }
} }
} }

View file

@ -192,10 +192,12 @@ void KeybindingManager::loadFromConfigFile(const std::string& filePath) {
key = ImGuiKey_End; key = ImGuiKey_End;
} else if (keyStr.find("F") == 0 && keyStr.length() <= 3) { } else if (keyStr.find("F") == 0 && keyStr.length() <= 3) {
// F1-F12 keys // F1-F12 keys
try {
int fNum = std::stoi(keyStr.substr(1)); int fNum = std::stoi(keyStr.substr(1));
if (fNum >= 1 && fNum <= 12) { if (fNum >= 1 && fNum <= 12) {
key = static_cast<ImGuiKey>(ImGuiKey_F1 + (fNum - 1)); key = static_cast<ImGuiKey>(ImGuiKey_F1 + (fNum - 1));
} }
} catch (...) {}
} }
if (key == ImGuiKey_None) continue; if (key == ImGuiKey_None) continue;