1#![no_main]
2use libfuzzer_sys::fuzz_target;
3use onestore::{ExGuid, ObjectData, PropertySets, RevisionIndex, Store, Value, create_section};
4fuzz_target!(|input: &[u8]| {
5 let count = input.first().copied().unwrap_or(0) as usize % 32;
6 let entries: Vec<_> = (0..count)
7 .map(|i| (format!("section-{i}.one"), [i as u8 + 1; 16]))
8 .collect();
9 let sections: Vec<_> = entries
10 .iter()
11 .map(|(name, id)| (name.as_str(), *id))
12 .collect();
13 let toc = onestore::create_table_of_contents("Open Notebook.onetoc2", &sections).unwrap();
14 let store = Store::parse(&toc).unwrap();
15 assert!(store.checksum_mismatches.is_empty());
16 let index = RevisionIndex::parse(&store).unwrap();
17 index.validate_current().unwrap();
18 let revision = index
19 .resolve(
20 index.root,
21 index.spaces[&index.root].labels[&(ExGuid::default(), 1)],
22 )
23 .unwrap();
24 assert_eq!(
25 revision.objects[&revision.roots[&1]]
26 .references()
27 .unwrap()
28 .objects
29 .len(),
30 count
31 );
32 let Ok(text) = std::str::from_utf8(input) else {
33 return;
34 };
35 let result = create_section("synthetic.one", text, "Fuzz author");
36 if text.contains(['\0', '\n']) {
37 assert!(result.is_err());
38 return;
39 }
40 let bytes = result.unwrap();
41 let store = Store::parse(&bytes).unwrap();
42 assert!(store.checksum_mismatches.is_empty());
43 let index = RevisionIndex::parse(&store).unwrap();
44 index.validate_current().unwrap();
45 let expected: Vec<_> = text
46 .encode_utf16()
47 .chain([0])
48 .flat_map(u16::to_le_bytes)
49 .collect();
50 let mut found = 0;
51 for (osid, space) in &index.spaces {
52 let revision = index
53 .resolve(*osid, space.labels[&(ExGuid::default(), 1)])
54 .unwrap();
55 for object in revision
56 .objects
57 .values()
58 .filter(|object| object.jcid == 0x6000e)
59 {
60 let ObjectData::Properties(data) = object.data else {
61 panic!()
62 };
63 assert!(
64 PropertySets::parse(data).unwrap().sets[0]
65 .iter()
66 .any(|p| p.id == 0x1c001c22 && p.value == Value::Bytes(&expected))
67 );
68 found += 1;
69 }
70 }
71 assert_eq!(found, 1);
72});