Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion implants/lib/eldritchv2/eldritch-macros/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ fn is_interpreter_type(ty: &Type) -> bool {
fn generate_args_parsing(sig: &Signature) -> Result<(TokenStream, TokenStream), syn::Error> {
let mut parsing = Vec::new();
let mut call_args = Vec::new();
let mut param_names_str = Vec::new();
let mut arg_idx = 0usize;

for input in &sig.inputs {
Expand All @@ -204,6 +205,7 @@ fn generate_args_parsing(sig: &Signature) -> Result<(TokenStream, TokenStream),
}

let arg_name_str = quote!(#pat).to_string();
param_names_str.push(arg_name_str.clone());

// Detect &str
let is_str_ref = if let Type::Reference(TypeReference { elem, .. }) = &**ty {
Expand All @@ -216,6 +218,13 @@ fn generate_args_parsing(sig: &Signature) -> Result<(TokenStream, TokenStream),
false
};

// Add validation for multiple values (positional AND keyword)
parsing.push(quote! {
if #arg_idx < _eldritch_args.len() && _eldritch_kwargs.contains_key(#arg_name_str) {
return Err(alloc::format!("TypeError: Function got multiple values for argument '{}'", #arg_name_str));
}
});

if is_str_ref {
parsing.push(quote! {
let #pat: alloc::string::String = if #arg_idx < _eldritch_args.len() {
Expand Down Expand Up @@ -250,5 +259,43 @@ fn generate_args_parsing(sig: &Signature) -> Result<(TokenStream, TokenStream),
}
}

Ok((quote! { #(#parsing)* }, quote! { #(#call_args),* }))
// Validate argument counts and unexpected keywords
let max_pos = arg_idx;
let mut validation = Vec::new();

validation.push(quote! {
if _eldritch_args.len() > #max_pos {
return Err(alloc::format!("TypeError: Function got too many arguments. Expected {}, got {}", #max_pos, _eldritch_args.len()));
}
});

// Validate keywords - handle empty case
if param_names_str.is_empty() {
validation.push(quote! {
if !_eldritch_kwargs.is_empty() {
// Get first key to report
let key = _eldritch_kwargs.keys().next().unwrap();
return Err(alloc::format!("TypeError: Function got an unexpected keyword argument '{}'", key));
}
});
} else {
validation.push(quote! {
for key in _eldritch_kwargs.keys() {
let is_valid = match key.as_str() {
#(#param_names_str)|* => true,
_ => false
};
if !is_valid {
return Err(alloc::format!("TypeError: Function got an unexpected keyword argument '{}'", key));
}
}
});
}

// Prepend validation to parsing logic
let mut final_parsing = Vec::new();
final_parsing.extend(validation);
final_parsing.push(quote! { #(#parsing)* });

Ok((quote! { #(#final_parsing)* }, quote! { #(#call_args),* }))
}
Empty file.