mirror of
https://github.com/askama-rs/askama.git
synced 2025-09-28 05:21:14 +00:00
parser: reject isolated CRs in string literals
According to <https://doc.rust-lang.org/reference/tokens.html#string-literals>. Fixes <https://github.com/askama-rs/askama/issues/482>. Fixes <https://issues.oss-fuzz.com/issues/424227903>.
This commit is contained in:
parent
163d9780bf
commit
341b850351
@ -573,6 +573,7 @@ fn str_lit<'a>(i: &mut &'a str) -> ParseResult<'a, StrLit<'a>> {
|
||||
Text(&'a str),
|
||||
Close,
|
||||
Escape,
|
||||
Cr(bool),
|
||||
}
|
||||
|
||||
let start = *i;
|
||||
@ -583,9 +584,10 @@ fn str_lit<'a>(i: &mut &'a str) -> ParseResult<'a, StrLit<'a>> {
|
||||
|
||||
while !i.is_empty() {
|
||||
let seq = alt((
|
||||
repeat::<_, _, (), _, _>(1.., none_of(['\\', '"']))
|
||||
repeat::<_, _, (), _, _>(1.., none_of(['\r', '\\', '"']))
|
||||
.take()
|
||||
.map(Sequence::Text),
|
||||
preceded('\r', opt('\n')).map(|c| Sequence::Cr(c.is_some())),
|
||||
'\\'.value(Sequence::Escape),
|
||||
peek('"').value(Sequence::Close),
|
||||
))
|
||||
@ -598,6 +600,16 @@ fn str_lit<'a>(i: &mut &'a str) -> ParseResult<'a, StrLit<'a>> {
|
||||
contains_null = contains_null || s.bytes().any(|c: u8| c == 0);
|
||||
continue;
|
||||
}
|
||||
Sequence::Cr(has_lf) => {
|
||||
if has_lf {
|
||||
continue;
|
||||
} else {
|
||||
return Err(winnow::error::ErrMode::Cut(ErrorContext::new(
|
||||
r#"bare CR not allowed in string, use `\r` instead"#,
|
||||
start,
|
||||
)));
|
||||
}
|
||||
}
|
||||
Sequence::Close => break,
|
||||
Sequence::Escape => {}
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
˙˙˙{{ ("
")}}˙ ˙i˙
|
@ -102,4 +102,19 @@ struct SurrogateLow3;
|
||||
#[template(ext = "txt", source = r#"{{ c"hello \u{de09} world" }}"#)]
|
||||
struct SurrogateHigh3;
|
||||
|
||||
// CR (\r) is only allowed if followed by NL (\n)
|
||||
// (regression test for <https://github.com/askama-rs/askama/issues/482>)
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "txt", source = "{{ \"hello \r world\" }}")]
|
||||
struct UnpairedCr;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "txt", source = "{{ b\"hello \r world\" }}")]
|
||||
struct UnpairedCrInBytes;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "txt", source = "{{ c\"hello \r world\" }}")]
|
||||
struct UnpairedCrInCstring;
|
||||
|
||||
fn main() {}
|
||||
|
@ -141,3 +141,27 @@ error: unicode escape must not be a surrogate
|
||||
|
|
||||
102 | #[template(ext = "txt", source = r#"{{ c"hello \u{de09} world" }}"#)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: bare CR not allowed in string, use `\r` instead
|
||||
--> <source attribute>:1:4
|
||||
"hello \r world\" }}"
|
||||
--> tests/ui/illegal-string-literals.rs:109:34
|
||||
|
|
||||
109 | #[template(ext = "txt", source = "{{ \"hello \r world\" }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: bare CR not allowed in string, use `\r` instead
|
||||
--> <source attribute>:1:5
|
||||
"hello \r world\" }}"
|
||||
--> tests/ui/illegal-string-literals.rs:113:34
|
||||
|
|
||||
113 | #[template(ext = "txt", source = "{{ b\"hello \r world\" }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: bare CR not allowed in string, use `\r` instead
|
||||
--> <source attribute>:1:5
|
||||
"hello \r world\" }}"
|
||||
--> tests/ui/illegal-string-literals.rs:117:34
|
||||
|
|
||||
117 | #[template(ext = "txt", source = "{{ c\"hello \r world\" }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
Loading…
x
Reference in New Issue
Block a user