pub fn propagate_taint_forward(
graph: &SqliteGraph,
sources: &[i64],
sinks: &[i64],
) -> Result<TaintResult, SqliteGraphError>Expand description
Propagates taint forward from sources to find reachable sinks.
Computes all nodes reachable from taint sources and identifies which security-sensitive sinks are reachable (vulnerabilities).
§Arguments
graph- The graph to analyzesources- Source node IDs where taint originatessinks- Sink node IDs to check for taint reachability
§Returns
TaintResult containing:
- All nodes tainted by sources (forward reachable)
- Which sinks are reachable (vulnerabilities)
- Source-sink paths that represent vulnerabilities
§Complexity
- Time: O(S × (V + E) + S × Sinks × (V + E)) where S = sources count
- O(V + E) per source for forward reachability
- O(V + E) per source-sink pair for path validation
- Space: O(V) for tainted nodes set
§Algorithm
- Initialize tainted_nodes = empty set
- For each source:
- Compute forward reachability using reachable_from()
- Extend tainted_nodes with reachable nodes
- Compute sinks_reached = sinks ∩ tainted_nodes
- Build source_sink_paths:
- For each source and sink pair, check can_reach(source, sink)
- If true, add (source, sink) to paths
- Return TaintResult with size = tainted_nodes.len()
§Example
ⓘ
use sqlitegraph::{SqliteGraph, algo::propagate_taint_forward};
let graph = SqliteGraph::open_in_memory()?;
// ... build graph with sources and sinks ...
let sources = vec![1, 2]; // User input nodes
let sinks = vec![10, 20]; // SQL query nodes
let result = propagate_taint_forward(&graph, &sources, &sinks)?;
if result.has_vulnerability() {
println!("Found {} vulnerabilities", result.source_sink_paths.len());
for (source, sink) in result.sorted_vulnerabilities() {
println!(" Source {} can reach sink {}", source, sink);
}
}