From ca801d55d50ddd6be84158d6ecfa18905b54b99d Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 23 Mar 2025 20:43:12 +0100 Subject: [PATCH] Fix: [NewGRF] Display an error, if NewGRF reference out-of-bounds string parameters in gender/plural choices. (#13881) --- src/strings.cpp | 11 +++++++++-- src/strings_internal.h | 6 ++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/strings.cpp b/src/strings.cpp index 005cecab18..83164dfa06 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -1161,7 +1161,10 @@ static void FormatString(StringBuilder &builder, std::string_view str_arg, Strin /* First read the meta data from the language file. */ size_t offset = ref_param_offset + (uint8_t)*str++; int gender = 0; - if (!dry_run && args.GetTypeAtOffset(offset) != 0) { + if (offset >= args.GetNumParameters()) { + /* The offset may come from an external NewGRF, and be invalid. */ + builder += "(invalid GENDER parameter)"; + } else if (!dry_run && args.GetTypeAtOffset(offset) != 0) { /* Now we need to figure out what text to resolve, i.e. * what do we need to draw? So get the actual raw string * first using the control code to get said string. */ @@ -1202,7 +1205,11 @@ static void FormatString(StringBuilder &builder, std::string_view str_arg, Strin case SCC_PLURAL_LIST: { // {P} int plural_form = *str++; // contains the plural form for this string size_t offset = ref_param_offset + (uint8_t)*str++; - const uint64_t *v = std::get_if(&args.GetParam(offset)); // contains the number that determines plural + const uint64_t *v = nullptr; + /* The offset may come from an external NewGRF, and be invalid. */ + if (offset < args.GetNumParameters()) { + v = std::get_if(&args.GetParam(offset)); // contains the number that determines plural + } if (v != nullptr) { str = ParseStringChoice(str, DeterminePluralForm(static_cast(*v), plural_form), builder); } else { diff --git a/src/strings_internal.h b/src/strings_internal.h index 6a73db44a4..bd2a2082e6 100644 --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -153,6 +153,12 @@ public: return this->parameters.size() - this->offset; } + /** Return the number of parameters. */ + size_t GetNumParameters() const + { + return this->parameters.size(); + } + /** Get the type of a specific element. */ char32_t GetTypeAtOffset(size_t offset) const {