--- src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScope.cs +++ src/MoonSharp.Interpreter/Execution/Scopes/BuildTimeScope.cs @@ -79,6 +79,7 @@ private SymbolRef CreateUpValue(BuildTimeScope buildTimeScope, SymbolRef symb, int closuredFrame, int currentFrame) { + StackGuard.Ensure(); // it's a 0-level upvalue. Just create it and we're done. if (closuredFrame == currentFrame) return m_ClosureBuilders[currentFrame + 1].CreateUpvalue(this, symb); --- /dev/null +++ src/MoonSharp.Interpreter/StackGuard.cs @@ -0,0 +1,30 @@ +using System; +using System.Runtime.CompilerServices; + +namespace MoonSharp.Interpreter +{ + /// + /// Turns a nearly used-up stack into a syntax error. + /// It sits where the parser and compiler recurse with no bound of their own. + /// Those are the expression and statement parsers, the compilers of nodes that a loop can chain without limit, and + /// the walk that links an upvalue through every enclosing function. + /// Every other recursion is over a tree no deeper than the parser accepted. + /// + internal static class StackGuard + { + /// + /// Throws a when the stack is too low to recurse further. + /// + public static void Ensure() + { + try + { + RuntimeHelpers.EnsureSufficientExecutionStack(); + } + catch (InsufficientExecutionStackException) + { + throw new SyntaxErrorException(null, "chunk has too many syntax levels"); + } + } + } +} --- src/MoonSharp.Interpreter/Tree/Expression_.cs +++ src/MoonSharp.Interpreter/Tree/Expression_.cs @@ -62,6 +62,7 @@ internal static Expression SubExpr(ScriptLoadingContext lcontext, bool isPrimary) { + StackGuard.Ensure(); Expression e = null; Token T = lcontext.Lexer.Current; --- src/MoonSharp.Interpreter/Tree/Expressions/BinaryOperatorExpression.cs +++ src/MoonSharp.Interpreter/Tree/Expressions/BinaryOperatorExpression.cs @@ -299,6 +299,7 @@ public override void Compile(Execution.VM.ByteCode bc) { + StackGuard.Ensure(); m_Exp1.Compile(bc); if (m_Operator == Operator.Or) --- src/MoonSharp.Interpreter/Tree/Expressions/FunctionCallExpression.cs +++ src/MoonSharp.Interpreter/Tree/Expressions/FunctionCallExpression.cs @@ -68,6 +68,7 @@ public override void Compile(Execution.VM.ByteCode bc) { + StackGuard.Ensure(); m_Function.Compile(bc); int argslen = m_Arguments.Count; --- src/MoonSharp.Interpreter/Tree/Expressions/IndexExpression.cs +++ src/MoonSharp.Interpreter/Tree/Expressions/IndexExpression.cs @@ -27,6 +27,7 @@ public override void Compile(ByteCode bc) { + StackGuard.Ensure(); m_BaseExp.Compile(bc); if (m_Name != null) --- src/MoonSharp.Interpreter/Tree/Statement.cs +++ src/MoonSharp.Interpreter/Tree/Statement.cs @@ -13,6 +13,7 @@ protected static Statement CreateStatement(ScriptLoadingContext lcontext, out bool forceLast) { + StackGuard.Ensure(); Token tkn = lcontext.Lexer.Current; forceLast = false;