Skip to content

Commit 74cf811

Browse files
authored
Adding Bellman Ford Fuzz targets (#1427)
Added a check to test the principle that for undirected non-negative weights, Bellman Ford and Dijkstra's algorithm must produce the same shortest distance. Next, will start on adding fuzz targets for connectivity and generator modules.
1 parent 9900471 commit 74cf811

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

rustworkx-core/fuzz/Cargo.toml

+7
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,10 @@ path = "fuzz_targets/test_fuzz_dijkstra.rs"
2727
test = false
2828
doc = false
2929
bench = false
30+
31+
[[bin]]
32+
name = "test_fuzz_bellman_ford"
33+
path = "fuzz_targets/test_fuzz_bellman_ford.rs"
34+
test = false
35+
doc = false
36+
bench = false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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::{bellman_ford, dijkstra};
10+
use rustworkx_core::Result;
11+
12+
#[derive(Debug, Arbitrary)]
13+
struct FuzzGraph {
14+
edges: Vec<(usize, usize, u32)>,
15+
node_count: usize,
16+
}
17+
18+
fuzz_target!(|data: &[u8]| {
19+
if let Ok(input) = FuzzGraph::arbitrary(&mut Unstructured::new(data)) {
20+
fuzz_check_bellman_vs_dijkstra(&input);
21+
}
22+
});
23+
24+
fn fuzz_check_bellman_vs_dijkstra(input: &FuzzGraph) {
25+
if input.node_count == 0 || input.edges.is_empty() || input.node_count > 1000 {
26+
return;
27+
}
28+
29+
let node_count = input.node_count.min(512);
30+
31+
let mut graph = Graph::<(), i32, Undirected>::new_undirected();
32+
let mut nodes = Vec::with_capacity(node_count);
33+
for _ in 0..node_count {
34+
nodes.push(graph.add_node(()));
35+
}
36+
37+
for &(u, v, w) in &input.edges {
38+
if u < node_count && v < node_count {
39+
let safe_weight = (w % 10_000) as i32;
40+
graph.add_edge(nodes[u], nodes[v], safe_weight);
41+
}
42+
}
43+
44+
let start_node = nodes[0];
45+
46+
let bf_res: Result<Option<DictMap<NodeIndex, i32>>> =
47+
bellman_ford(&graph, start_node, |e| Ok(*e.weight()), None);
48+
49+
let dijk_res: Result<DictMap<NodeIndex, i32>> =
50+
dijkstra(&graph, start_node, None, |e| Ok(*e.weight()), None);
51+
52+
match (bf_res, dijk_res) {
53+
(Ok(Some(bf_map)), Ok(dijk_map)) => {
54+
assert_eq!(
55+
bf_map, dijk_map,
56+
"Mismatch between Bellman-Ford and Dijkstra"
57+
);
58+
}
59+
(Ok(None), _) => {
60+
panic!("Bellman-Ford returned None (negative cycle) on non-negative-weight graph");
61+
}
62+
(Err(e), _) | (_, Err(e)) => {
63+
panic!("Fuzzing caused an unexpected error: {e:?}");
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)