diff --git a/src/3rdparty/squirrel/squirrel/sqbaselib.cpp b/src/3rdparty/squirrel/squirrel/sqbaselib.cpp index 26c02510dd..cbda1adef8 100644 --- a/src/3rdparty/squirrel/squirrel/sqbaselib.cpp +++ b/src/3rdparty/squirrel/squirrel/sqbaselib.cpp @@ -5,6 +5,7 @@ #include "../../../stdafx.h" #include "../../fmt/format.h" +#include "../../../core/string_consumer.hpp" #include "sqpcheader.h" #include "sqvm.h" #include "sqstring.h" @@ -27,9 +28,9 @@ bool str2num(const SQChar *s,SQObjectPtr &res) return true; } else{ - SQInteger r = SQInteger(strtol(s,&end,10)); - if(s == end) return false; - res = r; + auto val = ParseInteger(s); + if (!val.has_value()) return false; + res = *val; return true; } } diff --git a/src/3rdparty/squirrel/squirrel/sqlexer.cpp b/src/3rdparty/squirrel/squirrel/sqlexer.cpp index 89eae0026e..6d6bba4960 100644 --- a/src/3rdparty/squirrel/squirrel/sqlexer.cpp +++ b/src/3rdparty/squirrel/squirrel/sqlexer.cpp @@ -12,6 +12,7 @@ #include "sqlexer.h" #include "../../../core/utf8.hpp" +#include "../../../core/string_consumer.hpp" #include "../../../safeguards.h" @@ -310,16 +311,16 @@ SQInteger SQLexer::ReadString(char32_t ndelim,bool verbatim) case 'x': NEXT(); { if(!isxdigit(CUR_CHAR)) Error("hexadecimal number expected"); const SQInteger maxdigits = 4; - SQChar temp[maxdigits+1]; - SQInteger n = 0; + SQChar temp[maxdigits]; + size_t n = 0; while(isxdigit(CUR_CHAR) && n < maxdigits) { temp[n] = CUR_CHAR; n++; NEXT(); } - temp[n] = 0; - SQChar *sTemp; - APPEND_CHAR((SQChar)strtoul(temp,&sTemp,16)); + auto val = ParseInteger(std::string_view{temp, n}, 16); + if (!val.has_value()) Error("hexadecimal number expected"); + APPEND_CHAR(static_cast(*val)); } break; case 't': APPEND_CHAR('\t'); NEXT(); break; diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 8c14f3c6b7..f7fcdaa168 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -45,6 +45,7 @@ #include "object_cmd.h" #include "timer/timer.h" #include "timer/timer_window.h" +#include "core/string_consumer.hpp" #include "widgets/company_widget.h" @@ -1692,7 +1693,9 @@ public: if (!str.has_value()) return; /* Set a new company manager face number */ if (!str->empty()) { - this->face = std::strtoul(str->c_str(), nullptr, 10); + auto val = ParseInteger(*str); + if (!val.has_value()) return; + this->face = *val; ScaleAllCompanyManagerFaceBits(this->face); ShowErrorMessage(GetEncodedString(STR_FACE_FACECODE_SET), {}, WL_INFO); this->UpdateData(); @@ -2455,7 +2458,9 @@ struct CompanyWindow : Window default: NOT_REACHED(); case WID_C_GIVE_MONEY: { - Money money = std::strtoull(str->c_str(), nullptr, 10) / GetCurrency().rate; + auto value = ParseInteger(*str); + if (!value.has_value()) return; + Money money = *value / GetCurrency().rate; Command::Post(STR_ERROR_CAN_T_GIVE_MONEY, money, this->window_number); break; } diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index c9df8d3cba..58db6b765a 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -609,9 +609,11 @@ struct NewGRFInspectWindow : Window { void OnQueryTextFinished(std::optional str) override { - if (!str.has_value() || str->empty()) return; + if (!str.has_value()) return; - NewGRFInspectWindow::var60params[GetFeatureNum(this->window_number)][this->current_edit_param - 0x60] = std::strtol(str->c_str(), nullptr, 16); + auto val = ParseInteger(*str); + if (!val.has_value()) return; + NewGRFInspectWindow::var60params[GetFeatureNum(this->window_number)][this->current_edit_param - 0x60] = *val; this->SetDirty(); } diff --git a/src/openttd.cpp b/src/openttd.cpp index 1a6bcce33d..3983183c74 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -636,7 +636,13 @@ int openttd_main(std::span arguments) _skip_all_newgrf_scanning += 1; break; } - case 'G': scanner->generation_seed = std::strtoul(mgo.opt, nullptr, 10); break; + case 'G': + if (auto value = ParseInteger(mgo.opt); value.has_value()) { + scanner->generation_seed = *value; + } else { + fmt::print(stderr, "Invalid generation seed: {}\n", mgo.opt); + } + break; case 'c': _config_file = mgo.opt; break; case 'x': scanner->save_config = false; break; case 'X': only_local_path = true; break; diff --git a/src/safeguards.h b/src/safeguards.h index e5919c3de3..d00c7c0c71 100644 --- a/src/safeguards.h +++ b/src/safeguards.h @@ -55,6 +55,10 @@ #define atoi SAFEGUARD_DO_NOT_USE_THIS_METHOD #define atol SAFEGUARD_DO_NOT_USE_THIS_METHOD #define atoll SAFEGUARD_DO_NOT_USE_THIS_METHOD +#define strtol SAFEGUARD_DO_NOT_USE_THIS_METHOD +#define strtoll SAFEGUARD_DO_NOT_USE_THIS_METHOD +#define strtoul SAFEGUARD_DO_NOT_USE_THIS_METHOD +#define strtoull SAFEGUARD_DO_NOT_USE_THIS_METHOD /* Use fmt::print instead. */ #define printf SAFEGUARD_DO_NOT_USE_THIS_METHOD diff --git a/src/settings.cpp b/src/settings.cpp index 670a0d3c00..d54048112d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1010,10 +1010,26 @@ static void GraphicsSetLoadConfig(IniFile &ini) if (const IniItem *item = group->GetItem("name"); item != nullptr && item->value) BaseGraphics::ini_data.name = *item->value; if (const IniItem *item = group->GetItem("shortname"); item != nullptr && item->value && item->value->size() == 8) { - BaseGraphics::ini_data.shortname = std::byteswap(std::strtoul(item->value->c_str(), nullptr, 16)); + auto val = ParseInteger(*item->value, 16); + if (val.has_value()) { + BaseGraphics::ini_data.shortname = std::byteswap(*val); + } else { + ShowErrorMessage(GetEncodedString(STR_CONFIG_ERROR), + GetEncodedString(STR_CONFIG_ERROR_INVALID_VALUE, *item->value, BaseGraphics::ini_data.name), + WL_CRITICAL); + } } - if (const IniItem *item = group->GetItem("extra_version"); item != nullptr && item->value) BaseGraphics::ini_data.extra_version = std::strtoul(item->value->c_str(), nullptr, 10); + if (const IniItem *item = group->GetItem("extra_version"); item != nullptr && item->value) { + auto val = ParseInteger(*item->value); + if (val.has_value()) { + BaseGraphics::ini_data.extra_version = *val; + } else { + ShowErrorMessage(GetEncodedString(STR_CONFIG_ERROR), + GetEncodedString(STR_CONFIG_ERROR_INVALID_VALUE, *item->value, BaseGraphics::ini_data.name), + WL_CRITICAL); + } + } if (const IniItem *item = group->GetItem("extra_params"); item != nullptr && item->value) { auto params = ParseIntList(item->value->c_str()); diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index f07f7cf19e..b1557de493 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -27,6 +27,7 @@ #include "settings_type.h" #include "timetable_cmd.h" #include "timetable.h" +#include "core/string_consumer.hpp" #include "widgets/timetable_widget.h" @@ -747,7 +748,7 @@ struct TimetableWindow : Window { if (!str.has_value()) return; const Vehicle *v = this->vehicle; - uint64_t val = str->empty() ? 0 : std::strtoul(str->c_str(), nullptr, 10); + uint64_t val = ParseInteger(*str).value_or(0); auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, query_widget == WID_VT_CHANGE_SPEED); switch (query_widget) {