Skip to content

Commit 87b0816

Browse files
committed
Fix stack overflow on parsing deeply nested expressions
Added a maximum expression depth of 64 to the parser and a more helpful error message if it's exceeded This fixes #788 Changelog: fixed
1 parent 2d5dd8d commit 87b0816

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

ast/src/parser.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ pub struct ParseError {
5050
pub location: Location,
5151
}
5252

53+
/// The maximum number of nested expressions allowed
54+
const MAX_DEPTH: u32 = 64;
55+
5356
/// A recursive-descent parser that turns Inko source code into an AST.
5457
///
5558
/// The AST is not a lossless AST. For example, whitespace and comments are not
@@ -60,13 +63,14 @@ pub struct Parser {
6063
lexer: Lexer,
6164
peeked: Option<Token>,
6265
comments: bool,
66+
depth: u32,
6367
}
6468

6569
impl Parser {
6670
pub fn new(input: Vec<u8>, file: PathBuf) -> Self {
6771
let lexer = Lexer::new(input);
6872

69-
Self { file, lexer, comments: false, peeked: None }
73+
Self { file, lexer, comments: false, peeked: None, depth: 0 }
7074
}
7175

7276
pub fn with_comments(input: Vec<u8>, file: PathBuf) -> Self {
@@ -1552,7 +1556,16 @@ impl Parser {
15521556
}
15531557

15541558
fn expression(&mut self, start: Token) -> Result<Expression, ParseError> {
1555-
self.boolean_and_or(start)
1559+
if self.depth == MAX_DEPTH {
1560+
error!(
1561+
start.location,
1562+
"Maximum expression depth of {} exceeded", MAX_DEPTH
1563+
)
1564+
}
1565+
self.depth += 1;
1566+
let res = self.boolean_and_or(start);
1567+
self.depth -= 1;
1568+
res
15561569
}
15571570

15581571
fn boolean_and_or(

0 commit comments

Comments
 (0)