Skip to content

Commit ddfaeca

Browse files
committed
2.3: Fix an invalid pointer dereferencing issue in the script events system.
Closes #2300.
1 parent 6e716e4 commit ddfaeca

File tree

2 files changed

+70
-61
lines changed

2 files changed

+70
-61
lines changed

Diff for: lib/script/event.c

+69-60
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ static ACTIVE_TRIGGER *psAddedTriggers = NULL;
4343

4444
/** The trigger which is currently firing */
4545
static ACTIVE_TRIGGER *psFiringTrigger = NULL;
46-
static BOOL triggerChanged;
4746
static UDWORD updateTime;
4847

4948
/** The currently allocated contexts */
@@ -98,6 +97,15 @@ static void eventAddTrigger(ACTIVE_TRIGGER *psTrigger);
9897
// Free up a trigger
9998
static void eventFreeTrigger(ACTIVE_TRIGGER *psTrigger);
10099

100+
// Remove triggers marked for deletion
101+
static void eventPruneList(ACTIVE_TRIGGER **psList);
102+
static void eventPruneLists(void)
103+
{
104+
eventPruneList(&psTrigList);
105+
eventPruneList(&psCallbackList);
106+
eventPruneList(&psAddedTriggers);
107+
}
108+
101109
//resets the event timer - updateTime
102110
void eventTimeReset(UDWORD initTime)
103111
{
@@ -834,10 +842,8 @@ static BOOL eventInitTrigger(ACTIVE_TRIGGER **ppsTrigger, SCRIPT_CONTEXT *psCont
834842
TRIGGER_DATA *psTrigData;
835843
UDWORD testTime;
836844

837-
ASSERT( event < psContext->psCode->numEvents,
838-
"eventAddTrigger: Event out of range" );
839-
ASSERT( trigger < psContext->psCode->numTriggers,
840-
"eventAddTrigger: Trigger out of range" );
845+
ASSERT( event < psContext->psCode->numEvents, "Event out of range" );
846+
ASSERT( trigger < psContext->psCode->numTriggers, "Trigger out of range" );
841847
if (trigger == -1)
842848
{
843849
return false;
@@ -861,6 +867,7 @@ static BOOL eventInitTrigger(ACTIVE_TRIGGER **ppsTrigger, SCRIPT_CONTEXT *psCont
861867
psNewTrig->type = (SWORD)psTrigData->type;
862868
psNewTrig->event = (UWORD)event;
863869
psNewTrig->offset = 0;
870+
psNewTrig->deactivated = false;
864871

865872
*ppsTrigger = psNewTrig;
866873

@@ -897,6 +904,7 @@ BOOL eventLoadTrigger(UDWORD time, SCRIPT_CONTEXT *psContext,
897904
psNewTrig->type = (SWORD)type;
898905
psNewTrig->event = (UWORD)event;
899906
psNewTrig->offset = (UWORD)offset;
907+
psNewTrig->deactivated = false;
900908

901909
eventAddTrigger(psNewTrig);
902910

@@ -947,13 +955,14 @@ BOOL eventAddPauseTrigger(SCRIPT_CONTEXT *psContext, UDWORD event, UDWORD offset
947955
psNewTrig->type = TR_PAUSE;
948956
psNewTrig->event = (UWORD)event;
949957
psNewTrig->offset = (UWORD)offset;
958+
psNewTrig->deactivated = false;
950959

951960
// store the new trigger
952961
psNewTrig->psNext = psAddedTriggers;
953962
psAddedTriggers = psNewTrig;
954963

955-
// tell the event system the trigger has been changed
956-
triggerChanged = true;
964+
// mark the trigger for deletion
965+
psFiringTrigger->deactivated = true;
957966

958967
return true;
959968
}
@@ -1041,23 +1050,22 @@ void eventFireCallbackTrigger(TRIGGER_TYPE callback)
10411050
psPrev->psNext = psNext;
10421051
}
10431052

1044-
triggerChanged = false;
10451053
psFiringTrigger = psCurr;
1046-
if (!interpRunScript(psCurr->psContext, IRT_EVENT, psCurr->event, psCurr->offset)) // this could set triggerChanged
1054+
if (!interpRunScript(psCurr->psContext, IRT_EVENT, psCurr->event, psCurr->offset)) // this could set psCurr->deactivated
10471055
{
10481056
ASSERT(false, "eventFireCallbackTrigger: event %s: code failed",
10491057
eventGetEventID(psCurr->psContext->psCode, psCurr->event));
10501058
}
1051-
if (triggerChanged)
1059+
if (psCurr->deactivated)
10521060
{
10531061
// don't need to add the trigger again - just free it
10541062
eventFreeTrigger(psCurr);
10551063
}
10561064
else
10571065
{
10581066
// make sure the trigger goes back into the system
1059-
psFiringTrigger->psNext = psAddedTriggers;
1060-
psAddedTriggers = psFiringTrigger;
1067+
psCurr->psNext = psAddedTriggers;
1068+
psAddedTriggers = psCurr;
10611069
}
10621070
}
10631071
else
@@ -1071,6 +1079,9 @@ void eventFireCallbackTrigger(TRIGGER_TYPE callback)
10711079
}
10721080
}
10731081

1082+
// Delete marked triggers now
1083+
eventPruneLists();
1084+
10741085
// Now add all the new triggers
10751086
for(psCurr = psAddedTriggers; psCurr; psCurr=psNext)
10761087
{
@@ -1089,7 +1100,7 @@ static BOOL eventFireTrigger(ACTIVE_TRIGGER *psTrigger)
10891100
INTERP_VAL sResult;
10901101

10911102
fired = false;
1092-
1103+
psFiringTrigger = psTrigger;
10931104

10941105
// If this is a code trigger see if it fires
10951106
if (psTrigger->type == TR_CODE)
@@ -1154,15 +1165,10 @@ void eventProcessTriggers(UDWORD currTime)
11541165
psCurr = psTrigList;
11551166
psTrigList = psTrigList->psNext;
11561167

1157-
// Store the trigger so that I can tell if the event changes
1158-
// the trigger assigned to it
1159-
psFiringTrigger = psCurr;
1160-
triggerChanged = false;
1161-
11621168
// Run the trigger
1163-
if (eventFireTrigger(psCurr)) // This might set triggerChanged
1169+
if (eventFireTrigger(psCurr)) // This might mark the trigger for deletion
11641170
{
1165-
if (triggerChanged || psCurr->type == TR_WAIT)
1171+
if (psCurr->deactivated || psCurr->type == TR_WAIT)
11661172
{
11671173
// remove the trigger
11681174
eventFreeTrigger(psCurr);
@@ -1195,6 +1201,9 @@ void eventProcessTriggers(UDWORD currTime)
11951201
}
11961202
}
11971203

1204+
// Delete marked triggers now
1205+
eventPruneLists();
1206+
11981207
// Now add all the new triggers
11991208
for(psCurr = psAddedTriggers; psCurr; psCurr=psNext)
12001209
{
@@ -1205,56 +1214,56 @@ void eventProcessTriggers(UDWORD currTime)
12051214
psAddedTriggers = NULL;
12061215
}
12071216

1208-
1209-
// remove a trigger from a list
1210-
static void eventRemoveTriggerFromList(ACTIVE_TRIGGER **ppsList,
1211-
SCRIPT_CONTEXT *psContext,
1212-
SDWORD event, SDWORD *pTrigger)
1217+
// remove all marked triggers
1218+
static void eventPruneList(ACTIVE_TRIGGER **ppsList)
12131219
{
1214-
ACTIVE_TRIGGER *psCurr, *psPrev=NULL;
1220+
ACTIVE_TRIGGER **ppsCurr = ppsList, *psTemp;
12151221

1216-
if (((*ppsList) != NULL) &&
1217-
(*ppsList)->event == event &&
1218-
(*ppsList)->psContext == psContext)
1222+
while (*ppsCurr)
12191223
{
1220-
if ((*ppsList)->type == TR_PAUSE)
1224+
if ((*ppsCurr)->deactivated)
12211225
{
1222-
// pause trigger, don't remove it,
1223-
// just note the type for when the pause finishes
1224-
(*ppsList)->trigger = (SWORD)*pTrigger;
1225-
*pTrigger = -1;
1226+
psTemp = (*ppsCurr)->psNext;
1227+
free(*ppsCurr);
1228+
*ppsCurr = psTemp;
12261229
}
12271230
else
12281231
{
1229-
psCurr = *ppsList;
1230-
*ppsList = (*ppsList)->psNext;
1231-
free(psCurr);
1232+
ppsCurr = &(*ppsCurr)->psNext;
12321233
}
12331234
}
1234-
else
1235+
}
1236+
1237+
// Mark a trigger for removal from a list
1238+
static void eventMarkTriggerInList(ACTIVE_TRIGGER **ppsList,
1239+
SCRIPT_CONTEXT *psContext,
1240+
SDWORD event, SDWORD *pTrigger)
1241+
{
1242+
ACTIVE_TRIGGER **ppsCurr;
1243+
1244+
for (ppsCurr = ppsList;; ppsCurr = &(*ppsCurr)->psNext)
12351245
{
1236-
for(psCurr=*ppsList; psCurr; psCurr=psCurr->psNext)
1237-
{
1238-
if (psCurr->event == event &&
1239-
psCurr->psContext == psContext)
1240-
{
1241-
break;
1242-
}
1243-
psPrev = psCurr;
1244-
}
1245-
if (psCurr && psCurr->type == TR_PAUSE)
1246+
if (!(*ppsCurr))
12461247
{
1247-
// pause trigger, don't remove it,
1248-
// just note the type for when the pause finishes
1249-
psCurr->trigger = (SWORD)*pTrigger;
1250-
*pTrigger = -1;
1248+
return;
12511249
}
1252-
else if (psCurr)
1250+
else if ((*ppsCurr)->event == event &&
1251+
(*ppsCurr)->psContext == psContext)
12531252
{
1254-
psPrev->psNext = psCurr->psNext;
1255-
free(psCurr);
1253+
break;
12561254
}
12571255
}
1256+
if ((*ppsCurr)->type == TR_PAUSE)
1257+
{
1258+
// pause trigger, don't remove it,
1259+
// just note the type for when the pause finishes
1260+
(*ppsCurr)->trigger = (SWORD)*pTrigger;
1261+
*pTrigger = -1;
1262+
}
1263+
else
1264+
{
1265+
(*ppsCurr)->deactivated = true;
1266+
}
12581267
}
12591268

12601269

@@ -1281,14 +1290,14 @@ BOOL eventSetTrigger(void)
12811290
psContext = psFiringTrigger->psContext;
12821291
if (psFiringTrigger->event == event)
12831292
{
1284-
triggerChanged = true;
1293+
psFiringTrigger->deactivated = true;
12851294
}
12861295
else
12871296
{
1288-
// Remove any old trigger from the list
1289-
eventRemoveTriggerFromList(&psTrigList, psContext, event, &trigger);
1290-
eventRemoveTriggerFromList(&psCallbackList, psContext, event, &trigger);
1291-
eventRemoveTriggerFromList(&psAddedTriggers, psContext, event, &trigger);
1297+
// Mark the old trigger in the lists
1298+
eventMarkTriggerInList(&psTrigList, psContext, event, &trigger);
1299+
eventMarkTriggerInList(&psCallbackList, psContext, event, &trigger);
1300+
eventMarkTriggerInList(&psAddedTriggers, psContext, event, &trigger);
12921301
}
12931302

12941303
// Create a new trigger if necessary

Diff for: lib/script/event.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ typedef struct _active_trigger
8383
SWORD trigger;
8484
UWORD event;
8585
UWORD offset;
86-
86+
BOOL deactivated; // Whether the trigger is marked for deletion
8787
struct _active_trigger *psNext;
8888
} ACTIVE_TRIGGER;
8989

0 commit comments

Comments
 (0)