From 76f0f9e38689d3a03fe42b3cd337b4ac2af33c37 Mon Sep 17 00:00:00 2001 From: SamuXarick <43006711+SamuXarick@users.noreply.github.com> Date: Sat, 27 Jan 2024 21:11:02 +0000 Subject: [PATCH] Fix #10438: [GS] Validate story page element type for ScriptStoryPage::NewElement (#11888) Fixes a crash that happens if an invalid StoryPageElementType is passed to ScriptStoryPage::NewElement. Adds an enforced precondition that tests the validity of StoryPageElementType. Adds GSStoryPage::IsValidStoryPageElementType to the API. --- src/script/api/game_changelog.hpp | 1 + src/script/api/script_story_page.cpp | 6 ++++++ src/script/api/script_story_page.hpp | 8 ++++++++ 3 files changed, 15 insertions(+) diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp index 570e8c589b..241b955304 100644 --- a/src/script/api/game_changelog.hpp +++ b/src/script/api/game_changelog.hpp @@ -81,6 +81,7 @@ * \li GSGoal::SetDestination * \li GSIndustry::GetProductionLevel * \li GSIndustry::SetProductionLevel + * \li GSStoryPage::IsValidStoryPageElementType * * API removals: * \li GSError::ERR_PRECONDITION_TOO_MANY_PARAMETERS, that error is never returned anymore. diff --git a/src/script/api/script_story_page.cpp b/src/script/api/script_story_page.cpp index 87a46427eb..b99c703aa1 100644 --- a/src/script/api/script_story_page.cpp +++ b/src/script/api/script_story_page.cpp @@ -38,6 +38,11 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) return ::StoryPageElement::IsValidID(story_page_element_id); } +/* static */ bool ScriptStoryPage::IsValidStoryPageElementType(StoryPageElementType type) +{ + return type == SPET_TEXT || type == SPET_LOCATION || type == SPET_GOAL || type == SPET_BUTTON_PUSH || type == SPET_BUTTON_TILE || type == SPET_BUTTON_VEHICLE; +} + /* static */ ScriptStoryPage::StoryPageID ScriptStoryPage::New(ScriptCompany::CompanyID company, Text *title) { CCountedPtr counter(title); @@ -63,6 +68,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) EnforceDeityMode(STORY_PAGE_ELEMENT_INVALID); EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, IsValidStoryPage(story_page_id)); + EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, IsValidStoryPageElementType(type)); std::string encoded_text; if (StoryPageElementTypeRequiresText(btype)) { EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, text != nullptr); diff --git a/src/script/api/script_story_page.hpp b/src/script/api/script_story_page.hpp index c51c4c9363..edebc0bf1c 100644 --- a/src/script/api/script_story_page.hpp +++ b/src/script/api/script_story_page.hpp @@ -179,6 +179,13 @@ public: */ static bool IsValidStoryPageElement(StoryPageElementID story_page_element_id); + /** + * Check whether this is a valid story page element type. + * @param type The StoryPageElementType to check. + * @return True if and only if this story page element type is valid. + */ + static bool IsValidStoryPageElementType(StoryPageElementType type); + /** * Create a new story page. * @param company The company to create the story page for, or ScriptCompany::COMPANY_INVALID for all. @@ -202,6 +209,7 @@ public: * @return The new StoryPageElementID, or STORY_PAGE_ELEMENT_INVALID if it failed. * @pre ScriptCompanyMode::IsDeity(). * @pre IsValidStoryPage(story_page). + * @pre IsValidStoryPageElementType(type). * @pre (type != SPET_TEXT && type != SPET_LOCATION) || (text != null && len(text) != 0). * @pre type != SPET_LOCATION || ScriptMap::IsValidTile(reference). * @pre type != SPET_GOAL || ScriptGoal::IsValidGoal(reference).