use tldr_core::{Language, TaintSinkType};
#[path = "common/integ_helpers.rs"]
mod common;
use common::analyze_with_ssa;
#[test]
fn python_os_spawnl_to_user_input_via_compute_taint() {
let src = "\
import os
def handler():
cmd = input()
os.spawnl(os.P_WAIT, '/bin/sh', '-c', cmd)
";
let result = analyze_with_ssa(src, Language::Python, "handler", false);
let sink_lines: Vec<_> = result
.sinks
.iter()
.filter(|s| matches!(s.sink_type, TaintSinkType::ShellExec))
.map(|s| s.line)
.collect();
assert!(
!sink_lines.is_empty(),
"expected at least one ShellExec sink for os.spawnl; got sinks={:?}",
result.sinks
);
}
#[test]
fn python_os_spawnle_via_compute_taint() {
let src = "\
import os
def handler():
cmd = input()
os.spawnle(os.P_WAIT, '/bin/sh', cmd, {})
";
let result = analyze_with_ssa(src, Language::Python, "handler", false);
let sink_lines: Vec<_> = result
.sinks
.iter()
.filter(|s| matches!(s.sink_type, TaintSinkType::ShellExec))
.map(|s| s.line)
.collect();
assert!(
!sink_lines.is_empty(),
"expected at least one ShellExec sink for os.spawnle; got sinks={:?}",
result.sinks
);
}
#[test]
fn python_os_spawnlp_via_compute_taint() {
let src = "\
import os
def handler():
cmd = input()
os.spawnlp(os.P_WAIT, 'sh', '-c', cmd)
";
let result = analyze_with_ssa(src, Language::Python, "handler", false);
let sink_lines: Vec<_> = result
.sinks
.iter()
.filter(|s| matches!(s.sink_type, TaintSinkType::ShellExec))
.map(|s| s.line)
.collect();
assert!(
!sink_lines.is_empty(),
"expected at least one ShellExec sink for os.spawnlp; got sinks={:?}",
result.sinks
);
}
#[test]
fn python_os_spawnv_via_compute_taint() {
let src = "\
import os
def handler():
cmd = input()
os.spawnv(os.P_WAIT, '/bin/sh', ['-c', cmd])
";
let result = analyze_with_ssa(src, Language::Python, "handler", false);
let sink_lines: Vec<_> = result
.sinks
.iter()
.filter(|s| matches!(s.sink_type, TaintSinkType::ShellExec))
.map(|s| s.line)
.collect();
assert!(
!sink_lines.is_empty(),
"expected at least one ShellExec sink for os.spawnv; got sinks={:?}",
result.sinks
);
}
#[test]
fn python_os_spawnvp_via_compute_taint() {
let src = "\
import os
def handler():
cmd = input()
os.spawnvp(os.P_WAIT, 'sh', ['sh', '-c', cmd])
";
let result = analyze_with_ssa(src, Language::Python, "handler", false);
let sink_lines: Vec<_> = result
.sinks
.iter()
.filter(|s| matches!(s.sink_type, TaintSinkType::ShellExec))
.map(|s| s.line)
.collect();
assert!(
!sink_lines.is_empty(),
"expected at least one ShellExec sink for os.spawnvp; got sinks={:?}",
result.sinks
);
}
#[test]
fn python_os_spawnvpe_via_compute_taint() {
let src = "\
import os
def handler():
cmd = input()
os.spawnvpe(os.P_WAIT, 'sh', ['sh', '-c', cmd], {})
";
let result = analyze_with_ssa(src, Language::Python, "handler", false);
let sink_lines: Vec<_> = result
.sinks
.iter()
.filter(|s| matches!(s.sink_type, TaintSinkType::ShellExec))
.map(|s| s.line)
.collect();
assert!(
!sink_lines.is_empty(),
"expected at least one ShellExec sink for os.spawnvpe; got sinks={:?}",
result.sinks
);
}
#[test]
fn ruby_io_popen_module_call_via_compute_taint() {
let src = "\
def handler
cmd = gets
IO.popen(cmd)
end
";
let result = analyze_with_ssa(src, Language::Ruby, "handler", false);
let sink_lines: Vec<_> = result
.sinks
.iter()
.filter(|s| matches!(s.sink_type, TaintSinkType::ShellExec))
.map(|s| s.line)
.collect();
assert!(
!sink_lines.is_empty(),
"expected at least one ShellExec sink for IO.popen; got sinks={:?}",
result.sinks
);
}
#[test]
fn elixir_system_cmd_module_call_via_compute_taint() {
let src = "\
def handler do
cmd = IO.gets(\"$ \")
System.cmd(cmd, [])
end
";
let result = analyze_with_ssa(src, Language::Elixir, "handler", false);
let sink_lines: Vec<_> = result
.sinks
.iter()
.filter(|s| matches!(s.sink_type, TaintSinkType::ShellExec))
.map(|s| s.line)
.collect();
assert!(
!sink_lines.is_empty(),
"expected at least one ShellExec sink for System.cmd; got sinks={:?}",
result.sinks
);
}