mirror of
https://github.com/askama-rs/askama.git
synced 2025-09-28 05:21:14 +00:00
parser: recognize comments in macro calls
Fixes issue <https://issues.oss-fuzz.com/issues/425145246>
This commit is contained in:
parent
e329f98433
commit
568ced0c55
@ -4,9 +4,10 @@ use std::str;
|
||||
use winnow::Parser;
|
||||
use winnow::ascii::digit1;
|
||||
use winnow::combinator::{
|
||||
alt, cut_err, fail, not, opt, peek, preceded, repeat, separated, terminated,
|
||||
alt, cut_err, empty, fail, not, opt, peek, preceded, repeat, separated, terminated,
|
||||
};
|
||||
use winnow::error::ParserError as _;
|
||||
use winnow::token::take_until;
|
||||
|
||||
use crate::node::CondTest;
|
||||
use crate::{
|
||||
@ -780,6 +781,9 @@ impl<'a> Suffix<'a> {
|
||||
identifier_or_prefixed_string.value(Token::SomeOther),
|
||||
// lifetimes
|
||||
('\'', identifier, not(peek('\''))).value(Token::SomeOther),
|
||||
// comments
|
||||
line_comment.value(Token::SomeOther),
|
||||
block_comment.value(Token::SomeOther),
|
||||
// punctuations
|
||||
punctuation.value(Token::SomeOther),
|
||||
hash,
|
||||
@ -787,6 +791,46 @@ impl<'a> Suffix<'a> {
|
||||
alt((open.map(Token::Open), close.map(Token::Close), some_other)).parse_next(i)
|
||||
}
|
||||
|
||||
fn line_comment<'a>(i: &mut &'a str) -> ParseResult<'a, ()> {
|
||||
let start = "//".parse_next(i)?;
|
||||
let is_doc_comment = alt((
|
||||
('/', not(peek('/'))).value(true),
|
||||
'!'.value(true),
|
||||
empty.value(false),
|
||||
))
|
||||
.parse_next(i)?;
|
||||
if opt(take_until(.., '\n')).parse_next(i)?.is_none() {
|
||||
return Err(winnow::error::ErrMode::Cut(ErrorContext::new(
|
||||
format!(
|
||||
"you are probably missing a line break to end {}comment",
|
||||
if is_doc_comment { "doc " } else { "" }
|
||||
),
|
||||
start,
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn block_comment<'a>(i: &mut &'a str) -> ParseResult<'a, ()> {
|
||||
let start = "/*".parse_next(i)?;
|
||||
let is_doc_comment = alt((
|
||||
('*', not(peek('*'))).value(true),
|
||||
'!'.value(true),
|
||||
empty.value(false),
|
||||
))
|
||||
.parse_next(i)?;
|
||||
if opt(take_until(.., "*/")).parse_next(i)?.is_none() {
|
||||
return Err(winnow::error::ErrMode::Cut(ErrorContext::new(
|
||||
format!(
|
||||
"missing `*/` to close block {}comment",
|
||||
if is_doc_comment { "doc " } else { "" }
|
||||
),
|
||||
start,
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn identifier_or_prefixed_string<'a>(i: &mut &'a str) -> ParseResult<'a, ()> {
|
||||
// <https://doc.rust-lang.org/reference/tokens.html#r-lex.token.literal.str-raw.syntax>
|
||||
|
||||
|
@ -1441,3 +1441,70 @@ fn macro_calls_can_have_raw_prefixes() {
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn macro_comments_in_macro_calls() {
|
||||
// Related to issue <https://github.com/askama-rs/askama/issues/475>.
|
||||
let syntax = Syntax::default();
|
||||
|
||||
assert!(Ast::from_str("{{ e!(// hello) }}", None, &syntax).is_err());
|
||||
assert!(Ast::from_str("{{ e!(/// hello) }}", None, &syntax).is_err());
|
||||
assert!(Ast::from_str("{{ e!(// hello)\n }}", None, &syntax).is_err());
|
||||
assert!(Ast::from_str("{{ e!(/// hello)\n }}", None, &syntax).is_err());
|
||||
|
||||
assert_eq!(
|
||||
Ast::from_str("{{ e!(// hello\n) }}", None, &syntax)
|
||||
.unwrap()
|
||||
.nodes,
|
||||
vec![Node::Expr(
|
||||
Ws(None, None),
|
||||
WithSpan::no_span(Expr::RustMacro(vec!["e"], "// hello\n")),
|
||||
)],
|
||||
);
|
||||
assert_eq!(
|
||||
Ast::from_str("{{ e!(/// hello\n) }}", None, &syntax)
|
||||
.unwrap()
|
||||
.nodes,
|
||||
vec![Node::Expr(
|
||||
Ws(None, None),
|
||||
WithSpan::no_span(Expr::RustMacro(vec!["e"], "/// hello\n")),
|
||||
)],
|
||||
);
|
||||
assert_eq!(
|
||||
Ast::from_str("{{ e!(//! hello\n) }}", None, &syntax)
|
||||
.unwrap()
|
||||
.nodes,
|
||||
vec![Node::Expr(
|
||||
Ws(None, None),
|
||||
WithSpan::no_span(Expr::RustMacro(vec!["e"], "//! hello\n")),
|
||||
)],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ast::from_str("{{ e!(/* hello */) }}", None, &syntax)
|
||||
.unwrap()
|
||||
.nodes,
|
||||
vec![Node::Expr(
|
||||
Ws(None, None),
|
||||
WithSpan::no_span(Expr::RustMacro(vec!["e"], "/* hello */")),
|
||||
)],
|
||||
);
|
||||
assert_eq!(
|
||||
Ast::from_str("{{ e!(/** hello */) }}", None, &syntax)
|
||||
.unwrap()
|
||||
.nodes,
|
||||
vec![Node::Expr(
|
||||
Ws(None, None),
|
||||
WithSpan::no_span(Expr::RustMacro(vec!["e"], "/** hello */")),
|
||||
)],
|
||||
);
|
||||
assert_eq!(
|
||||
Ast::from_str("{{ e!(/*! hello */) }}", None, &syntax)
|
||||
.unwrap()
|
||||
.nodes,
|
||||
vec![Node::Expr(
|
||||
Ws(None, None),
|
||||
WithSpan::no_span(Expr::RustMacro(vec!["e"], "/*! hello */")),
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
˙˙˙{{e!{//}}}˙˙˙˙s˙
|
41
testing/tests/ui/comments-in-macro-calls.rs
Normal file
41
testing/tests/ui/comments-in-macro-calls.rs
Normal file
@ -0,0 +1,41 @@
|
||||
use askama::Template;
|
||||
|
||||
// Regression test for <https://issues.oss-fuzz.com/issues/425145246>.
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "html", source = "{{ e!(// hello) }}")]
|
||||
struct LineComment;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "html", source = "{{ e!(// hello)\n}}")]
|
||||
struct LineComment2;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "html", source = "{{ e!(/* hello) }}")]
|
||||
struct BlockComment;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "html", source = "{{ e!(/// hello) }}")]
|
||||
struct OuterLineDoc;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "html", source = "{{ e!(/// hello)\n}}")]
|
||||
struct OuterLineDoc2;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "html", source = "{{ e!(/** hello) }}")]
|
||||
struct OuterBlockDoc;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "html", source = "{{ e!(//! hello) }}")]
|
||||
struct InnerLineDoc;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "html", source = "{{ e!(//! hello)\n}}")]
|
||||
struct InnerLineDoc2;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "html", source = "{{ e!(/*! hello) }}")]
|
||||
struct InnerBlockDoc;
|
||||
|
||||
fn main() {}
|
71
testing/tests/ui/comments-in-macro-calls.stderr
Normal file
71
testing/tests/ui/comments-in-macro-calls.stderr
Normal file
@ -0,0 +1,71 @@
|
||||
error: you are probably missing a line break to end comment
|
||||
--> <source attribute>:1:6
|
||||
"// hello) }}"
|
||||
--> tests/ui/comments-in-macro-calls.rs:6:35
|
||||
|
|
||||
6 | #[template(ext = "html", source = "{{ e!(// hello) }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: expected `)` but found `}`
|
||||
--> <source attribute>:1:15
|
||||
"}}"
|
||||
--> tests/ui/comments-in-macro-calls.rs:10:35
|
||||
|
|
||||
10 | #[template(ext = "html", source = "{{ e!(// hello)\n}}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: missing `*/` to close block comment
|
||||
--> <source attribute>:1:6
|
||||
"/* hello) }}"
|
||||
--> tests/ui/comments-in-macro-calls.rs:14:35
|
||||
|
|
||||
14 | #[template(ext = "html", source = "{{ e!(/* hello) }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: you are probably missing a line break to end doc comment
|
||||
--> <source attribute>:1:6
|
||||
"/// hello) }}"
|
||||
--> tests/ui/comments-in-macro-calls.rs:18:35
|
||||
|
|
||||
18 | #[template(ext = "html", source = "{{ e!(/// hello) }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: expected `)` but found `}`
|
||||
--> <source attribute>:1:16
|
||||
"}}"
|
||||
--> tests/ui/comments-in-macro-calls.rs:22:35
|
||||
|
|
||||
22 | #[template(ext = "html", source = "{{ e!(/// hello)\n}}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: missing `*/` to close block doc comment
|
||||
--> <source attribute>:1:6
|
||||
"/** hello) }}"
|
||||
--> tests/ui/comments-in-macro-calls.rs:26:35
|
||||
|
|
||||
26 | #[template(ext = "html", source = "{{ e!(/** hello) }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: you are probably missing a line break to end doc comment
|
||||
--> <source attribute>:1:6
|
||||
"//! hello) }}"
|
||||
--> tests/ui/comments-in-macro-calls.rs:30:35
|
||||
|
|
||||
30 | #[template(ext = "html", source = "{{ e!(//! hello) }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: expected `)` but found `}`
|
||||
--> <source attribute>:1:16
|
||||
"}}"
|
||||
--> tests/ui/comments-in-macro-calls.rs:34:35
|
||||
|
|
||||
34 | #[template(ext = "html", source = "{{ e!(//! hello)\n}}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: missing `*/` to close block doc comment
|
||||
--> <source attribute>:1:6
|
||||
"/*! hello) }}"
|
||||
--> tests/ui/comments-in-macro-calls.rs:38:35
|
||||
|
|
||||
38 | #[template(ext = "html", source = "{{ e!(/*! hello) }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
Loading…
x
Reference in New Issue
Block a user