Duke3d: this is intended to fix an issue where CON VM errors within a CON_FOR loop could cause an infinite loop

This commit is contained in:
Richard C. Gobeille 2020-05-06 05:11:02 -07:00 committed by Christoph Oelckers
parent 8cf064b90c
commit c0160065e4

View file

@ -2727,14 +2727,6 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
dispatch(); dispatch();
} }
#define CON_FOR_ITERATION() \
do \
{ \
Gv_SetVar(returnVar, jj); \
insptr = pNext; \
VM_Execute(); \
} while (0)
vInstruction(CON_FOR): // special-purpose iteration vInstruction(CON_FOR): // special-purpose iteration
insptr++; insptr++;
{ {
@ -2745,6 +2737,13 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
auto const pEnd = insptr + *insptr; auto const pEnd = insptr + *insptr;
auto const pNext = ++insptr; auto const pNext = ++insptr;
auto execute = [&](int index) {
Gv_SetVar(returnVar, index);
insptr = pNext;
VM_Execute();
return !!(vm.flags & VM_RETURN);
};
switch (iterType) switch (iterType)
{ {
case ITER_ALLSPRITES: case ITER_ALLSPRITES:
@ -2752,7 +2751,9 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
{ {
if (sprite[jj].statnum == MAXSTATUS) if (sprite[jj].statnum == MAXSTATUS)
continue; continue;
CON_FOR_ITERATION();
if (execute(jj))
return;
} }
break; break;
@ -2760,7 +2761,8 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
for (native_t statNum = 0; statNum < MAXSTATUS; ++statNum) for (native_t statNum = 0; statNum < MAXSTATUS; ++statNum)
{ {
for (native_t kk, SPRITES_OF_STAT_SAFE(statNum, jj, kk)) for (native_t kk, SPRITES_OF_STAT_SAFE(statNum, jj, kk))
CON_FOR_ITERATION(); if (execute(jj))
return;
} }
break; break;
@ -2768,18 +2770,21 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
for (native_t sectNum = 0; sectNum < numsectors; ++sectNum) for (native_t sectNum = 0; sectNum < numsectors; ++sectNum)
{ {
for (native_t kk, SPRITES_OF_SECT_SAFE(sectNum, jj, kk)) for (native_t kk, SPRITES_OF_SECT_SAFE(sectNum, jj, kk))
CON_FOR_ITERATION(); if (execute(jj))
return;
} }
break; break;
case ITER_ALLSECTORS: case ITER_ALLSECTORS:
for (native_t jj = 0; jj < numsectors; ++jj) for (native_t jj = 0; jj < numsectors; ++jj)
CON_FOR_ITERATION(); if (execute(jj))
return;
break; break;
case ITER_ALLWALLS: case ITER_ALLWALLS:
for (native_t jj = 0; jj < numwalls; ++jj) for (native_t jj = 0; jj < numwalls; ++jj)
CON_FOR_ITERATION(); if (execute(jj))
return;
break; break;
case ITER_ACTIVELIGHTS: case ITER_ACTIVELIGHTS:
@ -2788,14 +2793,17 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
{ {
if (!prlights[jj].flags.active) if (!prlights[jj].flags.active)
continue; continue;
CON_FOR_ITERATION();
if (execute(jj))
return;
} }
#endif #endif
break; break;
case ITER_DRAWNSPRITES: case ITER_DRAWNSPRITES:
for (native_t jj = 0; jj < spritesortcnt; jj++) for (native_t jj = 0; jj < spritesortcnt; jj++)
CON_FOR_ITERATION(); if (execute(jj))
return;
break; break;
case ITER_SPRITESOFSECTOR: case ITER_SPRITESOFSECTOR:
@ -2803,7 +2811,8 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
goto badindex; goto badindex;
for (native_t kk, SPRITES_OF_SECT_SAFE(nIndex, jj, kk)) for (native_t kk, SPRITES_OF_SECT_SAFE(nIndex, jj, kk))
CON_FOR_ITERATION(); if (execute(jj))
return;
break; break;
case ITER_SPRITESOFSTATUS: case ITER_SPRITESOFSTATUS:
@ -2811,7 +2820,8 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
goto badindex; goto badindex;
for (native_t kk, SPRITES_OF_STAT_SAFE(nIndex, jj, kk)) for (native_t kk, SPRITES_OF_STAT_SAFE(nIndex, jj, kk))
CON_FOR_ITERATION(); if (execute(jj))
return;
break; break;
case ITER_WALLSOFSECTOR: case ITER_WALLSOFSECTOR:
@ -2819,7 +2829,8 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
goto badindex; goto badindex;
for (native_t jj = sector[nIndex].wallptr, endwall = jj + sector[nIndex].wallnum - 1; jj <= endwall; jj++) for (native_t jj = sector[nIndex].wallptr, endwall = jj + sector[nIndex].wallnum - 1; jj <= endwall; jj++)
CON_FOR_ITERATION(); if (execute(jj))
return;
break; break;
case ITER_LOOPOFWALL: case ITER_LOOPOFWALL:
@ -2829,7 +2840,9 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
int jj = nIndex; int jj = nIndex;
do do
{ {
CON_FOR_ITERATION(); if (execute(jj))
return;
jj = wall[jj].point2; jj = wall[jj].point2;
} while (jj != nIndex); } while (jj != nIndex);
} }
@ -2837,7 +2850,8 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
case ITER_RANGE: case ITER_RANGE:
for (native_t jj = 0; jj < nIndex; jj++) for (native_t jj = 0; jj < nIndex; jj++)
CON_FOR_ITERATION(); if (execute(jj))
return;
break; break;
badindex: badindex:
Printf(OSD_ERROR "Line %d, for %s: index %d out of range!\n", VM_DECODE_LINE_NUMBER(g_tw), iter_tokens[iterType].token, nIndex); Printf(OSD_ERROR "Line %d, for %s: index %d out of range!\n", VM_DECODE_LINE_NUMBER(g_tw), iter_tokens[iterType].token, nIndex);
@ -2847,7 +2861,6 @@ badindex:
insptr = pEnd; insptr = pEnd;
} }
dispatch(); dispatch();
#undef CON_FOR_ITERATION
vInstruction(CON_REDEFINEQUOTE): vInstruction(CON_REDEFINEQUOTE):
insptr++; insptr++;