From 59a046de9c8b50121a38bcbc9e0fe87cd8cc66c0 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Fri, 2 Feb 2024 23:01:54 +0100 Subject: [PATCH] Fix: don't use non-owning string pointer in StringParameter (#11952) The string pointer can become invalid before the reference is dropped, causing out-of-bound access in windows like ErrorWindow, or News that copy 10 or 20 parameters for their internals. Co-authored-by: Jonathan G Rennison --- src/strings_internal.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/strings_internal.h b/src/strings_internal.h index fc28c34716..3095e33107 100644 --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -16,7 +16,6 @@ /** The data required to format and validate a single parameter of a string. */ struct StringParameter { uint64_t data; ///< The data of the parameter. - const char *string_view; ///< The string value, if it has any. std::unique_ptr string; ///< Copied string value, if it has any. char32_t type; ///< The #StringControlCode to interpret this data with when it's the first parameter, otherwise '\0'. }; @@ -106,7 +105,7 @@ public: const char *GetNextParameterString() { auto ptr = GetNextParameterPointer(); - return ptr->string != nullptr ? ptr->string->c_str() : ptr->string_view; + return ptr->string != nullptr ? ptr->string->c_str() : nullptr; } /** @@ -152,7 +151,6 @@ public: assert(n < this->parameters.size()); this->parameters[n].data = v; this->parameters[n].string.reset(); - this->parameters[n].string_view = nullptr; } template ::value, int> = 0> @@ -165,8 +163,7 @@ public: { assert(n < this->parameters.size()); this->parameters[n].data = 0; - this->parameters[n].string.reset(); - this->parameters[n].string_view = str; + this->parameters[n].string = std::make_unique(str); } void SetParam(size_t n, const std::string &str) { this->SetParam(n, str.c_str()); } @@ -176,13 +173,12 @@ public: assert(n < this->parameters.size()); this->parameters[n].data = 0; this->parameters[n].string = std::make_unique(std::move(str)); - this->parameters[n].string_view = nullptr; } uint64_t GetParam(size_t n) const { assert(n < this->parameters.size()); - assert(this->parameters[n].string_view == nullptr && this->parameters[n].string == nullptr); + assert(this->parameters[n].string == nullptr); return this->parameters[n].data; } @@ -195,7 +191,7 @@ public: { assert(n < this->parameters.size()); auto ¶m = this->parameters[n]; - return param.string != nullptr ? param.string->c_str() : param.string_view; + return param.string != nullptr ? param.string->c_str() : nullptr; } };