Skip to content

Commit 32b8083

Browse files
committed
factor out parts of the fuzzers into separate files
1 parent 53e7a7f commit 32b8083

File tree

4 files changed

+79
-74
lines changed

4 files changed

+79
-74
lines changed

fuzz/fuzz_targets/object_cache.rs

+6-73
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,14 @@
11
#![no_main]
22
mod fuzzing_utils;
33
mod make_tree;
4+
mod pick_node;
5+
mod serialized_len;
46

5-
use clvmr::serde::{node_to_bytes, serialized_length, treehash, ObjectCache};
6-
use clvmr::{Allocator, NodePtr, SExp};
7+
use clvmr::serde::{serialized_length, treehash, ObjectCache};
8+
use clvmr::Allocator;
79
use fuzzing_utils::tree_hash;
810
use libfuzzer_sys::fuzz_target;
9-
use std::collections::hash_map::Entry;
10-
use std::collections::HashMap;
11-
use std::collections::HashSet;
12-
13-
enum Op {
14-
Cons(NodePtr),
15-
Traverse(NodePtr),
16-
}
17-
18-
fn compute_serialized_len(a: &Allocator, n: NodePtr) -> u64 {
19-
let mut stack: Vec<u64> = vec![];
20-
let mut op_stack = vec![Op::Traverse(n)];
21-
let mut cache = HashMap::<NodePtr, u64>::new();
22-
23-
while let Some(op) = op_stack.pop() {
24-
match op {
25-
Op::Cons(node) => {
26-
let right = stack.pop().expect("internal error, empty stack");
27-
let left = stack.pop().expect("internal error, empty stack");
28-
match cache.entry(node) {
29-
Entry::Occupied(e) => stack.push(*e.get()),
30-
Entry::Vacant(e) => {
31-
e.insert(1 + left + right);
32-
stack.push(1 + left + right);
33-
}
34-
}
35-
}
36-
Op::Traverse(node) => match cache.entry(node) {
37-
Entry::Occupied(e) => stack.push(*e.get()),
38-
Entry::Vacant(e) => match a.sexp(node) {
39-
SExp::Pair(left, right) => {
40-
op_stack.push(Op::Cons(node));
41-
op_stack.push(Op::Traverse(left));
42-
op_stack.push(Op::Traverse(right));
43-
}
44-
SExp::Atom => {
45-
let ser_len = node_to_bytes(a, node)
46-
.expect("internal error, failed to serialize")
47-
.len() as u64;
48-
e.insert(ser_len);
49-
stack.push(ser_len);
50-
}
51-
},
52-
},
53-
}
54-
}
55-
assert_eq!(stack.len(), 1);
56-
*stack.last().expect("internal error, empty stack")
57-
}
58-
59-
fn pick_node(a: &Allocator, root: NodePtr, mut node_idx: i32) -> NodePtr {
60-
let mut stack = vec![root];
61-
let mut seen_node = HashSet::<NodePtr>::new();
62-
63-
while let Some(node) = stack.pop() {
64-
if node_idx == 0 {
65-
return node;
66-
}
67-
if !seen_node.insert(node) {
68-
continue;
69-
}
70-
node_idx -= 1;
71-
if let SExp::Pair(left, right) = a.sexp(node) {
72-
stack.push(left);
73-
stack.push(right);
74-
}
75-
}
76-
NodePtr::NIL
77-
}
11+
use serialized_len::compute_serialized_len;
7812

7913
fuzz_target!(|data: &[u8]| {
8014
let mut unstructured = arbitrary::Unstructured::new(data);
@@ -86,8 +20,7 @@ fuzz_target!(|data: &[u8]| {
8620
let mut length_cache = ObjectCache::new(serialized_length);
8721

8822
let node_idx = unstructured.int_in_range(0..=node_count).unwrap_or(5) as i32;
89-
90-
let node = pick_node(&allocator, tree, node_idx);
23+
let node = pick_node::pick_node(&allocator, tree, node_idx);
9124

9225
let expect_hash = tree_hash(&allocator, node);
9326
let expect_len = compute_serialized_len(&allocator, node);

fuzz/fuzz_targets/pick_node.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use clvmr::{Allocator, NodePtr, SExp};
2+
use std::collections::HashSet;
3+
4+
pub fn pick_node(a: &Allocator, root: NodePtr, mut node_idx: i32) -> NodePtr {
5+
let mut stack = vec![root];
6+
let mut seen_node = HashSet::<NodePtr>::new();
7+
8+
while let Some(node) = stack.pop() {
9+
if node_idx == 0 {
10+
return node;
11+
}
12+
if !seen_node.insert(node) {
13+
continue;
14+
}
15+
node_idx -= 1;
16+
if let SExp::Pair(left, right) = a.sexp(node) {
17+
stack.push(left);
18+
stack.push(right);
19+
}
20+
}
21+
NodePtr::NIL
22+
}

fuzz/fuzz_targets/serialized_len.rs

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use clvmr::serde::node_to_bytes;
2+
use clvmr::{Allocator, NodePtr, SExp};
3+
use std::collections::hash_map::Entry;
4+
use std::collections::HashMap;
5+
6+
enum Op {
7+
Cons(NodePtr),
8+
Traverse(NodePtr),
9+
}
10+
11+
pub fn compute_serialized_len(a: &Allocator, n: NodePtr) -> u64 {
12+
let mut stack: Vec<u64> = vec![];
13+
let mut op_stack = vec![Op::Traverse(n)];
14+
let mut cache = HashMap::<NodePtr, u64>::new();
15+
16+
while let Some(op) = op_stack.pop() {
17+
match op {
18+
Op::Cons(node) => {
19+
let right = stack.pop().expect("internal error, empty stack");
20+
let left = stack.pop().expect("internal error, empty stack");
21+
match cache.entry(node) {
22+
Entry::Occupied(e) => stack.push(*e.get()),
23+
Entry::Vacant(e) => {
24+
e.insert(1 + left + right);
25+
stack.push(1 + left + right);
26+
}
27+
}
28+
}
29+
Op::Traverse(node) => match cache.entry(node) {
30+
Entry::Occupied(e) => stack.push(*e.get()),
31+
Entry::Vacant(e) => match a.sexp(node) {
32+
SExp::Pair(left, right) => {
33+
op_stack.push(Op::Cons(node));
34+
op_stack.push(Op::Traverse(left));
35+
op_stack.push(Op::Traverse(right));
36+
}
37+
SExp::Atom => {
38+
let ser_len = node_to_bytes(a, node)
39+
.expect("internal error, failed to serialize")
40+
.len() as u64;
41+
e.insert(ser_len);
42+
stack.push(ser_len);
43+
}
44+
},
45+
},
46+
}
47+
}
48+
assert_eq!(stack.len(), 1);
49+
*stack.last().expect("internal error, empty stack")
50+
}

src/serde/ser_br.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub fn node_to_stream_backrefs<W: io::Write>(
6363
}
6464
},
6565
}
66-
while !read_op_stack.is_empty() && read_op_stack[read_op_stack.len() - 1] == ReadOp::Cons {
66+
while let Some(ReadOp::Cons) = read_op_stack.last() {
6767
read_op_stack.pop();
6868
read_cache_lookup.pop2_and_cons();
6969
}

0 commit comments

Comments
 (0)