Codechange: [Script] Don't expose static buffers outside of ScriptText

pull/491/head
glx22 1 year ago committed by Loïc Guilloux
parent e735370318
commit 3559576166

@ -40,7 +40,7 @@
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
EnforcePrecondition(false, IsValidBaseStation(station_id));
EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText();
const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_STATION_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);

@ -48,7 +48,7 @@
CCountedPtr<Text> counter(name);
EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText();
const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_COMPANY_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);
@ -69,7 +69,7 @@
CCountedPtr<Text> counter(name);
EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText();
const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_PRESIDENT_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);

@ -42,7 +42,7 @@
* @param string The string that is checked.
*/
#define EnforcePreconditionEncodedText(returnval, string) \
if (StrEmpty(string)) { \
if (string.empty()) { \
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_FAILED); \
return returnval; \
}

@ -34,7 +34,7 @@
EnforcePrecondition(GOAL_INVALID, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(GOAL_INVALID, goal != nullptr);
const char *text = goal->GetEncodedText();
const std::string &text = goal->GetEncodedText();
EnforcePreconditionEncodedText(GOAL_INVALID, text);
EnforcePrecondition(GOAL_INVALID, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);
@ -71,9 +71,10 @@
EnforcePrecondition(false, IsValidGoal(goal_id));
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(false, goal != nullptr);
EnforcePrecondition(false, !StrEmpty(goal->GetEncodedText()));
const std::string &text = goal->GetEncodedText();
EnforcePreconditionEncodedText(false, text);
return ScriptObject::Command<CMD_SET_GOAL_TEXT>::Do(goal_id, goal->GetEncodedText());
return ScriptObject::Command<CMD_SET_GOAL_TEXT>::Do(goal_id, text);
}
/* static */ bool ScriptGoal::SetProgress(GoalID goal_id, Text *progress)
@ -83,12 +84,7 @@
EnforcePrecondition(false, IsValidGoal(goal_id));
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
/* Ensure null as used for empty string. */
if (progress != nullptr && StrEmpty(progress->GetEncodedText())) {
progress = nullptr;
}
return ScriptObject::Command<CMD_SET_GOAL_PROGRESS>::Do(goal_id, progress != nullptr ? std::string{ progress->GetEncodedText() } : std::string{});
return ScriptObject::Command<CMD_SET_GOAL_PROGRESS>::Do(goal_id, progress != nullptr ? progress->GetEncodedText() : std::string{});
}
/* static */ bool ScriptGoal::SetCompleted(GoalID goal_id, bool completed)
@ -114,7 +110,7 @@
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(false, question != nullptr);
const char *text = question->GetEncodedText();
const std::string &text = question->GetEncodedText();
EnforcePreconditionEncodedText(false, text);
uint min_buttons = (type == QT_QUESTION ? 1 : 0);
EnforcePrecondition(false, CountBits(buttons) >= min_buttons && CountBits(buttons) <= 3);

@ -57,7 +57,7 @@
EnforcePrecondition(false, IsValidGroup(group_id));
EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText();
const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_GROUP_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);

@ -53,14 +53,9 @@
{
CCountedPtr<Text> counter(text);
const char *encoded_text = nullptr;
if (text != nullptr) {
encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_text);
}
EnforcePrecondition(false, IsValidIndustry(industry_id));
return ScriptObject::Command<CMD_INDUSTRY_SET_TEXT>::Do(industry_id, std::string{ encoded_text ? encoded_text : "" });
return ScriptObject::Command<CMD_INDUSTRY_SET_TEXT>::Do(industry_id, text != nullptr ? text->GetEncodedText() : std::string{});
}
/* static */ ScriptIndustry::CargoAcceptState ScriptIndustry::IsCargoAccepted(IndustryID industry_id, CargoID cargo_id)

@ -84,7 +84,7 @@ public:
/**
* Set the custom text of an industry, shown in the GUI.
* @param industry_id The industry to set the custom text of.
* @param text The text to set it to (can be either a raw string, or a ScriptText object). If null is passed, the text will be removed.
* @param text The text to set it to (can be either a raw string, or a ScriptText object). If null, or an empty string, is passed, the text will be removed.
* @pre IsValidIndustry(industry_id).
* @return True if the action succeeded.
* @api -ai

@ -32,11 +32,11 @@
EnforcePrecondition(LEAGUE_TABLE_INVALID, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(LEAGUE_TABLE_INVALID, title != nullptr);
const char *encoded_title = title->GetEncodedText();
const std::string &encoded_title = title->GetEncodedText();
EnforcePreconditionEncodedText(LEAGUE_TABLE_INVALID, encoded_title);
auto encoded_header = (header != nullptr ? std::string{ header->GetEncodedText() } : std::string{});
auto encoded_footer = (footer != nullptr ? std::string{ footer->GetEncodedText() } : std::string{});
const std::string &encoded_header = (header != nullptr ? header->GetEncodedText() : std::string{});
const std::string &encoded_footer = (footer != nullptr ? footer->GetEncodedText() : std::string{});
if (!ScriptObject::Command<CMD_CREATE_LEAGUE_TABLE>::Do(&ScriptInstance::DoCommandReturnLeagueTableID, encoded_title, encoded_header, encoded_footer)) return LEAGUE_TABLE_INVALID;
@ -63,12 +63,11 @@
if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, text != nullptr);
const char *encoded_text_ptr = text->GetEncodedText();
EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_text_ptr);
std::string encoded_text = encoded_text_ptr; // save into string so GetEncodedText can reuse the internal buffer
const std::string &encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_text);
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, score != nullptr);
const char *encoded_score = score->GetEncodedText();
const std::string &encoded_score = score->GetEncodedText();
EnforcePreconditionEncodedText(LEAGUE_TABLE_ELEMENT_INVALID, encoded_score);
EnforcePrecondition(LEAGUE_TABLE_ELEMENT_INVALID, IsValidLink(Link((::LinkType)link_type, link_target)));
@ -91,7 +90,7 @@
if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
EnforcePrecondition(false, text != nullptr);
const char *encoded_text = text->GetEncodedText();
const std::string &encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_text);
EnforcePrecondition(false, IsValidLink(Link((::LinkType)link_type, link_target)));
@ -107,7 +106,7 @@
EnforcePrecondition(false, IsValidLeagueTableElement(element));
EnforcePrecondition(false, score != nullptr);
const char *encoded_score = score->GetEncodedText();
const std::string &encoded_score = score->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_score);
return ScriptObject::Command<CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE>::Do(element, rating, encoded_score);

@ -25,7 +25,7 @@
CCountedPtr<Text> counter(text);
EnforcePrecondition(false, text != nullptr);
const char *encoded = text->GetEncodedText();
const std::string &encoded = text->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded);
EnforcePrecondition(false, type == NT_ECONOMY || type == NT_SUBSIDIES || type == NT_GENERAL);
EnforcePrecondition(false, company == ScriptCompany::COMPANY_INVALID || ScriptCompany::ResolveCompanyID(company) != ScriptCompany::COMPANY_INVALID);

@ -38,7 +38,7 @@
EnforcePrecondition(false, IsValidSign(sign_id));
EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText();
const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_SIGN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);
@ -73,7 +73,7 @@
EnforcePrecondition(INVALID_SIGN, ::IsValidTile(location));
EnforcePrecondition(INVALID_SIGN, name != nullptr);
const char *text = name->GetDecodedText();
const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(INVALID_SIGN, text);
EnforcePreconditionCustomError(INVALID_SIGN, ::Utf8StringLength(text) < MAX_LENGTH_SIGN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);

@ -49,7 +49,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
if (company == ScriptCompany::COMPANY_INVALID) c = INVALID_COMPANY;
if (!ScriptObject::Command<CMD_CREATE_STORY_PAGE>::Do(&ScriptInstance::DoCommandReturnStoryPageID,
(::CompanyID)c, title != nullptr ? std::string{ title->GetEncodedText() } : std::string{})) return STORY_PAGE_INVALID;
(::CompanyID)c, title != nullptr ? title->GetEncodedText() : std::string{})) return STORY_PAGE_INVALID;
/* In case of test-mode, we return StoryPageID 0 */
return (ScriptStoryPage::StoryPageID)0;
@ -63,7 +63,12 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, ScriptObject::GetCompany() == OWNER_DEITY);
EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, IsValidStoryPage(story_page_id));
EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, !StoryPageElementTypeRequiresText(btype) || (text != nullptr && !StrEmpty(text->GetEncodedText())));
std::string encoded_text;
if (StoryPageElementTypeRequiresText(btype)) {
EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, text != nullptr);
encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(STORY_PAGE_ELEMENT_INVALID, encoded_text);
}
EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, type != SPET_LOCATION || ::IsValidTile(reference));
EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, type != SPET_GOAL || ScriptGoal::IsValidGoal((ScriptGoal::GoalID)reference));
EnforcePrecondition(STORY_PAGE_ELEMENT_INVALID, type != SPET_GOAL || !(StoryPage::Get(story_page_id)->company == INVALID_COMPANY && Goal::Get(reference)->company != INVALID_COMPANY));
@ -90,7 +95,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
reftile,
(::StoryPageID)story_page_id, (::StoryPageElementType)type,
refid,
StoryPageElementTypeRequiresText(btype) ? std::string{ text->GetEncodedText() } : std::string{})) return STORY_PAGE_ELEMENT_INVALID;
encoded_text)) return STORY_PAGE_ELEMENT_INVALID;
/* In case of test-mode, we return StoryPageElementID 0 */
return (ScriptStoryPage::StoryPageElementID)0;
@ -107,7 +112,12 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
StoryPage *p = StoryPage::Get(pe->page);
::StoryPageElementType type = pe->type;
EnforcePrecondition(false, !StoryPageElementTypeRequiresText(type) || (text != nullptr && !StrEmpty(text->GetEncodedText())));
std::string encoded_text;
if (StoryPageElementTypeRequiresText(type)) {
EnforcePrecondition(false, text != nullptr);
encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_text);
}
EnforcePrecondition(false, type != ::SPET_LOCATION || ::IsValidTile(reference));
EnforcePrecondition(false, type != ::SPET_GOAL || ScriptGoal::IsValidGoal((ScriptGoal::GoalID)reference));
EnforcePrecondition(false, type != ::SPET_GOAL || !(p->company == INVALID_COMPANY && Goal::Get(reference)->company != INVALID_COMPANY));
@ -130,10 +140,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
NOT_REACHED();
}
return ScriptObject::Command<CMD_UPDATE_STORY_PAGE_ELEMENT>::Do(reftile,
story_page_element_id,
refid,
StoryPageElementTypeRequiresText(type) ? std::string{ text->GetEncodedText() } : std::string{});
return ScriptObject::Command<CMD_UPDATE_STORY_PAGE_ELEMENT>::Do(reftile, story_page_element_id, refid, encoded_text);
}
/* static */ uint32 ScriptStoryPage::GetPageSortValue(StoryPageID story_page_id)
@ -157,7 +164,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
EnforcePrecondition(false, IsValidStoryPage(story_page_id));
EnforcePrecondition(false, ScriptObject::GetCompany() == OWNER_DEITY);
return ScriptObject::Command<CMD_SET_STORY_PAGE_TITLE>::Do(story_page_id, title != nullptr ? std::string{ title->GetEncodedText() } : std::string{});
return ScriptObject::Command<CMD_SET_STORY_PAGE_TITLE>::Do(story_page_id, title != nullptr ? title->GetEncodedText() : std::string{});
}
/* static */ ScriptCompany::CompanyID ScriptStoryPage::GetCompany(StoryPageID story_page_id)

@ -18,15 +18,10 @@
#include "../../safeguards.h"
RawText::RawText(const char *text) : text(stredup(text))
RawText::RawText(const char *text) : text(text)
{
}
RawText::~RawText()
{
free(this->text);
}
ScriptText::ScriptText(HSQUIRRELVM vm) :
ZeroedMemoryAllocator()
@ -177,7 +172,7 @@ SQInteger ScriptText::_set(HSQUIRRELVM vm)
return this->_SetParam(k, vm);
}
const char *ScriptText::GetEncodedText()
const std::string ScriptText::GetEncodedText()
{
static char buf[1024];
int param_count = 0;
@ -208,7 +203,7 @@ char *ScriptText::_GetEncodedText(char *p, char *lastofp, int &param_count)
return p;
}
const char *Text::GetDecodedText()
const std::string Text::GetDecodedText()
{
const std::string &encoded_text = this->GetEncodedText();

@ -21,17 +21,17 @@ class Text : public ScriptObject {
public:
/**
* Convert a ScriptText to a normal string.
* @return A string (in a static buffer), or nullptr.
* @return A string.
* @api -all
*/
virtual const char *GetEncodedText() = 0;
virtual const std::string GetEncodedText() = 0;
/**
* Convert a #ScriptText into a decoded normal string.
* @return A string (in a static buffer), or nullptr.
* @return A string.
* @api -all
*/
const char *GetDecodedText();
const std::string GetDecodedText();
};
/**
@ -41,11 +41,10 @@ public:
class RawText : public Text {
public:
RawText(const char *text);
~RawText();
const char *GetEncodedText() override { return this->text; }
const std::string GetEncodedText() override { return this->text; }
private:
const char *text;
const std::string text;
};
/**
@ -125,7 +124,7 @@ public:
/**
* @api -all
*/
virtual const char *GetEncodedText();
virtual const std::string GetEncodedText();
private:
StringID string;

@ -44,29 +44,23 @@
{
CCountedPtr<Text> counter(name);
const char *text = nullptr;
EnforcePrecondition(false, IsValidTown(town_id));
std::string text;
if (name != nullptr) {
text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_TOWN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);
}
EnforcePrecondition(false, IsValidTown(town_id));
return ScriptObject::Command<CMD_RENAME_TOWN>::Do(town_id, text != nullptr ? std::string{ text } : std::string{});
return ScriptObject::Command<CMD_RENAME_TOWN>::Do(town_id, text);
}
/* static */ bool ScriptTown::SetText(TownID town_id, Text *text)
{
CCountedPtr<Text> counter(text);
const char *encoded_text = nullptr;
if (text != nullptr) {
encoded_text = text->GetEncodedText();
EnforcePreconditionEncodedText(false, encoded_text);
}
EnforcePrecondition(false, IsValidTown(town_id));
return ScriptObject::Command<CMD_TOWN_SET_TEXT>::Do(town_id, encoded_text != nullptr ? std::string{ encoded_text } : std::string{});
return ScriptObject::Command<CMD_TOWN_SET_TEXT>::Do(town_id, text != nullptr ? text->GetEncodedText() : std::string{});
}
/* static */ int32 ScriptTown::GetPopulation(TownID town_id)
@ -294,10 +288,9 @@
layout = (RoadLayout) (byte)_settings_game.economy.town_layout;
}
const char *text = nullptr;
std::string text;
if (name != nullptr) {
text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_TOWN_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);
}
uint32 townnameparts;
@ -306,7 +299,7 @@
return false;
}
return ScriptObject::Command<CMD_FOUND_TOWN>::Do(tile, (::TownSize)size, city, (::TownLayout)layout, false, townnameparts, text != nullptr ? std::string{ text } : std::string{});
return ScriptObject::Command<CMD_FOUND_TOWN>::Do(tile, (::TownSize)size, city, (::TownLayout)layout, false, townnameparts, text);
}
/* static */ ScriptTown::TownRating ScriptTown::GetRating(TownID town_id, ScriptCompany::CompanyID company_id)

@ -147,7 +147,7 @@ public:
/**
* Rename a town.
* @param town_id The town to rename
* @param name The new name of the town. If null is passed, the town name will be reset to the default name.
* @param name The new name of the town. If null, or an empty string, is passed, the town name will be reset to the default name.
* @pre IsValidTown(town_id).
* @return True if the action succeeded.
* @api -ai
@ -157,7 +157,7 @@ public:
/**
* Set the custom text of a town, shown in the GUI.
* @param town_id The town to set the custom text of.
* @param text The text to set it to (can be either a raw string, or a ScriptText object). If null is passed, the text will be removed.
* @param text The text to set it to (can be either a raw string, or a ScriptText object). If null, or an empty string, is passed, the text will be removed.
* @pre IsValidTown(town_id).
* @return True if the action succeeded.
* @api -ai
@ -401,7 +401,7 @@ public:
* @param size The town size of the new town.
* @param city True if the new town should be a city.
* @param layout The town layout of the new town.
* @param name The name of the new town. Pass null to use a random town name.
* @param name The name of the new town. Pass null, or an empty string, to use a random town name.
* @game @pre no company mode in scope || ScriptSettings.GetValue("economy.found_town") != 0.
* @ai @pre ScriptSettings.GetValue("economy.found_town") != 0.
* @game @pre no company mode in scope || size != TOWN_SIZE_LARGE.

@ -244,7 +244,7 @@
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
EnforcePrecondition(false, IsValidVehicle(vehicle_id));
EnforcePrecondition(false, name != nullptr);
const char *text = name->GetDecodedText();
const std::string &text = name->GetDecodedText();
EnforcePreconditionEncodedText(false, text);
EnforcePreconditionCustomError(false, ::Utf8StringLength(text) < MAX_LENGTH_VEHICLE_NAME_CHARS, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG);

Loading…
Cancel
Save