summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2013-05-12 13:12:55 +0000
committerrubidium <rubidium@openttd.org>2013-05-12 13:12:55 +0000
commit001fdc3682bd514b31f7c3a0a916720af056b00b (patch)
tree1093ba1956b68079deaba48c0d65b0496b9ddfd3
parent5931faeff6afd9c9a76410aa756f3dc4effed29d (diff)
downloadopenttd-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.cpp13
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()