From ff77febb365c0251cac35a761c31d031f888ba49 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 27 Mar 2026 10:14:49 -0700 Subject: [PATCH] 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. --- src/core/application.cpp | 16 +++++++++++----- src/rendering/renderer.cpp | 8 ++++++-- src/ui/keybinding_manager.cpp | 10 ++++++---- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/core/application.cpp b/src/core/application.cpp index 5f980e5c..836a7b23 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -2232,7 +2232,8 @@ void Application::setupUICallbacks() { size_t colonPos = realmAddress.find(':'); if (colonPos != std::string::npos) { host = realmAddress.substr(0, colonPos); - port = static_cast(std::stoi(realmAddress.substr(colonPos + 1))); + try { port = static_cast(std::stoi(realmAddress.substr(colonPos + 1))); } + catch (...) { LOG_WARNING("Invalid port in realm address: ", realmAddress); } } // Connect to world server @@ -9715,10 +9716,15 @@ Application::LastWorldInfo Application::loadLastWorldInfo() const { std::ifstream f(dir + "/last_world.cfg"); if (!f) return info; std::string line; - if (std::getline(f, line)) info.mapId = static_cast(std::stoul(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.y = std::stof(line); + try { + if (std::getline(f, line)) info.mapId = static_cast(std::stoul(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.y = std::stof(line); + } catch (...) { + LOG_WARNING("Malformed last_world.cfg, ignoring saved position"); + return info; + } info.valid = !info.mapName.empty(); return info; } diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index 36e404cb..85c5ae5b 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -6036,8 +6036,12 @@ bool Renderer::loadTestTerrain(pipeline::AssetManager* assetManager, const std:: if (secondUnderscore != std::string::npos) { size_t dot = filename.find('.', secondUnderscore); if (dot != std::string::npos) { - tileX = std::stoi(filename.substr(firstUnderscore + 1, secondUnderscore - firstUnderscore - 1)); - tileY = std::stoi(filename.substr(secondUnderscore + 1, dot - secondUnderscore - 1)); + try { + tileX = std::stoi(filename.substr(firstUnderscore + 1, secondUnderscore - firstUnderscore - 1)); + tileY = std::stoi(filename.substr(secondUnderscore + 1, dot - secondUnderscore - 1)); + } catch (...) { + LOG_WARNING("Failed to parse tile coords from: ", filename); + } } } } diff --git a/src/ui/keybinding_manager.cpp b/src/ui/keybinding_manager.cpp index a7f52a3b..81e63bd3 100644 --- a/src/ui/keybinding_manager.cpp +++ b/src/ui/keybinding_manager.cpp @@ -192,10 +192,12 @@ void KeybindingManager::loadFromConfigFile(const std::string& filePath) { key = ImGuiKey_End; } else if (keyStr.find("F") == 0 && keyStr.length() <= 3) { // F1-F12 keys - int fNum = std::stoi(keyStr.substr(1)); - if (fNum >= 1 && fNum <= 12) { - key = static_cast(ImGuiKey_F1 + (fNum - 1)); - } + try { + int fNum = std::stoi(keyStr.substr(1)); + if (fNum >= 1 && fNum <= 12) { + key = static_cast(ImGuiKey_F1 + (fNum - 1)); + } + } catch (...) {} } if (key == ImGuiKey_None) continue;