Skip to content

Commit

Permalink
add fuzzer for Allocator, specifically handling of atom, small_number…
Browse files Browse the repository at this point in the history
… and number
  • Loading branch information
arvidn committed Feb 13, 2024
1 parent 52d56b2 commit 11f63e8
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
6 changes: 6 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,9 @@ name = "operators"
path = "fuzz_targets/operators.rs"
test = false
doc = false

[[bin]]
name = "allocator"
path = "fuzz_targets/allocator.rs"
test = false
doc = false
54 changes: 54 additions & 0 deletions fuzz/fuzz_targets/allocator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#![no_main]
use libfuzzer_sys::fuzz_target;

use clvmr::{Allocator, NodePtr};

fn run_tests(a: &mut Allocator, atom1: NodePtr, data: &[u8]) {
assert_eq!(a.atom(atom1).as_ref(), data);
assert_eq!(a.atom_len(atom1), data.len());

let canonical = data != [0]
&& (data.len() < 2 || data[0] != 0 || (data[1] & 0x80) != 0)
&& (data.len() < 2 || data[0] != 0xff || (data[1] & 0x80) == 0);

// small_number
if let Some(val) = a.small_number(atom1) {
let atom2 = a.new_small_number(val).expect("new_small_number()");
assert_eq!(a.atom(atom1), a.atom(atom2));
assert_eq!(a.atom(atom2).as_ref(), data);
assert!(a.atom_eq(atom1, atom2));
assert_eq!(a.number(atom1), val.into());
assert_eq!(a.number(atom2), val.into());
assert_eq!(a.atom_len(atom2), data.len());
assert!(canonical);
}

// number
let val = a.number(atom1);

let atom3 = a.new_number(val.clone()).expect("new_number()");

assert_eq!(a.number(atom3), val);
// if the atom is not in canonical integer form we don't expect it to stay
// the same once we "launder" it through a BigInt.
if !canonical {
assert!(a.atom(atom3).as_ref() != data);
assert!(a.atom_len(atom3) < data.len());
assert!(!a.atom_eq(atom1, atom3));
} else {
assert_eq!(a.atom(atom3).as_ref(), data);
assert_eq!(a.atom_len(atom3), data.len());
assert!(a.atom_eq(atom1, atom3));
}
}

fuzz_target!(|data: &[u8]| {
let mut a = Allocator::new();
let atom1 = a.new_atom(data).expect("new_atom()");
run_tests(&mut a, atom1, data);

let atom1 = a
.new_concat(data.len(), &[a.nil(), atom1, a.nil()])
.expect("new_concat()");
run_tests(&mut a, atom1, data);
});
4 changes: 3 additions & 1 deletion src/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,9 @@ fn test_concat_launder_small_number() {

// this "launders" the small number into actually being allocated on the
// heap
let atom2 = a.new_concat(1, &[atom1]).expect("new_substr");
let atom2 = a
.new_concat(1, &[a.nil(), atom1, a.nil()])
.expect("new_substr");

// even though this atom is allocated on the heap (and not stored as a small
// int), we can still retrieve it as one. The CLVM interpreter depends on
Expand Down

0 comments on commit 11f63e8

Please sign in to comment.