Skip to content

Commit 9900471

Browse files
authored
Adding new fuzz targets (#1425)
Starting off with a triangle inequality check for Dijkstra's Algorithm. Thinking about adding one more target for shortest path and then move to other modules.
1 parent 08c21ec commit 9900471

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

rustworkx-core/fuzz/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,10 @@ path = "fuzz_targets/test_traversal_node_coverage.rs"
2020
test = false
2121
doc = false
2222
bench = false
23+
24+
[[bin]]
25+
name = "test_fuzz_dijkstra"
26+
path = "fuzz_targets/test_fuzz_dijkstra.rs"
27+
test = false
28+
doc = false
29+
bench = false
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#![no_main]
2+
3+
use arbitrary::{Arbitrary, Unstructured};
4+
use libfuzzer_sys::fuzz_target;
5+
use rustworkx_core::dictmap::DictMap;
6+
use rustworkx_core::petgraph::graph::Graph;
7+
use rustworkx_core::petgraph::prelude::*;
8+
use rustworkx_core::petgraph::Undirected;
9+
use rustworkx_core::shortest_path::dijkstra;
10+
use rustworkx_core::Result;
11+
12+
#[derive(Debug, Arbitrary)]
13+
struct FuzzGraph {
14+
edges: Vec<(usize, usize, usize)>,
15+
node_count: usize,
16+
}
17+
18+
fuzz_target!(|data: &[u8]| {
19+
if let Ok(fuzz_input) = FuzzGraph::arbitrary(&mut Unstructured::new(data)) {
20+
fuzz_check_dijkstra_triangle_inequality(&fuzz_input);
21+
}
22+
});
23+
24+
fn fuzz_check_dijkstra_triangle_inequality(input: &FuzzGraph) {
25+
if input.node_count == 0
26+
|| input.edges.is_empty()
27+
|| input.node_count > 1000
28+
|| input.edges.len() > 10_000
29+
{
30+
return;
31+
}
32+
let mut graph = Graph::<(), usize, Undirected>::new_undirected();
33+
let mut nodes = Vec::with_capacity(input.node_count);
34+
for _ in 0..input.node_count {
35+
nodes.push(graph.add_node(()));
36+
}
37+
38+
for &(u, v, w) in &input.edges {
39+
if u < input.node_count && v < input.node_count && w > 0 {
40+
graph.add_edge(nodes[u], nodes[v], w);
41+
}
42+
}
43+
44+
let start_node = nodes[0];
45+
46+
let res: Result<DictMap<NodeIndex, usize>> =
47+
dijkstra(&graph, start_node, None, |e| Ok(*e.weight()), None);
48+
49+
let dist_map = res.unwrap();
50+
51+
for edge in graph.edge_references() {
52+
let u = edge.source();
53+
let v = edge.target();
54+
let w = *edge.weight();
55+
56+
if let (Some(&du), Some(&dv)) = (dist_map.get(&u), dist_map.get(&v)) {
57+
if let Some(bound) = du.checked_add(w) {
58+
assert!(
59+
dv <= bound,
60+
"Triangle inequality failed: dist[{v:?}] = {dv}, dist[{u:?}] = {du}, w = {w}"
61+
);
62+
}
63+
64+
if let Some(bound) = dv.checked_add(w) {
65+
assert!(
66+
du <= bound,
67+
"Triangle inequality failed: dist[{u:?}] = {du}, dist[{v:?}] = {dv}, w = {w}"
68+
);
69+
}
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)