1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-12-23 01:59:43 +01:00

Prevent same-frame infinite loops in scripts

It's trivially easy to send the scripting system into an infinite loop
on the same frame (i.e. without any script delay in between, i.e. within
the same execution of script.run()). Just take a look at these two
scripts:

    a:
    iftrinkets(0,b)
    #

    b:
    iftrinkets(0,a)
    #

The hashes are to prevent the scripting system from parsing iftrinkets()
using the internal version instead of the simplified version, because
after doing a simplified iftrinkets(), the parser will (to oversimplify)
execute the last line of the script as internal.

Anyway, sending the game into an infinite loop like this will cause the
Not Responding dialog on Windows.

So to prevent this from happening, I've added an execution counter to
scriptclass::run(). If it gets too high, we're in an infinite loop and
so we stop running the script.
This commit is contained in:
Misa 2020-09-07 20:58:32 -07:00 committed by Ethan Lee
parent 662a658cf6
commit a6a8173e20

View file

@ -9,6 +9,8 @@
#include "Music.h" #include "Music.h"
#include "UtilityClass.h" #include "UtilityClass.h"
#include <limits.h>
scriptclass::scriptclass() scriptclass::scriptclass()
{ {
//Start SDL //Start SDL
@ -76,6 +78,8 @@ void scriptclass::tokenize( const std::string& t )
void scriptclass::run() void scriptclass::run()
{ {
// This counter here will stop the function when it gets too high
short execution_counter = 0;
while(running && scriptdelay<=0 && !game.pausescript) while(running && scriptdelay<=0 && !game.pausescript)
{ {
if (position < (int) commands.size()) if (position < (int) commands.size())
@ -2603,6 +2607,17 @@ void scriptclass::run()
{ {
running = false; running = false;
} }
// Don't increment if we're at the max, signed int overflow is UB
if (execution_counter == SHRT_MAX)
{
// We must be in an infinite loop
printf("Warning: execution counter got to %i, stopping script\n", SHRT_MAX);
running = false;
}
else
{
execution_counter++;
}
} }
if(scriptdelay>0) if(scriptdelay>0)