Index: class.c ================================================================== --- class.c +++ class.c @@ -637,10 +637,11 @@ static void nxttok(void) { if(pushback) { pushback=0; return; } + if(StackProtection()) fatal("Stack overflow\n"); again: nxttok1(); if(tokent&TF_EOF) { if(inpstack) { InputStack s=*inpstack; Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -2,10 +2,11 @@ gcc ${CFLAGS:--s -O2} -c exec.c `sdl-config --cflags` exit #endif #include "SDL.h" +#include #include #include #include #include "sqlite3.h" #include "smallxrm.h" @@ -14,5 +15,13 @@ Uint32 generation_number; Object*objects; Uint32 nobjects; Value globals[0x800]; +static jmp_buf my_env; +static int my_error; + +int execute_turn(int key) { + if(setjmp(my_env)) return my_error; + + return 0; +} Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -39,10 +39,29 @@ extern xrm_db*resourcedb; extern const char*basefilename; extern xrm_quark optionquery[16]; extern char main_options[128]; extern Uint8 message_trace[0x4100/8]; + +#ifdef __GNUC__ +extern char stack_protect_mode; +extern void*stack_protect_mark; +extern void*stack_protect_low; +extern void*stack_protect_high; +#define StackProtection() (stack_protect_mode && ( \ + stack_protect_mode=='<' ? (__builtin_frame_address(0)' ? (__builtin_frame_address(0)>stack_protect_mark) : \ + stack_protect_mode=='?' ? ({ \ + if(__builtin_frame_address(0)stack_protect_high) stack_protect_high=__builtin_frame_address(0); \ + 0; \ + }) : \ + stack_protect_mode=='!' ? 1 : \ +0)) +#else +#define StackProtection() 0 +#endif unsigned char*read_lump(int sol,int lvl,long*sz,sqlite3_value**us); void write_lump(int sol,int lvl,long sz,const unsigned char*data); void set_cursor(int id); Index: main.c ================================================================== --- main.c +++ main.c @@ -41,10 +41,17 @@ xrm_db*resourcedb; const char*basefilename; xrm_quark optionquery[16]; char main_options[128]; Uint8 message_trace[0x4100/8]; + +#ifdef __GNUC__ +char stack_protect_mode=0; +void*stack_protect_mark; +void*stack_protect_low; +void*stack_protect_high; +#endif static const char*globalclassname; static SDL_Cursor*cursor[77]; static FILE*levelfp; static FILE*solutionfp; @@ -561,10 +568,30 @@ if(n>=m) fatal("Too long SQL statement\n"); } if(n) fatal("Unterminated SQL statement\n"); free(txt); } + +#ifdef __GNUC__ +static void test_stack_protection(void) { + fprintf(stderr,"Stack protection final values: %p %p %p\n",stack_protect_mark,stack_protect_low,stack_protect_high); +} + +static void set_stack_protection(void) { + const char*v; + optionquery[1]=Q_stackProtection; + v=xrm_get_resource(resourcedb,optionquery,optionquery,2); + if(!v || !*v) return; + stack_protect_mode=*v; + if(*v=='?') { + fprintf(stderr,"Stack protection test mode: %p\n",stack_protect_mark); + stack_protect_low=stack_protect_high=stack_protect_mark; + atexit(test_stack_protection); + } + if(v[1]) stack_protect_mark=((char*)stack_protect_mark)+strtoll(v+1,0,0); +} +#endif int main(int argc,char**argv) { int optind=1; while(argc>optind && argv[optind][0]=='-') { int i; @@ -583,17 +610,21 @@ globalclassname=argv[optind++]+1; } else if(find_globalclassname()) { globalclassname=strrchr(basefilename,'/'); globalclassname=globalclassname?globalclassname+1:basefilename; } + if(!main_options['c']) load_options(); + if(argc>optind) read_options(argc-optind,argv+optind); + *optionquery=xrm_make_quark(globalclassname,0)?:xrm_anyq; +#ifdef __GNUC__ + stack_protect_mark=__builtin_frame_address(0); + set_stack_protection(); +#endif if(main_options['c']) { load_classes(); return 0; } - load_options(); - if(argc>optind) read_options(argc-optind,argv+optind); - *optionquery=xrm_make_quark(globalclassname,0)?:xrm_anyq; init_sql(); load_key_bindings(); init_screen(); load_pictures(); if(main_options['T']) { Index: quarks ================================================================== --- quarks +++ quarks @@ -207,6 +207,7 @@ sqlPowerSafe ! Miscellaneous level tracePrefix +stackProtection Index: quarks.h ================================================================== --- quarks.h +++ quarks.h @@ -172,10 +172,11 @@ #define Q_sqlSmallAllocations 173 #define Q_sqlCoveringIndexScan 174 #define Q_sqlPowerSafe 175 #define Q_level 176 #define Q_tracePrefix 177 +#define Q_stackProtection 178 static const char*const global_quarks[]={ "screenWidth", "screenHeight", "palette", "popupColors", @@ -349,10 +350,11 @@ "sqlSmallAllocations", "sqlCoveringIndexScan", "sqlPowerSafe", "level", "tracePrefix", + "stackProtection", 0}; #ifdef HEROMESH_BINDINGS static const SDLKey quark_to_key[Q_undo+1-Q_backspace]={ SDLK_BACKSPACE, SDLK_TAB,