From be2fe943c049d479bec9c476e196037678e05b32 Mon Sep 17 00:00:00 2001 From: Jacob1 Date: Wed, 23 May 2012 20:08:53 -0400 Subject: [PATCH] Prevent accidental infinite loops in lua Also fix glitch when step_functions[0] is unregistered but others aren't --- .gitignore | 2 +- includes/defines.h | 1 + includes/luaconsole.h | 1 + src/interface.c | 1 + src/luaconsole.c | 35 +++++++++++++++++++++++++---------- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index f22dc53ce..27e78a6ec 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,4 @@ src/python/stdlib/* *.bat *.o *.me -* \ No newline at end of file +* diff --git a/includes/defines.h b/includes/defines.h index 28cdbd2b6..bb57b8e39 100644 --- a/includes/defines.h +++ b/includes/defines.h @@ -189,6 +189,7 @@ extern int ngrav_enable; int limitFPS; int water_equal_test; extern int quickoptions_tooltip_fade; +extern int loop_time; extern int debug_flags; #define DEBUG_PERF_FRAMECOUNT 256 diff --git a/includes/luaconsole.h b/includes/luaconsole.h index 83fa4054a..ce8f6b1c6 100644 --- a/includes/luaconsole.h +++ b/includes/luaconsole.h @@ -62,6 +62,7 @@ int luacon_particle_getproperty(char * key, int * format); int luacon_transition_getproperty(char * key, int * format); int luacon_element_getproperty(char * key, int * format, unsigned int * modified_stuff); int process_command_lua(pixel *vid_buf, char *console, char *console_error); +void lua_hook(lua_State *L, lua_Debug *ar); int getPartIndex_curIdx; diff --git a/src/interface.c b/src/interface.c index 9e8c6db86..f2f4b180a 100644 --- a/src/interface.c +++ b/src/interface.c @@ -2683,6 +2683,7 @@ int sdl_poll(void) { SDL_Event event; sdl_key=sdl_rkey=sdl_wheel=sdl_ascii=0; + loop_time = SDL_GetTicks(); while (SDL_PollEvent(&event)) { switch (event.type) diff --git a/src/luaconsole.c b/src/luaconsole.c index 759dd7522..92b58bb78 100644 --- a/src/luaconsole.c +++ b/src/luaconsole.c @@ -32,6 +32,7 @@ int tptProperties; //Table for some TPT properties int tptPropertiesVersion; int tptElements; //Table for TPT element names int tptParts, tptPartsMeta, tptElementTransitions, tptPartsCData, tptPartMeta, tptPart, cIndex; +int loop_time = 0; void luacon_open(){ int i = 0, j; char tmpname[12]; @@ -219,6 +220,7 @@ tpt.partsdata = nil"); { lua_el_mode[i] = 0; } + lua_sethook(l, &lua_hook, LUA_MASKCOUNT, 200); } #ifndef FFI int luacon_partread(lua_State* l){ @@ -733,26 +735,39 @@ int luacon_step(int mx, int my, int selectl, int selectr){ lua_setfield(l, tptProperties, "mousey"); lua_setfield(l, tptProperties, "selectedl"); lua_setfield(l, tptProperties, "selectedr"); - if(step_functions[0]){ - //Set mouse globals - for(i = 0; i<6; i++){ - if(step_functions[i]){ - lua_rawgeti(l, LUA_REGISTRYINDEX, step_functions[i]); - callret = lua_pcall(l, 0, 0, 0); - if (callret) + for(i = 0; i<6; i++){ + if(step_functions[i]){ + loop_time = SDL_GetTicks(); + lua_rawgeti(l, LUA_REGISTRYINDEX, step_functions[i]); + callret = lua_pcall(l, 0, 0, 0); + if (callret) + { + // failed, TODO: better error reporting + printf("%s\n",luacon_geterror()); + if (!strcmp(luacon_geterror(),"Error: Infinite loop")) { - // failed, TODO: better error reporting - printf("%s\n",luacon_geterror()); + lua_pushcfunction(l,&luatpt_unregister_step); + lua_rawgeti(l, LUA_REGISTRYINDEX, step_functions[i]); + lua_pcall(l, 1, 0, 0); } } } - return tempret; } return 0; } int luacon_eval(char *command){ + loop_time = SDL_GetTicks(); return luaL_dostring (l, command); } +void lua_hook(lua_State *L, lua_Debug *ar) +{ + if(ar->event == LUA_HOOKCOUNT && SDL_GetTicks()-loop_time > 3000) + { + if (confirm_ui(vid_buf,"Infinite Loop","The Lua code might have an infinite loop. Press OK to stop it","OK")) + luaL_error(l,"Error: Infinite loop"); + loop_time = SDL_GetTicks(); + } +} int luacon_part_update(int t, int i, int x, int y, int surround_space, int nt) { int retval = 0;