Fix crash when dialog speaker destroys itself

See #162
This commit is contained in:
Alexander Batalov 2022-10-03 15:04:30 +03:00
parent 56d27400ac
commit fe4c125474
2 changed files with 17 additions and 11 deletions

View File

@ -659,9 +659,9 @@ bool _gdialogActive()
// gdialogEnter // gdialogEnter
// 0x444D3C // 0x444D3C
void gameDialogEnter(Object* a1, int a2) void gameDialogEnter(Object* speaker, int a2)
{ {
if (a1 == NULL) { if (speaker == NULL) {
debugPrint("\nError: gdialogEnter: target was NULL!"); debugPrint("\nError: gdialogEnter: target was NULL!");
return; return;
} }
@ -672,14 +672,14 @@ void gameDialogEnter(Object* a1, int a2)
return; return;
} }
if (a1->sid == -1) { if (speaker->sid == -1) {
return; return;
} }
if (PID_TYPE(a1->pid) != OBJ_TYPE_ITEM && SID_TYPE(a1->sid) != SCRIPT_TYPE_SPATIAL) { if (PID_TYPE(speaker->pid) != OBJ_TYPE_ITEM && SID_TYPE(speaker->sid) != SCRIPT_TYPE_SPATIAL) {
MessageListItem messageListItem; MessageListItem messageListItem;
int rc = _action_can_talk_to(gDude, a1); int rc = _action_can_talk_to(gDude, speaker);
if (rc == -1) { if (rc == -1) {
// You can't see there. // You can't see there.
messageListItem.num = 660; messageListItem.num = 660;
@ -717,17 +717,23 @@ void gameDialogEnter(Object* a1, int a2)
isoDisable(); isoDisable();
_dialog_state_fix = 1; _dialog_state_fix = 1;
gGameDialogSpeaker = a1; gGameDialogSpeaker = speaker;
gGameDialogSpeakerIsPartyMember = objectIsPartyMember(a1); gGameDialogSpeakerIsPartyMember = objectIsPartyMember(speaker);
_dialogue_just_started = 1; _dialogue_just_started = 1;
if (a1->sid != -1) { // CE: Obtain and keep SID in a separate variable. This is needed because in
scriptExecProc(a1->sid, SCRIPT_PROC_TALK); // rare circumstates the speaker can destroy itself. So after executing it's
// script |speaker| can point to freed memory. Dereferencing such pointer
// can lead to crash depending on the environment (confirmed on Android and
// MSVC debug builds).
int sid = speaker->sid;
if (sid != -1) {
scriptExecProc(speaker->sid, SCRIPT_PROC_TALK);
} }
Script* script; Script* script;
if (scriptGetScript(a1->sid, &script) == -1) { if (scriptGetScript(sid, &script) == -1) {
gameMouseObjectsShow(); gameMouseObjectsShow();
isoEnable(); isoEnable();
scriptsExecMapUpdateProc(); scriptsExecMapUpdateProc();

View File

@ -15,7 +15,7 @@ int gameDialogInit();
int gameDialogReset(); int gameDialogReset();
int gameDialogExit(); int gameDialogExit();
bool _gdialogActive(); bool _gdialogActive();
void gameDialogEnter(Object* a1, int a2); void gameDialogEnter(Object* speaker, int a2);
void _gdialogSystemEnter(); void _gdialogSystemEnter();
void gameDialogStartLips(const char* a1); void gameDialogStartLips(const char* a1);
int gameDialogEnable(); int gameDialogEnable();