diff options
author | rubidium <rubidium@openttd.org> | 2013-05-12 13:12:55 +0000 |
---|---|---|
committer | rubidium <rubidium@openttd.org> | 2013-05-12 13:12:55 +0000 |
commit | 001fdc3682bd514b31f7c3a0a916720af056b00b (patch) | |
tree | 1093ba1956b68079deaba48c0d65b0496b9ddfd3 | |
parent | 5931faeff6afd9c9a76410aa756f3dc4effed29d (diff) | |
download | openttd-001fdc3682bd514b31f7c3a0a916720af056b00b.tar.xz |
(svn r25236) -Fix [FS#5547]: crash when AI is executing a command as it is bankrupted (removed from the game)
The command is placed in a queue for processing before it is bankrupted, after that the command
is executed. This command yields a failure because the company does not exist, but then it still
needs to call the callback. This callback tries to access the AI's virtual machine without any
checks, so it starts to read a just freed pointer and segfaults.
-rw-r--r-- | src/ai/ai_instance.cpp | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/src/ai/ai_instance.cpp b/src/ai/ai_instance.cpp index 4d808e055..f109a0926 100644 --- a/src/ai/ai_instance.cpp +++ b/src/ai/ai_instance.cpp @@ -238,8 +238,17 @@ ScriptInfo *AIInstance::FindLibrary(const char *library, int version) */ void CcAI(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2) { - Company::Get(_current_company)->ai_instance->DoCommandCallback(result, tile, p1, p2); - Company::Get(_current_company)->ai_instance->Continue(); + /* + * The company might not exist anymore. Check for this. + * The command checks are not useful since this callback + * is also called when the command fails, which is does + * when the company does not exist anymore. + */ + const Company *c = Company::GetIfValid(_current_company); + if (c == NULL || c->ai_instance == NULL) return; + + c->ai_instance->DoCommandCallback(result, tile, p1, p2); + c->ai_instance->Continue(); } CommandCallback *AIInstance::GetDoCommandCallback() |