1
0
Fork 0

Fix: crashes to desktop from game scripts when companies disappear

When a game script is in company mode, it pretends to be another company. When
that company disappear (bankruptcy/merger), the game script still uses that
company and it keeps calling functions as if it is that company.

For example, ScriptEngine::IsBuildable internally dereferences Company without
checks, causing a null dereference for any ScriptEngine function when called
from a company scope of a company that has disappeared.

Guard against this by extending the ScriptCompanyScope::IsValid check to also
check for the company still being active.
pull/10559/head
Rubidium 2023-03-02 21:27:30 +01:00 committed by rubidium42
parent 717f79ff22
commit 1e4a89177e
3 changed files with 3 additions and 3 deletions

View File

@ -29,7 +29,7 @@ ScriptCompanyMode::~ScriptCompanyMode()
/* static */ bool ScriptCompanyMode::IsValid() /* static */ bool ScriptCompanyMode::IsValid()
{ {
return ScriptObject::GetCompany() != OWNER_DEITY; return ::Company::IsValidID(ScriptObject::GetCompany());
} }
/* static */ bool ScriptCompanyMode::IsDeity() /* static */ bool ScriptCompanyMode::IsDeity()

View File

@ -50,7 +50,7 @@ public:
/** /**
* Check whether a company mode is valid. In other words, are commands * Check whether a company mode is valid. In other words, are commands
* being executed under some company. * being executed under some company and does the company still exist?
* @return true When a company mode is valid. * @return true When a company mode is valid.
* @post !ScriptCompanyMode::IsDeity(). * @post !ScriptCompanyMode::IsDeity().
*/ */

View File

@ -253,7 +253,7 @@ std::tuple<bool, bool, bool> ScriptObject::DoCommandPrep()
bool networking = _networking && !_generating_world; bool networking = _networking && !_generating_world;
if (ScriptCompanyMode::IsValid() && !::Company::IsValidID(ScriptObject::GetCompany())) { if (!ScriptCompanyMode::IsDeity() && !ScriptCompanyMode::IsValid()) {
ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY); ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY);
return { true, estimate_only, networking }; return { true, estimate_only, networking };
} }