mirror of
https://github.com/SpaceManiac/SpacemanDMM.git
synced 2025-12-23 05:36:47 +00:00
Implement compile time warning for datum[] (#397)
Lummox recently made this a RUNTIME error, but also irrespective of that this tends to mask HELL vars[] security holes. We really should be linting for it. I had to implement operator overloading support for the builtin parser, which was far more annoying then I expected. Bit scuffed, but it works. (I am unsure of how to parse for "" though so I left that unimplemented) This will likely throw errors on most codebases, I'm unsure of how to handle that.
This commit is contained in:
parent
660457818e
commit
70176ca27d
4 changed files with 122 additions and 1 deletions
|
|
@ -50,6 +50,7 @@ Raised by DreamChecker:
|
|||
* `control_condition_static` - Raised on a control condition such as `if`/`while` having a static condition such as `1` or `"string"`
|
||||
* `if_condition_determinate` - Raised on if condition being always true or always false
|
||||
* `loop_condition_determinate` - Raised on loop condition such as in `for` being always true or always false
|
||||
* `improper_index` - Raised on accessing a non list with []
|
||||
|
||||
Raised by Lexer:
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use syn::*;
|
|||
struct Header {
|
||||
attrs: Vec<Attribute>,
|
||||
path: Vec<Ident>,
|
||||
operator_overload_target: Option<String>,
|
||||
}
|
||||
|
||||
impl Header {
|
||||
|
|
@ -24,7 +25,110 @@ impl Header {
|
|||
input.parse::<Token![/]>()?;
|
||||
self.path.push(Ident::parse_any(input)?);
|
||||
}
|
||||
if let Some(final_ident) = self.path.last() {
|
||||
// If we find an operator{some token}() pattern we allow the some token part
|
||||
if final_ident == "operator" {
|
||||
self.parse_operator(input)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_operator(&mut self, input: ParseStream) -> Result<()> {
|
||||
let text_token: Option<&str> = if input.parse::<Token![%]>().is_ok() {
|
||||
if input.parse::<Token![%]>().is_ok() {
|
||||
Some("%%")
|
||||
} else if input.parse::<Token![%=]>().is_ok() {
|
||||
Some("%%=")
|
||||
} else {
|
||||
Some("%")
|
||||
}
|
||||
} else if input.parse::<Token![&]>().is_ok() {
|
||||
Some("&")
|
||||
} else if input.parse::<Token![&=]>().is_ok() {
|
||||
Some("&=")
|
||||
} else if input.parse::<Token![*]>().is_ok() {
|
||||
if input.parse::<Token![*]>().is_ok() {
|
||||
Some("**")
|
||||
} else {
|
||||
Some("*")
|
||||
}
|
||||
} else if input.parse::<Token![*=]>().is_ok() {
|
||||
Some("*=")
|
||||
} else if input.parse::<Token![/]>().is_ok() {
|
||||
Some("/")
|
||||
} else if input.parse::<Token![/=]>().is_ok() {
|
||||
Some("/=")
|
||||
} else if input.parse::<Token![+]>().is_ok() {
|
||||
if input.parse::<Token![+]>().is_ok() {
|
||||
Some("++")
|
||||
} else {
|
||||
Some("+")
|
||||
}
|
||||
} else if input.parse::<Token![+=]>().is_ok() {
|
||||
Some("+=")
|
||||
} else if input.parse::<Token![-]>().is_ok() {
|
||||
if input.parse::<Token![-]>().is_ok() {
|
||||
Some("--")
|
||||
} else {
|
||||
Some("-")
|
||||
}
|
||||
} else if input.parse::<Token![-=]>().is_ok() {
|
||||
Some("-=")
|
||||
} else if input.parse::<Token![<]>().is_ok() {
|
||||
Some("<")
|
||||
} else if input.parse::<Token![<<]>().is_ok() {
|
||||
Some("<<")
|
||||
} else if input.parse::<Token![<<=]>().is_ok() {
|
||||
Some("<<=")
|
||||
} else if input.parse::<Token![<=]>().is_ok() {
|
||||
Some("<=")
|
||||
} else if input.parse::<Token![>=]>().is_ok() {
|
||||
Some(">=")
|
||||
} else if input.parse::<Token![>>]>().is_ok() {
|
||||
Some(">>")
|
||||
} else if input.parse::<Token![>>=]>().is_ok() {
|
||||
Some(">>=")
|
||||
} else if input.parse::<Token![^]>().is_ok() {
|
||||
Some("^")
|
||||
} else if input.parse::<Token![^=]>().is_ok() {
|
||||
Some("^=")
|
||||
} else if input.parse::<Token![|]>().is_ok() {
|
||||
Some("|")
|
||||
} else if input.parse::<Token![|=]>().is_ok() {
|
||||
Some("|=")
|
||||
} else if input.parse::<Token![~]>().is_ok() {
|
||||
if input.parse::<Token![=]>().is_ok() {
|
||||
Some("~=")
|
||||
} else {
|
||||
Some("~")
|
||||
}
|
||||
} else if input.parse::<Token![~]>().is_ok() {
|
||||
Some("~")
|
||||
} else if input.peek(Token![:]) && input.peek2(Token![=]) {
|
||||
input.parse::<Token![:]>()?;
|
||||
input.parse::<Token![=]>()?;
|
||||
Some(":=")
|
||||
} else if self.brackets_next(input).is_ok() {
|
||||
if input.parse::<Token![=]>().is_ok() {
|
||||
Some("[]=")
|
||||
} else {
|
||||
Some("[]")
|
||||
}
|
||||
} else {
|
||||
// Todo: Implement operator""() support. Unsure how to expect an empty string
|
||||
None
|
||||
};
|
||||
if let Some(text) = text_token {
|
||||
self.operator_overload_target = Some(text.to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn brackets_next(&mut self, input: ParseStream) -> Result<()> {
|
||||
// Sorry
|
||||
let _bracket_dummy;
|
||||
bracketed!(_bracket_dummy in input);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -143,7 +247,11 @@ pub fn builtins_table(input: TokenStream) -> TokenStream {
|
|||
let mut output = Vec::new();
|
||||
for entry in builtins {
|
||||
let span = entry.header.path.first().unwrap().span();
|
||||
let lit_strs: Vec<_> = entry.header.path.into_iter().map(|x| LitStr::new(&x.to_string(), x.span())).collect();
|
||||
let mut lit_strs: Vec<_> = entry.header.path.into_iter().map(|x| LitStr::new(&x.to_string(), x.span())).collect();
|
||||
if let Some(operator) = entry.header.operator_overload_target {
|
||||
let last_entry = lit_strs.pop().unwrap();
|
||||
lit_strs.push(LitStr::new((last_entry.value() + operator.as_str()).as_str(), last_entry.span()));
|
||||
}
|
||||
let path = quote! {
|
||||
&[ #(#lit_strs),* ]
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2105,6 +2105,14 @@ impl<'o, 's> AnalyzeProc<'o, 's> {
|
|||
}
|
||||
res
|
||||
},
|
||||
StaticType::Type(typeref) => {
|
||||
if typeref.get_proc("operator[]").is_none() {
|
||||
error(location, format!("invalid list access on {}", typeref.path))
|
||||
.with_errortype("improper_index")
|
||||
.register(self.context);
|
||||
}
|
||||
lhs.clone()
|
||||
},
|
||||
_ => lhs.clone() // carry through fix_hint
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -626,6 +626,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) {
|
|||
list/var/const/parent_type;
|
||||
list/var/tag;
|
||||
list/var/const/list/vars;
|
||||
list/proc/operator[]();
|
||||
list/proc/Add(Item1, Item2/*,...*/);
|
||||
list/proc/Copy(Start=1, End=0);
|
||||
list/proc/Cut(Start=1, End=0);
|
||||
|
|
@ -642,6 +643,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) {
|
|||
alist/var/const/type;
|
||||
alist/var/const/parent_type;
|
||||
alist/var/tag;
|
||||
alist/proc/operator[]();
|
||||
alist/proc/Add(Item1, Item2/*,...*/);
|
||||
alist/proc/Copy(Start=1, End=0);
|
||||
alist/proc/Cut(Start=1, End=0);
|
||||
|
|
@ -1110,6 +1112,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) {
|
|||
savefile/var/list/dir;
|
||||
savefile/var/eof;
|
||||
savefile/var/name;
|
||||
savefile/proc/operator[]();
|
||||
savefile/proc/ExportText(/* path=cd, file */);
|
||||
savefile/proc/Flush();
|
||||
savefile/proc/ImportText(/* path=cd, file */);
|
||||
|
|
@ -1282,6 +1285,7 @@ pub fn register_builtins(tree: &mut ObjectTreeBuilder) {
|
|||
vector/var/y;
|
||||
vector/var/z;
|
||||
|
||||
vector/proc/operator[]();
|
||||
vector/proc/Cross(B);
|
||||
vector/proc/Dot(B);
|
||||
vector/proc/Interpolate(B, t);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue