diff --git a/include/daScript/builtin/debugapi_gen.inc b/include/daScript/builtin/debugapi_gen.inc index dbfa996755..8fca318c3b 100644 --- a/include/daScript/builtin/debugapi_gen.inc +++ b/include/daScript/builtin/debugapi_gen.inc @@ -1223,9 +1223,10 @@ protected: __fn_onBeforeVariables = 9, __fn_onVariable = 10, __fn_onAfterCall = 11, + __fn_onCorruptStack = 12, }; protected: - int _das_class_method_offset[12]; + int _das_class_method_offset[13]; public: DapiStackWalker_Adapter ( const StructInfo * info ) { _das_class_method_offset[__fn_canWalkArguments] = info->fields[2]->offset; @@ -1240,6 +1241,7 @@ public: _das_class_method_offset[__fn_onBeforeVariables] = info->fields[11]->offset; _das_class_method_offset[__fn_onVariable] = info->fields[12]->offset; _das_class_method_offset[__fn_onAfterCall] = info->fields[13]->offset; + _das_class_method_offset[__fn_onCorruptStack] = info->fields[14]->offset; } __forceinline Func get_canWalkArguments ( void * self ) const { return getDasClassMethod(self,_das_class_method_offset[__fn_canWalkArguments]); @@ -1349,5 +1351,14 @@ public: (__context__,nullptr,__funcCall__, self,pp); } + __forceinline Func get_onCorruptStack ( void * self ) const { + return getDasClassMethod(self,_das_class_method_offset[__fn_onCorruptStack]); + } + __forceinline void invoke_onCorruptStack ( Context * __context__, Func __funcCall__, void * self, Prologue const & pp ) const { + das_invoke_function::invoke + + (__context__,nullptr,__funcCall__, + self,pp); + } }; diff --git a/include/daScript/simulate/simulate.h b/include/daScript/simulate/simulate.h index 8b6c836492..7059eccaf5 100644 --- a/include/daScript/simulate/simulate.h +++ b/include/daScript/simulate/simulate.h @@ -287,6 +287,7 @@ namespace das virtual void onBeforeVariables ( ) { } virtual void onVariable ( FuncInfo *, LocalVariableInfo *, void *, bool ) { } virtual bool onAfterCall ( Prologue * ) { return true; } + virtual void onCorruptStack ( Prologue * ) { } }; typedef smart_ptr StackWalkerPtr; diff --git a/modules/dasLLVM b/modules/dasLLVM index a148b2d6e9..a5b37e16c1 160000 --- a/modules/dasLLVM +++ b/modules/dasLLVM @@ -1 +1 @@ -Subproject commit a148b2d6e97f716aa99e2f759edd9cfd872c50f1 +Subproject commit a5b37e16c1d0e955a30fc97296a8d52fbc9a37d1 diff --git a/src/builtin/debugger.das b/src/builtin/debugger.das index 9f1dd675a5..b9dfd8ce87 100644 --- a/src/builtin/debugger.das +++ b/src/builtin/debugger.das @@ -210,6 +210,7 @@ class DapiStackWalker { def abstract onBeforeVariables : void def abstract onVariable(inf : FuncInfo; vinfo : LocalVariableInfo; arg : void?; inScope : bool) : void def abstract onAfterCall(pp : Prologue) : bool + def abstract onCorruptStack(pp : Prologue) : void } def make_stack_walker(classPtr) : smart_ptr { diff --git a/src/builtin/debugger.das.inc b/src/builtin/debugger.das.inc index ce2ccb9f28..10d8b93379 100644 --- a/src/builtin/debugger.das.inc +++ b/src/builtin/debugger.das.inc @@ -1424,6 +1424,13 @@ static unsigned char debugger_das[] = { 0x3a,0x20,0x50,0x72,0x6f,0x6c,0x6f,0x67, 0x75,0x65,0x29,0x20,0x3a,0x20,0x62,0x6f, 0x6f,0x6c,0x0a, +0x20,0x20,0x20,0x20,0x64,0x65,0x66,0x20, +0x61,0x62,0x73,0x74,0x72,0x61,0x63,0x74, +0x20,0x6f,0x6e,0x43,0x6f,0x72,0x72,0x75, +0x70,0x74,0x53,0x74,0x61,0x63,0x6b,0x28, +0x70,0x70,0x20,0x3a,0x20,0x50,0x72,0x6f, +0x6c,0x6f,0x67,0x75,0x65,0x29,0x20,0x3a, +0x20,0x76,0x6f,0x69,0x64,0x0a, 0x7d,0x0a, 0x0a, 0x64,0x65,0x66,0x20,0x6d,0x61,0x6b,0x65, diff --git a/src/builtin/module_builtin_debugger.cpp b/src/builtin/module_builtin_debugger.cpp index 5ae6f91af5..de078562c6 100644 --- a/src/builtin/module_builtin_debugger.cpp +++ b/src/builtin/module_builtin_debugger.cpp @@ -757,6 +757,11 @@ namespace debugapi { return true; } } + virtual void onCorruptStack ( Prologue * pp ) override { + if ( auto fnOnCorruptStack = get_onCorruptStack(classPtr) ) { + invoke_onCorruptStack(context,fnOnCorruptStack,classPtr,*pp); + } + } protected: void * classPtr; Context * context; @@ -825,7 +830,7 @@ namespace debugapi { #if DAS_ENABLE_STACK_WALK char * sp = context.stack.ap(); int32_t depth = 0; - while ( sp < context.stack.top() ) { + while ( sp < context.stack.top() ) { Prologue * pp = (Prologue *) sp; Block * block = nullptr; FuncInfo * info = nullptr; @@ -840,7 +845,16 @@ namespace debugapi { info = pp->info; } } - sp += info ? info->stackSize : pp->stackSize; + auto incr = info ? info->stackSize : pp->stackSize; + if ( incr >= context.stack.size() || incr context.stack.top() ) { + // corrupted stack + break; + } depth ++; } return depth; @@ -854,7 +868,7 @@ namespace debugapi { #if DAS_ENABLE_STACK_WALK char * sp = context.stack.ap(); const LineInfo * lineAt = &at; - while ( sp < context.stack.top() ) { + while ( sp < context.stack.top() ) { Prologue * pp = (Prologue *) sp; Block * block = nullptr; FuncInfo * info = nullptr; @@ -869,6 +883,11 @@ namespace debugapi { info = pp->info; } } + auto incr = info ? info->stackSize : pp->stackSize; + if ( incr >= context.stack.size() || incronCorruptStack(pp); + break; + } walker->onBeforeCall(pp,SP); if ( !info ) { walker->onCallAOT(pp,pp->fileName); @@ -909,7 +928,11 @@ namespace debugapi { } } lineAt = info ? pp->line : nullptr; - sp += info ? info->stackSize : pp->stackSize; + sp += incr; + if ( sp > context.stack.top() ) { + walker->onCorruptStack(pp); + break; + } if ( !walker->onAfterCall(pp) ) break; } #else diff --git a/src/simulate/simulate.cpp b/src/simulate/simulate.cpp index afa2490d3b..d95c54c020 100644 --- a/src/simulate/simulate.cpp +++ b/src/simulate/simulate.cpp @@ -1592,7 +1592,10 @@ namespace das } virtual bool onAfterCall ( Prologue * ) override { return !stackTopOnly; - } + } + virtual void onCorruptStack (Prologue * ) override { + ssw << "!!! stack corrupted, aborting stack walk !!!\n"; + } public: bool showArguments = true; bool showLocalVariables = true;