Преглед изворни кода

Adding MaxStatements option

Sebastien Ros пре 11 година
родитељ
комит
4c52841fac

+ 9 - 0
Jint.Tests/Runtime/EngineTests.cs

@@ -1,6 +1,7 @@
 using System;
 using System.IO;
 using System.Reflection;
+using Jint.Runtime;
 using Xunit;
 using Xunit.Extensions;
 
@@ -563,5 +564,13 @@ namespace Jint.Tests.Runtime
         {
             new Engine().Execute("debugger"); 
         }
+       
+        [Fact]
+        public void ShouldThrowStatementCountOverflow()
+        {
+            Assert.Throws<StatementsCountOverflowException>(
+                () => new Engine(cfg => cfg.MaxStatements(100)).Execute("while(true);")
+            );
+        }
     }
 }

+ 18 - 1
Jint/Engine.cs

@@ -30,7 +30,8 @@ namespace Jint
         private readonly ExpressionInterpreter _expressions;
         private readonly StatementInterpreter _statements;
         private readonly Stack<ExecutionContext> _executionContexts;
- 
+        private int _statementsCount;
+
         public Engine() : this(null)
         {
         }
@@ -193,6 +194,14 @@ namespace Jint
             _executionContexts.Pop();
         }
 
+        /// <summary>
+        /// Initializes the statements count
+        /// </summary>
+        public void ResetStatementsCount()
+        {
+            _statementsCount = 0;
+        }
+
         public JsValue Execute(string source)
         {
             var parser = new JavaScriptParser();
@@ -201,6 +210,8 @@ namespace Jint
 
         public JsValue Execute(Program program)
         {
+            ResetStatementsCount();
+
             using (new StrictModeScope(Options.IsStrict() || program.Strict))
             {
                 DeclarationBindingInstantiation(DeclarationBindingType.GlobalCode, program.FunctionDeclarations, program.VariableDeclarations, null, null);
@@ -217,6 +228,12 @@ namespace Jint
 
         public Completion ExecuteStatement(Statement statement)
         {
+            var maxStatements = Options.GetMaxStatements();
+            if (maxStatements > 0 && _statementsCount++ > maxStatements)
+            {
+                throw new StatementsCountOverflowException();
+            }
+
             switch (statement.Type)
             {
                 case SyntaxNodes.BlockStatement:

+ 1 - 0
Jint/Jint.csproj

@@ -169,6 +169,7 @@
     <Compile Include="Runtime\JavaScriptException.cs" />
     <Compile Include="Runtime\References\Reference.cs" />
     <Compile Include="Runtime\StatementInterpreter.cs" />
+    <Compile Include="Runtime\StatementsCountOverflowException.cs" />
     <Compile Include="Runtime\TypeConverter.cs" />
     <Compile Include="StrictModeScope.cs" />
   </ItemGroup>

+ 12 - 0
Jint/Options.cs

@@ -8,6 +8,7 @@ namespace Jint
         private bool _strict;
         private bool _allowDebuggerStatement;
         private ITypeConverter _typeConverter = new DefaultTypeConverter();
+        private int _maxStatements = 0;
 
         /// <summary>
         /// When called, doesn't initialize the global scope.
@@ -50,6 +51,12 @@ namespace Jint
             return this;
         }
 
+        public Options MaxStatements(int maxStatements = 0)
+        {
+            _maxStatements = maxStatements;
+            return this;
+        }
+
         internal bool GetDiscardGlobal()
         {
             return _discardGlobal;
@@ -69,5 +76,10 @@ namespace Jint
         {
             return _typeConverter;
         }
+
+        internal int GetMaxStatements()
+        {
+            return _maxStatements;
+        }
     }
 }

+ 11 - 0
Jint/Runtime/StatementsCountOverflowException.cs

@@ -0,0 +1,11 @@
+using System;
+
+namespace Jint.Runtime
+{
+    public class StatementsCountOverflowException : Exception 
+    {
+        public StatementsCountOverflowException() : base("The maximum number of statements executed have been reached.")
+        {
+        }
+    }
+}