mirror of
https://github.com/askama-rs/askama.git
synced 2025-09-27 13:00:57 +00:00
parser: understand nested block comments in macro calls
Fixes <https://issues.oss-fuzz.com/issues/427825995>.
This commit is contained in:
parent
7610b374db
commit
c71aead21b
@ -7,7 +7,7 @@ use winnow::combinator::{
|
||||
alt, cut_err, empty, fail, not, opt, peek, preceded, repeat, separated, terminated,
|
||||
};
|
||||
use winnow::error::{ErrMode, ParserError as _};
|
||||
use winnow::token::take_until;
|
||||
use winnow::token::{one_of, take_until};
|
||||
|
||||
use crate::node::CondTest;
|
||||
use crate::{
|
||||
@ -839,21 +839,31 @@ impl<'a> Suffix<'a> {
|
||||
fn block_comment<'a>(i: &mut &'a str) -> ParseResult<'a, ()> {
|
||||
let start = "/*".parse_next(i)?;
|
||||
let is_doc_comment = alt((
|
||||
('*', not(peek('*'))).value(true),
|
||||
('*', not(peek(one_of(['*', '/'])))).value(true),
|
||||
'!'.value(true),
|
||||
empty.value(false),
|
||||
))
|
||||
.parse_next(i)?;
|
||||
if opt(take_until(.., "*/")).parse_next(i)?.is_none() {
|
||||
return cut_error!(
|
||||
format!(
|
||||
"missing `*/` to close block {}comment",
|
||||
if is_doc_comment { "doc " } else { "" }
|
||||
),
|
||||
start,
|
||||
);
|
||||
|
||||
let mut depth = 0usize;
|
||||
loop {
|
||||
if opt(take_until(.., ("/*", "*/"))).parse_next(i)?.is_none() {
|
||||
return cut_error!(
|
||||
format!(
|
||||
"missing `*/` to close block {}comment",
|
||||
if is_doc_comment { "doc " } else { "" }
|
||||
),
|
||||
start,
|
||||
);
|
||||
} else if alt(("/*".value(true), "*/".value(false))).parse_next(i)? {
|
||||
// cannot overflow: `i` cannot be longer than `isize::MAX`, cf. [std::alloc::Layout]
|
||||
depth += 1;
|
||||
} else if let Some(new_depth) = depth.checked_sub(1) {
|
||||
depth = new_depth;
|
||||
} else {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn identifier_or_prefixed_string<'a>(i: &mut &'a str) -> ParseResult<'a, ()> {
|
||||
|
@ -1561,3 +1561,34 @@ fn test_raw() {
|
||||
}))],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_macro_call_nested_comments() {
|
||||
// Regression test for <https://issues.oss-fuzz.com/issues/427825995>.
|
||||
let syntax = Syntax::default();
|
||||
|
||||
assert_eq!(
|
||||
Ast::from_str("{{ x!(/*/*/*)*/*/*/) }}", None, &syntax)
|
||||
.unwrap()
|
||||
.nodes,
|
||||
vec![Node::Expr(
|
||||
Ws(None, None),
|
||||
WithSpan::no_span(Expr::RustMacro(vec!["x"], "/*/*/*)*/*/*/")),
|
||||
)],
|
||||
);
|
||||
|
||||
let msg = Ast::from_str("{{ x!(/*/*/) }}", None, &syntax)
|
||||
.unwrap_err()
|
||||
.to_string();
|
||||
assert!(msg.contains("missing `*/` to close block comment"));
|
||||
|
||||
assert_eq!(
|
||||
Ast::from_str("{{ x!(/**/) }}", None, &syntax)
|
||||
.unwrap()
|
||||
.nodes,
|
||||
vec![Node::Expr(
|
||||
Ws(None, None),
|
||||
WithSpan::no_span(Expr::RustMacro(vec!["x"], "/**/")),
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD>{{K!(/*/*/)}}<7D><><EFBFBD><EFBFBD>u<EFBFBD><75>
|
Loading…
x
Reference in New Issue
Block a user