From 68c6160a14be4e77b98cd704d9e641a03aefa332 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 30 Dec 2022 09:48:30 +0100 Subject: Recursion with max depth --- src/model/eval.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/model/eval.rs') diff --git a/src/model/eval.rs b/src/model/eval.rs index ce1739ed..54007e76 100644 --- a/src/model/eval.rs +++ b/src/model/eval.rs @@ -20,6 +20,9 @@ use crate::syntax::{ast, Source, SourceId, Span, Spanned, SyntaxKind, SyntaxNode use crate::util::{format_eco, EcoString, PathExt}; use crate::World; +const MAX_ITERATIONS: usize = 10_000; +const MAX_CALL_DEPTH: usize = 256; + /// Evaluate a source file and return the resulting module. #[comemo::memoize] pub fn eval( @@ -41,7 +44,7 @@ pub fn eval( // Evaluate the module. let route = unsafe { Route::insert(route, id) }; let scopes = Scopes::new(Some(&library.scope)); - let mut vm = Vm::new(world, route.track(), id, scopes); + let mut vm = Vm::new(world, route.track(), id, scopes, 0); let result = source.ast()?.eval(&mut vm); // Handle control flow. @@ -70,6 +73,8 @@ pub struct Vm<'a> { pub(super) flow: Option, /// The stack of scopes. pub(super) scopes: Scopes<'a>, + /// The current call depth. + pub(super) depth: usize, } impl<'a> Vm<'a> { @@ -79,6 +84,7 @@ impl<'a> Vm<'a> { route: Tracked<'a, Route>, location: SourceId, scopes: Scopes<'a>, + depth: usize, ) -> Self { Self { world, @@ -87,6 +93,7 @@ impl<'a> Vm<'a> { location, flow: None, scopes, + depth, } } @@ -787,6 +794,10 @@ impl Eval for ast::FuncCall { type Output = Value; fn eval(&self, vm: &mut Vm) -> SourceResult { + if vm.depth >= MAX_CALL_DEPTH { + bail!(self.span(), "maximum function call depth exceeded"); + } + let callee = self.callee().eval(vm)?; let args = self.args().eval(vm)?; @@ -994,8 +1005,6 @@ impl Eval for ast::WhileLoop { type Output = Value; fn eval(&self, vm: &mut Vm) -> SourceResult { - const MAX_ITERS: usize = 10_000; - let flow = vm.flow.take(); let mut output = Value::None; let mut i = 0; @@ -1009,7 +1018,7 @@ impl Eval for ast::WhileLoop { && !can_diverge(body.as_untyped()) { bail!(condition.span(), "condition is always true"); - } else if i >= MAX_ITERS { + } else if i >= MAX_ITERATIONS { bail!(self.span(), "loop seems to be infinite"); } -- cgit v1.2.3