Fix: TextfileWindow called virtual methods before constructor completed. (#11889)

SetStringParameters() was called during widget tree init in the constructor.

Calls within a constructor cannot call the derived classes methods. This would result in invalid data being passed to the string system, which could then crash.
This commit is contained in:
Peter Nelson 2024-01-27 14:45:37 +00:00 committed by GitHub
parent 8a4a99b7e8
commit fef0bfcfd3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 20 additions and 4 deletions

View File

@ -59,6 +59,8 @@ static std::optional<std::string> FindGameManualFilePath(std::string_view filena
struct GameManualTextfileWindow : public TextfileWindow {
GameManualTextfileWindow(std::string_view filename) : TextfileWindow(TFT_GAME_MANUAL)
{
this->ConstructWindow();
/* Mark the content of these files as trusted. */
this->trusted = true;

View File

@ -43,6 +43,8 @@ struct ContentTextfileWindow : public TextfileWindow {
ContentTextfileWindow(TextfileType file_type, const ContentInfo *ci) : TextfileWindow(file_type), ci(ci)
{
this->ConstructWindow();
auto textfile = this->ci->GetTextfile(file_type);
this->LoadTextfile(textfile.value(), GetContentInfoSubDir(this->ci->type));
}

View File

@ -560,6 +560,8 @@ struct NewGRFTextfileWindow : public TextfileWindow {
NewGRFTextfileWindow(TextfileType file_type, const GRFConfig *c) : TextfileWindow(file_type), grf_config(c)
{
this->ConstructWindow();
auto textfile = this->grf_config->GetTextfile(file_type);
this->LoadTextfile(textfile.value(), NEWGRF_DIR);
}

View File

@ -631,6 +631,7 @@ struct ScriptTextfileWindow : public TextfileWindow {
ScriptTextfileWindow(TextfileType file_type, CompanyID slot) : TextfileWindow(file_type), slot(slot)
{
this->ConstructWindow();
this->OnInvalidateData();
}

View File

@ -97,6 +97,8 @@ struct BaseSetTextfileWindow : public TextfileWindow {
BaseSetTextfileWindow(TextfileType file_type, const TBaseSet *baseset, StringID content_type) : TextfileWindow(file_type), baseset(baseset), content_type(content_type)
{
this->ConstructWindow();
auto textfile = this->baseset->GetTextfile(file_type);
this->LoadTextfile(textfile.value(), BASESET_DIR);
}

View File

@ -82,13 +82,19 @@ static WindowDesc _textfile_desc(__FILE__, __LINE__,
);
TextfileWindow::TextfileWindow(TextfileType file_type) : Window(&_textfile_desc), file_type(file_type)
{
/* Init of nested tree is deferred.
* TextfileWindow::ConstructWindow must be called by the inheriting window. */
}
void TextfileWindow::ConstructWindow()
{
this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_TF_VSCROLLBAR);
this->hscroll = this->GetScrollbar(WID_TF_HSCROLLBAR);
this->GetWidget<NWidgetCore>(WID_TF_CAPTION)->SetDataTip(STR_TEXTFILE_README_CAPTION + file_type, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS);
this->GetWidget<NWidgetCore>(WID_TF_CAPTION)->SetDataTip(STR_TEXTFILE_README_CAPTION + this->file_type, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS);
this->GetWidget<NWidgetStacked>(WID_TF_SEL_JUMPLIST)->SetDisplayedPlane(SZSP_HORIZONTAL);
this->FinishInitNested(file_type);
this->FinishInitNested(this->file_type);
this->DisableWidget(WID_TF_NAVBACK);
this->DisableWidget(WID_TF_NAVFORWARD);

View File

@ -23,8 +23,6 @@ struct TextfileWindow : public Window, MissingGlyphSearcher {
Scrollbar *vscroll; ///< Vertical scrollbar.
Scrollbar *hscroll; ///< Horizontal scrollbar.
TextfileWindow(TextfileType file_type);
void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override;
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override;
void DrawWidget(const Rect &r, WidgetID widget) const override;
@ -42,6 +40,9 @@ struct TextfileWindow : public Window, MissingGlyphSearcher {
virtual void LoadTextfile(const std::string &textfile, Subdirectory dir);
protected:
TextfileWindow(TextfileType file_type);
void ConstructWindow();
struct Line {
int top{0}; ///< Top scroll position in visual lines.
int bottom{0}; ///< Bottom scroll position in visual lines.