mirror of
https://github.com/askama-rs/askama.git
synced 2025-09-29 05:51:32 +00:00
Comparison operators cannot be chained
This commit is contained in:
parent
cd13e4f148
commit
eaccbb02ae
@ -1225,3 +1225,17 @@ fn fuzzed_0b85() -> Result<(), syn::Error> {
|
||||
let _: syn::File = syn::parse2(output)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fuzzed_comparator_chain() -> Result<(), syn::Error> {
|
||||
let input = quote! {
|
||||
#[template(
|
||||
ext = "",
|
||||
source = "\u{c}{{vu7218/63e3666663-666/3330e633/63e3666663666/3333<c\"}\u{1}2}\0\"<c7}}2\"\"\"\"\0\0\0\0"
|
||||
)]
|
||||
enum fff {}
|
||||
};
|
||||
let output = crate::derive_template(input, import_askama);
|
||||
let _: syn::File = syn::parse2(output)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -280,7 +280,33 @@ impl<'a> Expr<'a> {
|
||||
|
||||
expr_prec_layer!(or, and, "||");
|
||||
expr_prec_layer!(and, compare, "&&");
|
||||
expr_prec_layer!(compare, bor, alt(("==", "!=", ">=", ">", "<=", "<",)));
|
||||
|
||||
fn compare(i: &mut &'a str, level: Level<'_>) -> ParseResult<'a, WithSpan<'a, Self>> {
|
||||
let right = |i: &mut _| {
|
||||
let op = alt(("==", "!=", ">=", ">", "<=", "<"));
|
||||
(ws(op), |i: &mut _| Self::bor(i, level)).parse_next(i)
|
||||
};
|
||||
|
||||
let start = *i;
|
||||
let expr = Self::bor(i, level)?;
|
||||
let Some((op, rhs)) = opt(right).parse_next(i)? else {
|
||||
return Ok(expr);
|
||||
};
|
||||
let expr = WithSpan::new(Self::BinOp(op, Box::new(expr), Box::new(rhs)), start);
|
||||
|
||||
if let Some((op2, _)) = opt(right).parse_next(i)? {
|
||||
return Err(winnow::error::ErrMode::Cut(ErrorContext::new(
|
||||
format!(
|
||||
"comparison operators cannot be chained; \
|
||||
consider using explicit parentheses, e.g. `(_ {op} _) {op2} _`"
|
||||
),
|
||||
op,
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
expr_prec_layer!(bor, bxor, "bitor".value("|"));
|
||||
expr_prec_layer!(bxor, band, token_xor);
|
||||
expr_prec_layer!(band, shifts, token_bitand);
|
||||
|
@ -605,35 +605,6 @@ fn test_associativity() {
|
||||
))
|
||||
)],
|
||||
);
|
||||
assert_eq!(
|
||||
Ast::from_str("{{ a == b != c > d > e == f }}", None, &syntax)
|
||||
.unwrap()
|
||||
.nodes,
|
||||
vec![Node::Expr(
|
||||
Ws(None, None),
|
||||
WithSpan::no_span(Expr::BinOp(
|
||||
"==",
|
||||
Box::new(WithSpan::no_span(Expr::BinOp(
|
||||
">",
|
||||
Box::new(WithSpan::no_span(Expr::BinOp(
|
||||
">",
|
||||
Box::new(WithSpan::no_span(Expr::BinOp(
|
||||
"!=",
|
||||
Box::new(WithSpan::no_span(Expr::BinOp(
|
||||
"==",
|
||||
Box::new(WithSpan::no_span(Expr::Var("a"))),
|
||||
Box::new(WithSpan::no_span(Expr::Var("b")))
|
||||
))),
|
||||
Box::new(WithSpan::no_span(Expr::Var("c")))
|
||||
))),
|
||||
Box::new(WithSpan::no_span(Expr::Var("d")))
|
||||
))),
|
||||
Box::new(WithSpan::no_span(Expr::Var("e")))
|
||||
))),
|
||||
Box::new(WithSpan::no_span(Expr::Var("f")))
|
||||
))
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1423,3 +1394,26 @@ fn there_is_no_digit_two_in_a_binary_integer() {
|
||||
assert!(Ast::from_str("{{ 0o9 }}", None, &syntax).is_err());
|
||||
assert!(Ast::from_str("{{ 0xg }}", None, &syntax).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn comparison_operators_cannot_be_chained() {
|
||||
const OPS: &[&str] = &["==", "!=", ">=", ">", "<=", "<"];
|
||||
|
||||
let syntax = Syntax::default();
|
||||
for op1 in OPS {
|
||||
assert!(Ast::from_str(&format!("{{{{ a {op1} b }}}}"), None, &syntax).is_ok());
|
||||
for op2 in OPS {
|
||||
assert!(Ast::from_str(&format!("{{{{ a {op1} b {op2} c }}}}"), None, &syntax).is_err());
|
||||
for op3 in OPS {
|
||||
assert!(
|
||||
Ast::from_str(
|
||||
&format!("{{{{ a {op1} b {op2} c {op3} d }}}}"),
|
||||
None,
|
||||
&syntax,
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
49
testing/tests/ui/comparator-chaining.rs
Normal file
49
testing/tests/ui/comparator-chaining.rs
Normal file
@ -0,0 +1,49 @@
|
||||
// Comparison operators cannot be chained, so our parser must reject chained comparisons.
|
||||
|
||||
use askama::Template;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "txt", source = "{{ a == b != c }}")]
|
||||
struct EqNe {
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "txt", source = "{{ a <= b < c }}")]
|
||||
struct Between {
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "txt", source = "{{ ((a == b) == c) == d == e }}")]
|
||||
struct ThreeTimesOk {
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
d: usize,
|
||||
e: usize,
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(ext = "txt", source = "{{ a == (b == (c == d == e)) }}")]
|
||||
struct ThreeTimesOk2 {
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
d: usize,
|
||||
e: usize,
|
||||
}
|
||||
|
||||
// Regression test for <https://github.com/askama-rs/askama/issues/454>
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
ext = "",
|
||||
source = "\u{c}{{vu7218/63e3666663-666/3330e633/63e3666663666/3333<c\"}\u{1}2}\0\"<c7}}2\"\"\"\"\0\0\0\0"
|
||||
)]
|
||||
struct Regression {}
|
||||
|
||||
fn main() {}
|
39
testing/tests/ui/comparator-chaining.stderr
Normal file
39
testing/tests/ui/comparator-chaining.stderr
Normal file
@ -0,0 +1,39 @@
|
||||
error: comparison operators cannot be chained; consider using explicit parentheses, e.g. `(_ == _) != _`
|
||||
--> <source attribute>:1:5
|
||||
"== b != c }}"
|
||||
--> tests/ui/comparator-chaining.rs:6:34
|
||||
|
|
||||
6 | #[template(ext = "txt", source = "{{ a == b != c }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: comparison operators cannot be chained; consider using explicit parentheses, e.g. `(_ <= _) < _`
|
||||
--> <source attribute>:1:5
|
||||
"<= b < c }}"
|
||||
--> tests/ui/comparator-chaining.rs:14:34
|
||||
|
|
||||
14 | #[template(ext = "txt", source = "{{ a <= b < c }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: comparison operators cannot be chained; consider using explicit parentheses, e.g. `(_ == _) == _`
|
||||
--> <source attribute>:1:19
|
||||
"== d == e }}"
|
||||
--> tests/ui/comparator-chaining.rs:22:34
|
||||
|
|
||||
22 | #[template(ext = "txt", source = "{{ ((a == b) == c) == d == e }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: comparison operators cannot be chained; consider using explicit parentheses, e.g. `(_ == _) == _`
|
||||
--> <source attribute>:1:17
|
||||
"== d == e)) }}"
|
||||
--> tests/ui/comparator-chaining.rs:32:34
|
||||
|
|
||||
32 | #[template(ext = "txt", source = "{{ a == (b == (c == d == e)) }}")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: comparison operators cannot be chained; consider using explicit parentheses, e.g. `(_ < _) < _`
|
||||
--> <source attribute>:1:52
|
||||
"<c\"}\u{1}2}\0\"<c7}}2\"\"\"\"\0\0\0\0"
|
||||
--> tests/ui/comparator-chaining.rs:45:14
|
||||
|
|
||||
45 | source = "\u{c}{{vu7218/63e3666663-666/3330e633/63e3666663666/3333<c\"}\u{1}2}\0\"<c7}}2\"\"\"\"\0\0\0\0"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
@ -96,7 +96,7 @@ struct SmallSelf3 {
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
ext = "",
|
||||
source = "{{\u{c}KK3e331<c7}}61/63m3333u7<c0.}}\u{6}\0\u{c}\u{c}{{c/crate<338<c7}}6unsafe/63a3ae\u{c}\u{c}\u{c}%et"
|
||||
source = "{{\u{c}KK3e331<c7}}61/63m3333u7<c0.}}\u{6}\0\u{c}\u{c}{{c/crate<338}}6unsafe/63a3ae\u{c}\u{c}\u{c}%et"
|
||||
)]
|
||||
struct Regression {}
|
||||
|
||||
|
@ -168,11 +168,11 @@ error: `self` cannot be used as an identifier
|
||||
|
||||
error: `crate` cannot be used as an identifier
|
||||
--> <source attribute>:1:41
|
||||
"crate<338<c7}}6unsafe/63a3ae\u{c}\u{c}\u{c}%et"
|
||||
"crate<338}}6unsafe/63a3ae\u{c}\u{c}\u{c}%et"
|
||||
--> tests/ui/crate_identifier.rs:99:14
|
||||
|
|
||||
99 | source = "{{\u{c}KK3e331<c7}}61/63m3333u7<c0.}}\u{6}\0\u{c}\u{c}{{c/crate<338<c7}}6unsafe/63a3ae\u{c}\u{c}\u{c}%et"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
99 | source = "{{\u{c}KK3e331<c7}}61/63m3333u7<c0.}}\u{6}\0\u{c}\u{c}{{c/crate<338}}6unsafe/63a3ae\u{c}\u{c}\u{c}%et"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `super` cannot be used as an identifier
|
||||
--> <source attribute>:1:27
|
||||
|
Loading…
x
Reference in New Issue
Block a user