diff --git a/libflux/flux-core/src/ast/check/mod.rs b/libflux/flux-core/src/ast/check/mod.rs index bbc5e147f9..a4bbaf65d2 100644 --- a/libflux/flux-core/src/ast/check/mod.rs +++ b/libflux/flux-core/src/ast/check/mod.rs @@ -11,15 +11,26 @@ use crate::{ /// Inspects an AST node and returns a list of found AST errors plus /// any errors existed before `ast.check()` is performed. pub fn check(node: walk::Node) -> Result<(), Errors> { + const MAX_DEPTH: u32 = 180; + #[derive(Default)] struct Check { + depth: u32, errors: Errors, } impl<'a> walk::Visitor<'a> for Check { fn visit(&mut self, n: walk::Node<'a>) -> bool { + self.depth += 1; + let errors = &mut self.errors; + if self.depth > MAX_DEPTH { + errors.push(located(n.base().location.clone(), ErrorKind::NestedToDeep)); + + return false; + } + // collect any errors we found prior to ast.check(). for err in n.base().errors.iter() { let err = if err == "Program is nested too deep" { @@ -87,6 +98,10 @@ pub fn check(node: walk::Node) -> Result<(), Errors> { true } + + fn done(&mut self, _: walk::Node<'a>) { + self.depth -= 1; + } } let mut check = Check::default(); diff --git a/libflux/flux-core/src/parser/tests/errors.rs b/libflux/flux-core/src/parser/tests/errors.rs index a21dc229a3..010f145166 100644 --- a/libflux/flux-core/src/parser/tests/errors.rs +++ b/libflux/flux-core/src/parser/tests/errors.rs @@ -938,12 +938,18 @@ builtin y : int fn dont_stack_overflow() { let mut p = Parser::new(include_str!("stack_overflow.flux")); let parsed = p.parse_file("".to_string()); - assert!(&ast::check::check(ast::walk::Node::File(&parsed)).is_err()); + assert!(&ast::check::check(ast::walk::Node::File(&parsed)) + .unwrap_err() + .iter() + .any(|err| err.error.is_fatal())); } #[test] fn dont_stack_overflow_2() { let mut p = Parser::new(include_str!("stack_overflow_2.flux")); let parsed = p.parse_file("".to_string()); - assert!(&ast::check::check(ast::walk::Node::File(&parsed)).is_err()); + assert!(&ast::check::check(ast::walk::Node::File(&parsed)) + .unwrap_err() + .iter() + .any(|err| err.error.is_fatal())); }