mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-02 23:35:07 +00:00
parser: reject illegal raw identifiers in attribute access
This commit is contained in:
parent
76b26cd5fa
commit
3f380721a2
@ -42,61 +42,47 @@ struct Allowed {
|
|||||||
|
|
||||||
fn check_expr<'a>(expr: &WithSpan<'a, Expr<'a>>, allowed: Allowed) -> Result<(), ParseErr<'a>> {
|
fn check_expr<'a>(expr: &WithSpan<'a, Expr<'a>>, allowed: Allowed) -> Result<(), ParseErr<'a>> {
|
||||||
match &expr.inner {
|
match &expr.inner {
|
||||||
Expr::Var(name) => {
|
&Expr::Var(name) => {
|
||||||
// List can be found in rust compiler "can_be_raw" function (although in our case, it's
|
// List can be found in rust compiler "can_be_raw" function (although in our case, it's
|
||||||
// also used in cases like `match`, so `self` is allowed in this case).
|
// also used in cases like `match`, so `self` is allowed in this case).
|
||||||
if (!allowed.super_keyword && *name == "super") || matches!(*name, "crate" | "Self") {
|
if (!allowed.super_keyword && name == "super") || matches!(name, "crate" | "Self") {
|
||||||
Err(winnow::error::ErrMode::Cut(ErrorContext::new(
|
Err(err_reserved_identifier(name))
|
||||||
format!("`{name}` cannot be used as an identifier"),
|
} else if !allowed.underscore && name == "_" {
|
||||||
expr.span,
|
Err(err_underscore_identifier(name))
|
||||||
)))
|
|
||||||
} else if !allowed.underscore && *name == "_" {
|
|
||||||
Err(winnow::error::ErrMode::Cut(ErrorContext::new(
|
|
||||||
"reserved keyword `_` cannot be used here",
|
|
||||||
expr.span,
|
|
||||||
)))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::IsDefined(var) | Expr::IsNotDefined(var) => {
|
&Expr::IsDefined(var) | &Expr::IsNotDefined(var) => {
|
||||||
if *var == "_" {
|
if var == "_" {
|
||||||
Err(winnow::error::ErrMode::Cut(ErrorContext::new(
|
Err(err_underscore_identifier(var))
|
||||||
"reserved keyword `_` cannot be used here",
|
|
||||||
expr.span,
|
|
||||||
)))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Path(path) => {
|
Expr::Path(path) => {
|
||||||
if let [name] = path.as_slice() {
|
if let &[name] = path.as_slice() {
|
||||||
if !crate::can_be_variable_name(name) {
|
if !crate::can_be_variable_name(name) {
|
||||||
return Err(winnow::error::ErrMode::Cut(ErrorContext::new(
|
return Err(err_reserved_identifier(name));
|
||||||
format!("`{name}` cannot be used as an identifier"),
|
|
||||||
*name,
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Expr::BoolLit(_)
|
|
||||||
| Expr::NumLit(_, _)
|
|
||||||
| Expr::StrLit(_)
|
|
||||||
| Expr::CharLit(_)
|
|
||||||
| Expr::Attr(_, _)
|
|
||||||
| Expr::Filter(_)
|
|
||||||
| Expr::NamedArgument(_, _)
|
|
||||||
| Expr::RustMacro(_, _)
|
|
||||||
| Expr::Try(_)
|
|
||||||
| Expr::FilterSource
|
|
||||||
| Expr::LetCond(_) => Ok(()),
|
|
||||||
Expr::Array(elems) | Expr::Tuple(elems) | Expr::Concat(elems) => {
|
Expr::Array(elems) | Expr::Tuple(elems) | Expr::Concat(elems) => {
|
||||||
for elem in elems {
|
for elem in elems {
|
||||||
check_expr(elem, allowed)?;
|
check_expr(elem, allowed)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Expr::Attr(elem, attr) => {
|
||||||
|
if attr.name == "_" {
|
||||||
|
Err(err_underscore_identifier(attr.name))
|
||||||
|
} else if !crate::can_be_variable_name(attr.name) {
|
||||||
|
Err(err_reserved_identifier(attr.name))
|
||||||
|
} else {
|
||||||
|
check_expr(elem, Allowed::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
Expr::Index(elem1, elem2) | Expr::BinOp(_, elem1, elem2) => {
|
Expr::Index(elem1, elem2) | Expr::BinOp(_, elem1, elem2) => {
|
||||||
check_expr(elem1, Allowed::default())?;
|
check_expr(elem1, Allowed::default())?;
|
||||||
check_expr(elem2, Allowed::default())
|
check_expr(elem2, Allowed::default())
|
||||||
@ -130,9 +116,33 @@ fn check_expr<'a>(expr: &WithSpan<'a, Expr<'a>>, allowed: Allowed) -> Result<(),
|
|||||||
"unreachable",
|
"unreachable",
|
||||||
expr.span,
|
expr.span,
|
||||||
))),
|
))),
|
||||||
|
Expr::BoolLit(_)
|
||||||
|
| Expr::NumLit(_, _)
|
||||||
|
| Expr::StrLit(_)
|
||||||
|
| Expr::CharLit(_)
|
||||||
|
| Expr::Filter(_)
|
||||||
|
| Expr::NamedArgument(_, _)
|
||||||
|
| Expr::RustMacro(_, _)
|
||||||
|
| Expr::Try(_)
|
||||||
|
| Expr::FilterSource
|
||||||
|
| Expr::LetCond(_) => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn err_underscore_identifier(name: &str) -> winnow::error::ErrMode<ErrorContext<'_>> {
|
||||||
|
winnow::error::ErrMode::Cut(ErrorContext::new(
|
||||||
|
"reserved keyword `_` cannot be used here",
|
||||||
|
name,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn err_reserved_identifier(name: &str) -> winnow::error::ErrMode<ErrorContext<'_>> {
|
||||||
|
winnow::error::ErrMode::Cut(ErrorContext::new(
|
||||||
|
format!("`{name}` cannot be used as an identifier"),
|
||||||
|
name,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Expr<'a> {
|
pub enum Expr<'a> {
|
||||||
BoolLit(bool),
|
BoolLit(bool),
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
˙˙˙{{crate.4}}˙˙˙˙e˙
|
@ -148,4 +148,32 @@ struct PathElemSelfType2 {
|
|||||||
a: u8,
|
a: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(ext = "html", source = "{{ Self.4 }}")]
|
||||||
|
struct InvalidRawIdentifierSelfTyInAttr1;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(ext = "html", source = "{{ super.4 }}")]
|
||||||
|
struct InvalidRawIdentifierSuperInAttr1;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(ext = "html", source = "{{ crate.4 }}")]
|
||||||
|
struct InvalidRawIdentifierCrateInAttr1;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(ext = "html", source = "{{ self.Self.4 }}")]
|
||||||
|
struct InvalidRawIdentifierSelfTyInAttr2;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(ext = "html", source = "{{ self.super.4 }}")]
|
||||||
|
struct InvalidRawIdentifierSuperInAttr2;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(ext = "html", source = "{{ self.crate.4 }}")]
|
||||||
|
struct InvalidRawIdentifierCrateInAttr2;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(ext = "html", source = "{{ self.self.4 }}")]
|
||||||
|
struct InvalidRawIdentifierSelfInAttr;
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -237,3 +237,59 @@ error: `Self` cannot be used as an identifier
|
|||||||
|
|
|
|
||||||
146 | #[template(ext = "html", source = "{% match a %}{% when self::a::b::Self %}{% endmatch %}")]
|
146 | #[template(ext = "html", source = "{% match a %}{% when self::a::b::Self %}{% endmatch %}")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `Self` cannot be used as an identifier
|
||||||
|
--> <source attribute>:1:3
|
||||||
|
"Self.4 }}"
|
||||||
|
--> tests/ui/crate_identifier.rs:152:35
|
||||||
|
|
|
||||||
|
152 | #[template(ext = "html", source = "{{ Self.4 }}")]
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `super` cannot be used as an identifier
|
||||||
|
--> <source attribute>:1:3
|
||||||
|
"super.4 }}"
|
||||||
|
--> tests/ui/crate_identifier.rs:156:35
|
||||||
|
|
|
||||||
|
156 | #[template(ext = "html", source = "{{ super.4 }}")]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `crate` cannot be used as an identifier
|
||||||
|
--> <source attribute>:1:3
|
||||||
|
"crate.4 }}"
|
||||||
|
--> tests/ui/crate_identifier.rs:160:35
|
||||||
|
|
|
||||||
|
160 | #[template(ext = "html", source = "{{ crate.4 }}")]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `Self` cannot be used as an identifier
|
||||||
|
--> <source attribute>:1:8
|
||||||
|
"Self.4 }}"
|
||||||
|
--> tests/ui/crate_identifier.rs:164:35
|
||||||
|
|
|
||||||
|
164 | #[template(ext = "html", source = "{{ self.Self.4 }}")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `super` cannot be used as an identifier
|
||||||
|
--> <source attribute>:1:8
|
||||||
|
"super.4 }}"
|
||||||
|
--> tests/ui/crate_identifier.rs:168:35
|
||||||
|
|
|
||||||
|
168 | #[template(ext = "html", source = "{{ self.super.4 }}")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `crate` cannot be used as an identifier
|
||||||
|
--> <source attribute>:1:8
|
||||||
|
"crate.4 }}"
|
||||||
|
--> tests/ui/crate_identifier.rs:172:35
|
||||||
|
|
|
||||||
|
172 | #[template(ext = "html", source = "{{ self.crate.4 }}")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `self` cannot be used as an identifier
|
||||||
|
--> <source attribute>:1:8
|
||||||
|
"self.4 }}"
|
||||||
|
--> tests/ui/crate_identifier.rs:176:35
|
||||||
|
|
|
||||||
|
176 | #[template(ext = "html", source = "{{ self.self.4 }}")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
Loading…
x
Reference in New Issue
Block a user