Skip to content

Commit a3f913a

Browse files
Merge pull request #504 from Kijewski/6503980895371264
parser: understand nested block comments in macro calls
2 parents 7610b37 + c71aead commit a3f913a

File tree

3 files changed

+53
-11
lines changed

3 files changed

+53
-11
lines changed

askama_parser/src/expr.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use winnow::combinator::{
77
alt, cut_err, empty, fail, not, opt, peek, preceded, repeat, separated, terminated,
88
};
99
use winnow::error::{ErrMode, ParserError as _};
10-
use winnow::token::take_until;
10+
use winnow::token::{one_of, take_until};
1111

1212
use crate::node::CondTest;
1313
use crate::{
@@ -839,21 +839,31 @@ impl<'a> Suffix<'a> {
839839
fn block_comment<'a>(i: &mut &'a str) -> ParseResult<'a, ()> {
840840
let start = "/*".parse_next(i)?;
841841
let is_doc_comment = alt((
842-
('*', not(peek('*'))).value(true),
842+
('*', not(peek(one_of(['*', '/'])))).value(true),
843843
'!'.value(true),
844844
empty.value(false),
845845
))
846846
.parse_next(i)?;
847-
if opt(take_until(.., "*/")).parse_next(i)?.is_none() {
848-
return cut_error!(
849-
format!(
850-
"missing `*/` to close block {}comment",
851-
if is_doc_comment { "doc " } else { "" }
852-
),
853-
start,
854-
);
847+
848+
let mut depth = 0usize;
849+
loop {
850+
if opt(take_until(.., ("/*", "*/"))).parse_next(i)?.is_none() {
851+
return cut_error!(
852+
format!(
853+
"missing `*/` to close block {}comment",
854+
if is_doc_comment { "doc " } else { "" }
855+
),
856+
start,
857+
);
858+
} else if alt(("/*".value(true), "*/".value(false))).parse_next(i)? {
859+
// cannot overflow: `i` cannot be longer than `isize::MAX`, cf. [std::alloc::Layout]
860+
depth += 1;
861+
} else if let Some(new_depth) = depth.checked_sub(1) {
862+
depth = new_depth;
863+
} else {
864+
return Ok(());
865+
}
855866
}
856-
Ok(())
857867
}
858868

859869
fn identifier_or_prefixed_string<'a>(i: &mut &'a str) -> ParseResult<'a, ()> {

askama_parser/src/tests.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,3 +1561,34 @@ fn test_raw() {
15611561
}))],
15621562
);
15631563
}
1564+
1565+
#[test]
1566+
fn test_macro_call_nested_comments() {
1567+
// Regression test for <https://issues.oss-fuzz.com/issues/427825995>.
1568+
let syntax = Syntax::default();
1569+
1570+
assert_eq!(
1571+
Ast::from_str("{{ x!(/*/*/*)*/*/*/) }}", None, &syntax)
1572+
.unwrap()
1573+
.nodes,
1574+
vec![Node::Expr(
1575+
Ws(None, None),
1576+
WithSpan::no_span(Expr::RustMacro(vec!["x"], "/*/*/*)*/*/*/")),
1577+
)],
1578+
);
1579+
1580+
let msg = Ast::from_str("{{ x!(/*/*/) }}", None, &syntax)
1581+
.unwrap_err()
1582+
.to_string();
1583+
assert!(msg.contains("missing `*/` to close block comment"));
1584+
1585+
assert_eq!(
1586+
Ast::from_str("{{ x!(/**/) }}", None, &syntax)
1587+
.unwrap()
1588+
.nodes,
1589+
vec![Node::Expr(
1590+
Ws(None, None),
1591+
WithSpan::no_span(Expr::RustMacro(vec!["x"], "/**/")),
1592+
)],
1593+
);
1594+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
���{{K!(/*/*/)}}����u��

0 commit comments

Comments
 (0)