agentshield/parser/python/
defs.rs1use std::collections::HashSet;
2use std::path::Path;
3
4use crate::analysis::cross_file::{SanitizerCategory, sanitizer_category, sanitizer_label};
5use crate::parser::{FunctionDef, FunctionParam, ParsedFile};
6
7use super::classify::{loc, sanitized_var_marker};
8use super::patterns::{FUNC_DEF_RE, HTTP_CLIENT_CTX_RE, SANITIZER_ASSIGN_RE};
9
10pub(crate) fn collect_sanitizer_vars(content: &str, parsed: &mut ParsedFile) {
11 for cap in SANITIZER_ASSIGN_RE.captures_iter(content) {
12 let var_name = &cap[1];
13 let func_name = &cap[2];
14 if sanitizer_category(func_name)
15 .is_some_and(|category| !matches!(category, SanitizerCategory::Redaction))
16 {
17 parsed.sanitized_vars.insert(var_name.to_string());
18 if let Some(label) = sanitizer_label(func_name) {
19 parsed
20 .sanitized_vars
21 .insert(sanitized_var_marker(var_name, &label));
22 }
23 }
24 }
25}
26
27pub(crate) fn collect_function_defs_and_params(
28 content: &str,
29 file_path: &Path,
30 parsed: &mut ParsedFile,
31) -> HashSet<String> {
32 let mut param_names = HashSet::new();
33 for cap in FUNC_DEF_RE.captures_iter(content) {
34 let func_name = &cap[1];
35 let params_str = &cap[2];
36 let is_exported = !func_name.starts_with('_');
38 let func_line = content[..cap.get(0).map(|m| m.start()).unwrap_or(0)]
39 .lines()
40 .count()
41 + 1;
42 let function_location = loc(file_path, func_line);
43
44 let mut func_params = Vec::new();
45 for param in params_str.split(',') {
46 let param = param.trim().split(':').next().unwrap_or("").trim();
47 let param = param.split('=').next().unwrap_or("").trim();
48 if !param.is_empty() && param != "self" && param != "cls" {
49 param_names.insert(param.to_string());
50 func_params.push(param.to_string());
51 parsed.function_params.push(FunctionParam {
52 function_name: func_name.to_string(),
53 param_name: param.to_string(),
54 location: function_location.clone(),
55 });
56 }
57 }
58
59 parsed.function_defs.push(FunctionDef {
60 name: func_name.to_string(),
61 params: func_params,
62 is_exported,
63 location: function_location,
64 });
65 }
66 param_names
67}
68
69pub(crate) fn collect_http_client_vars(content: &str) -> HashSet<String> {
70 let mut http_client_vars = HashSet::new();
71 for cap in HTTP_CLIENT_CTX_RE.captures_iter(content) {
72 http_client_vars.insert(cap[1].to_string());
73 }
74 http_client_vars
75}