Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit d8700b7

Browse files
author
Monte Goulding
committed
[[ Bug 17180 ]] Ensure objects aren't executing script before delete
1 parent efea5a9 commit d8700b7

24 files changed

+285
-121
lines changed

docs/notes/bugfix-17180.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Ensure deleted objects executing scripts can not be deleted

engine/src/aclip.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,16 @@ void MCAudioClip::timer(MCNameRef mptr, MCParameter *params)
203203
}
204204
}
205205

206-
Boolean MCAudioClip::del()
206+
Boolean MCAudioClip::del(bool p_check_flag)
207207
{
208-
getstack()->removeaclip(this);
208+
if (!isdeletable(p_check_flag))
209+
return False;
210+
211+
getstack()->removeaclip(this);
209212

210213
// MCObject now does things on del(), so we must make sure we finish by
211214
// calling its implementation.
212-
return MCObject::del();
215+
return MCObject::del(p_check_flag);
213216
}
214217

215218
void MCAudioClip::paste(void)

engine/src/aclip.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class MCAudioClip : public MCObject
7979

8080
virtual void timer(MCNameRef mptr, MCParameter *params);
8181

82-
virtual Boolean del();
82+
virtual Boolean del(bool p_check_flag);
8383
virtual void paste(void);
8484

8585
// MCAudioClip functions

engine/src/card.cpp

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,30 +1088,43 @@ void MCCard::timer(MCNameRef mptr, MCParameter *params)
10881088
MCObject::timer(mptr, params);
10891089
}
10901090

1091-
Boolean MCCard::del()
1091+
bool MCCard::isdeletable(bool p_check_flag)
10921092
{
1093-
if (parent == NULL || scriptdepth != 0 || getstack()->islocked()
1094-
|| getstack()->isediting() || flags & F_C_CANT_DELETE)
1095-
{
1096-
MCeerror->add(EE_OBJECT_CANTREMOVE, 0, 0);
1097-
return False;
1098-
}
1099-
clean();
1100-
if (objptrs != NULL)
1101-
{
1102-
MCObjptr *optr = objptrs;
1103-
do
1104-
{
1105-
if (optr->getref()->getscriptdepth() != 0)
1106-
{
1107-
MCeerror->add
1108-
(EE_OBJECT_CANTREMOVE, 0, 0);
1109-
return False;
1110-
}
1111-
optr = optr->next();
1112-
}
1113-
while (optr != objptrs);
1114-
}
1093+
if (parent == NULL || scriptdepth != 0 ||
1094+
(p_check_flag && getflag(F_C_CANT_DELETE)) ||
1095+
getstack() -> isediting())
1096+
{
1097+
MCAutoValueRef t_long_name;
1098+
getnameproperty(P_LONG_NAME, 0, &t_long_name);
1099+
MCeerror->add(EE_OBJECT_CANTREMOVE, 0, 0, *t_long_name);
1100+
return false;
1101+
}
1102+
1103+
if (objptrs != NULL)
1104+
{
1105+
MCObjptr *t_object_ptr = objptrs;
1106+
do
1107+
{
1108+
// if it's a background group then don't check flags
1109+
if (!((t_object_ptr->getref()->gettype() == CT_GROUP && static_cast<MCGroup *>(t_object_ptr->getref())->isshared())) &&
1110+
t_object_ptr->getref()->isdeletable(true))
1111+
return false;
1112+
1113+
t_object_ptr = t_object_ptr->next();
1114+
}
1115+
while (t_object_ptr != objptrs);
1116+
}
1117+
1118+
return true;
1119+
}
1120+
1121+
Boolean MCCard::del(bool p_check_flag)
1122+
{
1123+
if (!isdeletable(p_check_flag))
1124+
return False;
1125+
1126+
clean();
1127+
11151128
MCselected->remove(this);
11161129

11171130
// MW-2008-10-31: [[ ParentScripts ]] Make sure we close the controls
@@ -1151,7 +1164,7 @@ Boolean MCCard::del()
11511164

11521165
// MCObject now does things on del(), so we must make sure we finish by
11531166
// calling its implementation.
1154-
return MCObject::del();
1167+
return MCObject::del(p_check_flag);
11551168
}
11561169

11571170
struct UpdateDataIdsVisitor: public MCObjectVisitor

engine/src/card.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class MCCard : public MCObject
8383
virtual Boolean doubleup(uint2 which);
8484
virtual void timer(MCNameRef mptr, MCParameter *params);
8585

86-
virtual Boolean del();
86+
virtual Boolean del(bool p_check_flag);
8787
virtual void paste(void);
8888

8989
virtual Exec_stat handle(Handler_type, MCNameRef, MCParameter *, MCObject *pass_from);
@@ -107,7 +107,9 @@ class MCCard : public MCObject
107107

108108
virtual void scheduledelete(bool p_is_child);
109109

110-
void draw(MCDC *dc, const MCRectangle &dirty, bool p_isolated);
110+
virtual bool isdeletable(bool p_check_flag);
111+
112+
void draw(MCDC *dc, const MCRectangle &dirty, bool p_isolated);
111113

112114
MCObject *hittest(int32_t x, int32_t y);
113115

engine/src/control.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -450,14 +450,12 @@ void MCControl::deselect()
450450
}
451451
}
452452

453-
Boolean MCControl::del()
453+
Boolean MCControl::del(bool p_check_flag)
454454
{
455-
if (parent == NULL || scriptdepth != 0 || getstack()->islocked())
456-
{
457-
MCeerror->add(EE_OBJECT_CANTREMOVE, 0, 0);
458-
return False;
459-
}
460-
switch (gettype())
455+
if (!isdeletable(p_check_flag))
456+
return False;
457+
458+
switch (gettype())
461459
{
462460
case CT_BUTTON:
463461
message(MCM_delete_button);
@@ -529,7 +527,7 @@ Boolean MCControl::del()
529527

530528
// MCObject now does things on del(), so we must make sure we finish by
531529
// calling its implementation.
532-
return MCObject::del();
530+
return MCObject::del(p_check_flag);
533531
}
534532

535533
void MCControl::paste(void)
@@ -591,7 +589,7 @@ void MCControl::undo(Ustruct *us)
591589
}
592590
return;
593591
case UT_REPLACE:
594-
del();
592+
del(true);
595593
us->type = UT_DELETE;
596594
return;
597595
default:

engine/src/exec-engine.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -897,17 +897,20 @@ void MCEngineExecQuit(MCExecContext& ctxt, integer_t p_retcode)
897897
{
898898
// MW-2011-06-22: [[ SERVER ]] Don't send messages in server-mode.
899899
#ifndef _SERVER
900-
switch(MCdefaultstackptr->getcard()->message(MCM_shut_down_request))
901-
{
902-
case ES_PASS:
903-
case ES_NOT_HANDLED:
904-
break;
905-
default:
906-
return;
907-
}
908-
// IM-2013-05-01: [[ BZ 10586 ]] remove #ifdefs so this message is sent
909-
// here on Android in the same place as (almost) everything else
910-
MCdefaultstackptr->getcard()->message(MCM_shut_down);
900+
if (MCdefaultstackptr != nil && !MCdefaultstackptr->getstate(CS_DELETE_STACK))
901+
{
902+
switch(MCdefaultstackptr->getcard()->message(MCM_shut_down_request))
903+
{
904+
case ES_PASS:
905+
case ES_NOT_HANDLED:
906+
break;
907+
default:
908+
return;
909+
}
910+
// IM-2013-05-01: [[ BZ 10586 ]] remove #ifdefs so this message is sent
911+
// here on Android in the same place as (almost) everything else
912+
MCdefaultstackptr->getcard()->message(MCM_shut_down);
913+
}
911914
#endif
912915

913916
MCretcode = p_retcode;

engine/src/exec-interface.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1953,17 +1953,16 @@ static void MCInterfaceRevertStack(MCExecContext& ctxt, MCStack *p_stack)
19531953
if (!MCNameCreate(*t_filename, &t_name))
19541954
return;
19551955

1956-
Boolean oldlock = MClockmessages;
1957-
MClockmessages = True;
1958-
MCerrorlock++;
1959-
if (p_stack->del())
1956+
// we don't want to check flags on stack revert
1957+
if (p_stack->del(false))
1958+
{
19601959
p_stack -> scheduledelete();
1961-
MCerrorlock--;
1962-
MClockmessages = oldlock;
1963-
1964-
p_stack = MCdispatcher->findstackname(*t_name);
1965-
if (p_stack != NULL)
1966-
p_stack->openrect(oldrect, oldmode, NULL, WP_DEFAULT, OP_NONE);
1960+
p_stack = MCdispatcher->findstackname(*t_name);
1961+
if (p_stack != NULL)
1962+
p_stack->openrect(oldrect, oldmode, NULL, WP_DEFAULT, OP_NONE);
1963+
}
1964+
else
1965+
ctxt . Throw();
19671966
}
19681967

19691968
void MCInterfaceExecRevert(MCExecContext& ctxt)
@@ -2226,7 +2225,7 @@ void MCInterfaceExecDeleteObjects(MCExecContext& ctxt, MCObjectPtr *p_objects, u
22262225
{
22272226
for(uindex_t i = 0; i < p_object_count; i++)
22282227
{
2229-
if (!p_objects[i] . object -> del())
2228+
if (!p_objects[i] . object -> del(true))
22302229
{
22312230
ctxt . LegacyThrow(EE_CHUNK_CANTDELETEOBJECT);
22322231
return;

engine/src/exec-pasteboard.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,7 @@ void MCPasteboardProcessToClipboard(MCExecContext& ctxt, MCObjectPtr *p_targets,
10151015
{
10161016
for(uint4 i = 0; i < p_object_count; ++i)
10171017
{
1018-
if (p_targets[i] . object -> del())
1018+
if (p_targets[i] . object -> del(true))
10191019
{
10201020
if (p_targets[i] . object -> gettype() == CT_STACK)
10211021
MCtodestroy -> remove(static_cast<MCStack *>(p_targets[i] . object));

engine/src/group.cpp

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -981,31 +981,40 @@ void MCGroup::applyrect(const MCRectangle &nrect)
981981
}
982982
}
983983

984-
Boolean MCGroup::del()
984+
bool MCGroup::isdeletable(bool p_check_flag)
985985
{
986-
if (flags & F_G_CANT_DELETE)
987-
{
988-
MCeerror->add
989-
(EE_OBJECT_CANTREMOVE, 0, 0);
990-
return False;
991-
}
992-
if (controls != NULL)
993-
{
994-
MCControl *cptr = controls;
995-
do
996-
{
997-
if (cptr->getscriptdepth() != 0)
998-
{
999-
MCeerror->add
1000-
(EE_OBJECT_CANTREMOVE, 0, 0);
1001-
return False;
1002-
}
1003-
cptr = cptr->next();
1004-
}
1005-
while (cptr != controls);
1006-
}
1007-
rect = getcard()->getrect();
1008-
return MCControl::del();
986+
if (parent == NULL || scriptdepth != 0 ||
987+
(p_check_flag && getflag(F_G_CANT_DELETE)))
988+
{
989+
MCAutoValueRef t_long_name;
990+
getnameproperty(P_LONG_NAME, 0, &t_long_name);
991+
MCeerror->add(EE_OBJECT_CANTREMOVE, 0, 0, *t_long_name);
992+
return false;
993+
}
994+
995+
if (controls != NULL)
996+
{
997+
MCControl *t_control = controls;
998+
do
999+
{
1000+
if (!t_control->isdeletable(p_check_flag))
1001+
return false;
1002+
1003+
t_control = t_control->next();
1004+
}
1005+
while (t_control != controls);
1006+
}
1007+
1008+
return true;
1009+
}
1010+
1011+
Boolean MCGroup::del(bool p_check_flag)
1012+
{
1013+
if (!isdeletable(p_check_flag))
1014+
return False;
1015+
1016+
rect = getcard()->getrect();
1017+
return MCControl::del(p_check_flag);
10091018
}
10101019

10111020
void MCGroup::recompute()

0 commit comments

Comments
 (0)