Skip to main content

propagate_taint_forward

Function propagate_taint_forward 

Source
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 analyze
  • sources - Source node IDs where taint originates
  • sinks - 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

  1. Initialize tainted_nodes = empty set
  2. For each source:
    • Compute forward reachability using reachable_from()
    • Extend tainted_nodes with reachable nodes
  3. Compute sinks_reached = sinks ∩ tainted_nodes
  4. Build source_sink_paths:
    • For each source and sink pair, check can_reach(source, sink)
    • If true, add (source, sink) to paths
  5. 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);
    }
}