pub fn sink_reachability_analysis(
graph: &SqliteGraph,
sources: &[i64],
sinks: &[i64],
) -> Result<AHashMap<i64, Vec<i64>>, SqliteGraphError>Expand description
Performs sink reachability analysis for all sinks.
Analyzes each sink to determine which taint sources can reach it. Returns a mapping of vulnerable sinks to their affecting sources.
§Arguments
graph- The graph to analyzesources- Source node IDs where taint originatessinks- Sink node IDs to analyze
§Returns
HashMap mapping vulnerable sink -> Vec<affecting_sources> Only includes sinks that have at least one affecting source.
§Complexity
- Time: O(Sinks × (V + E)) - one backward BFS per sink
- Space: O(V) for ancestors set (per sink)
§Algorithm
- Initialize result = empty HashMap
- For each sink:
- Call propagate_taint_backward(graph, sink, sources)
- If result.sources is non-empty (vulnerable):
- Add entry: sink -> Vec<affecting_sources>
- Return result mapping
§Example
ⓘ
use sqlitegraph::{SqliteGraph, algo::sink_reachability_analysis};
let graph = SqliteGraph::open_in_memory()?;
// ... build graph with sources and sinks ...
let sources = vec![1, 2, 3]; // User input nodes
let sinks = vec![10, 20, 30]; // SQL query nodes
let vulnerabilities = sink_reachability_analysis(&graph, &sources, &sinks)?;
if vulnerabilities.is_empty() {
println!("No vulnerabilities found!");
} else {
println!("Found {} vulnerable sinks:", vulnerabilities.len());
for (sink, affecting_sources) in vulnerabilities {
println!(" Sink {} is reachable from sources: {:?}", sink, affecting_sources);
}
}