mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-01 15:00:57 +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::Parser;
|
||||||
use winnow::ascii::digit1;
|
use winnow::ascii::digit1;
|
||||||
use winnow::combinator::{
|
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::error::ParserError as _;
|
||||||
|
use winnow::token::take_until;
|
||||||
|
|
||||||
use crate::node::CondTest;
|
use crate::node::CondTest;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -780,6 +781,9 @@ impl<'a> Suffix<'a> {
|
|||||||
identifier_or_prefixed_string.value(Token::SomeOther),
|
identifier_or_prefixed_string.value(Token::SomeOther),
|
||||||
// lifetimes
|
// lifetimes
|
||||||
('\'', identifier, not(peek('\''))).value(Token::SomeOther),
|
('\'', identifier, not(peek('\''))).value(Token::SomeOther),
|
||||||
|
// comments
|
||||||
|
line_comment.value(Token::SomeOther),
|
||||||
|
block_comment.value(Token::SomeOther),
|
||||||
// punctuations
|
// punctuations
|
||||||
punctuation.value(Token::SomeOther),
|
punctuation.value(Token::SomeOther),
|
||||||
hash,
|
hash,
|
||||||
@ -787,6 +791,46 @@ impl<'a> Suffix<'a> {
|
|||||||
alt((open.map(Token::Open), close.map(Token::Close), some_other)).parse_next(i)
|
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, ()> {
|
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>
|
// <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