Skip to content

Commit ac1da8f

Browse files
authored
fix: avoid stack overflow on many comments in a row (#7325)
1 parent 09d7705 commit ac1da8f

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

compiler/noirc_frontend/src/lexer/lexer.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,28 @@ impl<'a> Lexer<'a> {
103103
}
104104

105105
fn next_token(&mut self) -> SpannedTokenResult {
106+
if !self.skip_comments {
107+
return self.next_token_without_checking_comments();
108+
}
109+
110+
// Read tokens and skip comments. This is done like this to avoid recursion
111+
// and hitting stack overflow when there are many comments in a row.
112+
loop {
113+
let token = self.next_token_without_checking_comments()?;
114+
if matches!(token.token(), Token::LineComment(_, None) | Token::BlockComment(_, None)) {
115+
continue;
116+
}
117+
return Ok(token);
118+
}
119+
}
120+
121+
/// Reads the next token, which might be a comment token (these aren't skipped in this method)
122+
fn next_token_without_checking_comments(&mut self) -> SpannedTokenResult {
106123
match self.next_char() {
107124
Some(x) if Self::is_code_whitespace(x) => {
108125
let spanned = self.eat_whitespace(x);
109126
if self.skip_whitespaces {
110-
self.next_token()
127+
self.next_token_without_checking_comments()
111128
} else {
112129
Ok(spanned)
113130
}
@@ -755,10 +772,6 @@ impl<'a> Lexer<'a> {
755772
return Err(LexerErrorKind::NonAsciiComment { span });
756773
}
757774

758-
if doc_style.is_none() && self.skip_comments {
759-
return self.next_token();
760-
}
761-
762775
Ok(Token::LineComment(comment, doc_style).into_span(start, self.position))
763776
}
764777

@@ -804,9 +817,6 @@ impl<'a> Lexer<'a> {
804817
return Err(LexerErrorKind::NonAsciiComment { span });
805818
}
806819

807-
if doc_style.is_none() && self.skip_comments {
808-
return self.next_token();
809-
}
810820
Ok(Token::BlockComment(content, doc_style).into_span(start, self.position))
811821
} else {
812822
let span = Span::inclusive(start, self.position);

compiler/noirc_frontend/src/tests.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4364,3 +4364,9 @@ fn errors_on_if_without_else_type_mismatch() {
43644364
};
43654365
assert!(matches!(**err, TypeCheckError::TypeMismatch { .. }));
43664366
}
4367+
4368+
#[test]
4369+
fn does_not_stack_overflow_on_many_comments_in_a_row() {
4370+
let src = "//\n".repeat(10_000);
4371+
assert_no_errors(&src);
4372+
}

0 commit comments

Comments
 (0)