refactor(dynamic): enhance Rust receiver construction with recursive dependency resolution, add Liquibase changelog context detection, and expand test coverage

This commit is contained in:
elipeter 2026-05-24 22:18:59 -05:00
parent acec041676
commit 8786d1b71e
6 changed files with 546 additions and 25 deletions

View file

@ -220,6 +220,20 @@ fn class_method_rust_uses_default_constructor() {
assert!(h.source.contains("instance.run"));
}
#[test]
fn class_method_rust_builds_recursive_receiver_literal() {
let mut spec = make_spec(Lang::Rust);
spec.entry_file = "tests/dynamic_fixtures/class_method/rust_recursive_deps/vuln.rs".into();
spec.sink_file = spec.entry_file.clone();
let h = lang::emit(&spec).expect("emit ok");
assert!(
h.source
.contains("entry::UserService { runner: entry::CommandRunner")
);
assert!(!h.source.contains("UserService::default()"));
assert!(!h.source.contains("UserService::new()"));
}
#[test]
fn class_method_c_collapses_to_class_underscore_method_symbol() {
let spec = make_spec(Lang::C);
@ -428,6 +442,17 @@ mod e2e_phase_19 {
cap: Cap::CODE_EXEC,
bins: &["cargo"],
},
Case {
lang: Lang::Rust,
fixture_dir: "rust_recursive_deps",
vuln_file: "vuln.rs",
benign_file: "benign.rs",
vuln_class: "UserService",
benign_class: "UserService",
method: "run",
cap: Cap::CODE_EXEC,
bins: &["cargo"],
},
Case {
lang: Lang::C,
fixture_dir: "c",

View file

@ -0,0 +1,23 @@
// Benign control for recursive Rust class-method receiver construction.
pub struct CommandRunner;
impl CommandRunner {
pub fn run(&self, input: &str) -> String {
let out = std::process::Command::new("true")
.arg(input)
.output()
.expect("exec");
String::from_utf8_lossy(&out.stdout).into_owned()
}
}
pub struct UserService {
pub runner: CommandRunner,
}
impl UserService {
pub fn run(&self, input: &str) -> String {
self.runner.run(input)
}
}

View file

@ -0,0 +1,26 @@
// Rust class-method fixture whose receiver has same-file dependencies
// but no Default or new() constructor.
pub struct CommandRunner;
impl CommandRunner {
pub fn run(&self, input: &str) -> String {
let cmd = format!("true {}", input);
let out = std::process::Command::new("sh")
.arg("-c")
.arg(&cmd)
.output()
.expect("exec");
String::from_utf8_lossy(&out.stdout).into_owned()
}
}
pub struct UserService {
pub runner: CommandRunner,
}
impl UserService {
pub fn run(&self, input: &str) -> String {
self.runner.run(input)
}
}