Skip to content

Commit

Permalink
add a recursion limit to parser
Browse files Browse the repository at this point in the history
  • Loading branch information
kaikalii committed Jun 15, 2024
1 parent 66f6291 commit d058919
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
21 changes: 20 additions & 1 deletion src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub enum ParseError {
SplitInModifier,
UnsplitInModifier,
LineTooLong(usize),
RecursionLimit,
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -100,6 +101,7 @@ impl fmt::Display for ParseError {
"Split line into multiple lines (heuristic: {}/{}) 😏",
width, ERROR_MAX_WIDTH
),
ParseError::RecursionLimit => write!(f, "Parsing recursion limit reached"),
}
}
}
Expand Down Expand Up @@ -197,6 +199,7 @@ pub fn parse(
errors,
diagnostics,
next_output_comment: 0,
depth: 0,
};
let items = parser.items(true);
if parser.errors.is_empty() && parser.index < parser.tokens.len() {
Expand All @@ -207,7 +210,15 @@ pub fn parse(
.map(ParseError::Unexpected),
);
}
(items, parser.errors, parser.diagnostics)
let mut errors = parser.errors;
if let Some(error) = errors
.iter()
.find(|e| matches!(e.value, ParseError::RecursionLimit))
{
let error = error.clone();
errors = vec![error];
}
(items, errors, parser.diagnostics)
}
parse(input, inputs, tokens, lex_errors, src)
}
Expand All @@ -220,6 +231,7 @@ struct Parser<'i> {
next_output_comment: usize,
errors: Vec<Sp<ParseError>>,
diagnostics: Vec<Diagnostic>,
depth: usize,
}

type FunctionContents = (Option<Sp<Signature>>, Vec<Vec<Sp<Word>>>, Option<CodeSpan>);
Expand Down Expand Up @@ -732,6 +744,11 @@ impl<'i> Parser<'i> {
Some(span.sp(make(items)))
}
fn try_modified(&mut self) -> Option<Sp<Word>> {
if self.depth > 50 {
self.errors
.push(self.prev_span().sp(ParseError::RecursionLimit));
return None;
}
let (modifier, mod_span) = if let Some(prim) = Primitive::all()
.filter(|prim| prim.is_modifier())
.find_map(|prim| {
Expand All @@ -756,6 +773,7 @@ impl<'i> Parser<'i> {
};
let mut args = Vec::new();
self.try_spaces();
self.depth += 1;
for i in 0..modifier.args() {
loop {
args.extend(self.try_spaces());
Expand All @@ -782,6 +800,7 @@ impl<'i> Parser<'i> {
break;
}
}
self.depth -= 1;

let span = if let Some(last) = args.last() {
mod_span.clone().merge(last.span.clone())
Expand Down
1 change: 1 addition & 0 deletions todo.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Uiua Todo

- 0.12
- Don't generate inlay hints if not necessary
- `setinv` on and by inverses
- Document on and by inverses
- Pervasive switch functions and `repeat`
Expand Down

0 comments on commit d058919

Please sign in to comment.