Skip to content

Commit

Permalink
fix: Don't stackoverflow on deeply nested expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
Markus Westerlind committed Jun 14, 2022
1 parent f8817e0 commit 9b544a0
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 7 deletions.
50 changes: 44 additions & 6 deletions libflux/flux-core/src/ast/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,31 @@ 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<Error>> {
let mut errors = Errors::new();
walk::walk(
&mut |n: walk::Node| {
const MAX_DEPTH: u32 = 1000;

#[derive(Default)]
struct Check {
depth: u32,
errors: Errors<Error>,
}

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 {
message: String::from("Program is nested to deep"),
},
));

return false;
}

// collect any errors we found prior to ast.check().
for err in n.base().errors.iter() {
errors.push(located(
Expand Down Expand Up @@ -76,9 +98,19 @@ pub fn check(node: walk::Node) -> Result<(), Errors<Error>> {
}
_ => {}
}
},
node,
);

true
}

fn done(&mut self, _: walk::Node<'a>) {
self.depth -= 1;
}
}

let mut check = Check::default();
walk::walk(&mut check, node);
let errors = check.errors;

if errors.is_empty() {
Ok(())
} else {
Expand All @@ -97,6 +129,12 @@ pub struct ErrorKind {
pub message: String,
}

impl ErrorKind {
pub(crate) fn is_fatal(&self) -> bool {
self.message.contains("Program is nested to deep")
}
}

impl AsDiagnostic for ErrorKind {
fn as_diagnostic(&self, _source: &dyn crate::semantic::Source) -> diagnostic::Diagnostic<()> {
diagnostic::Diagnostic::error().with_message(self.to_string())
Expand Down
1 change: 0 additions & 1 deletion libflux/flux-core/src/formatter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ pub fn format(contents: &str) -> Result<String> {
let file = parse_string("".to_string(), contents);
let node = ast::walk::Node::File(&file);
ast::check::check(node)?;

convert_to_string(&file)
}

Expand Down
14 changes: 14 additions & 0 deletions libflux/flux-core/src/semantic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,21 @@ impl<'env, I: import::Importer> Analyzer<'env, I> {
let mut errors = Errors::new();

if let Err(err) = ast::check::check(ast::walk::Node::Package(ast_pkg)) {
let has_fatal_error = err.iter().any(|e| e.error.is_fatal());
errors.extend(err.into_iter().map(Error::from));
if has_fatal_error {
return Err(Salvage {
error: FileErrors {
file: ast_pkg.package.clone(),
source: None,
diagnostics: Diagnostics {
errors,
warnings: Errors::new(),
},
},
value: None,
});
}
}

let mut sem_pkg = {
Expand Down

0 comments on commit 9b544a0

Please sign in to comment.